diff --git a/Cargo.lock b/Cargo.lock index e8d374c15df0a..18089c019f645 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "aes-gcm" -version = "0.10.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" +checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c" dependencies = [ "aead 0.5.2", "aes 0.8.2", @@ -172,19 +172,13 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" dependencies = [ "memchr", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -392,7 +386,7 @@ dependencies = [ "ark-serialize", "ark-std", "derivative", - "digest 0.10.7", + "digest 0.10.6", "itertools", "num-bigint", "num-traits", @@ -486,7 +480,7 @@ checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ "ark-serialize-derive", "ark-std", - "digest 0.10.7", + "digest 0.10.6", "num-bigint", ] @@ -790,9 +784,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "base64ct" @@ -851,7 +845,7 @@ dependencies = [ "lazy_static", "lazycell", "peeking_take_while", - "prettyplease 0.2.6", + "prettyplease 0.2.4", "proc-macro2", "quote", "regex", @@ -884,7 +878,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", ] [[package]] @@ -997,9 +991,9 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bstr" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" +checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" dependencies = [ "memchr", "once_cell", @@ -1018,9 +1012,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" [[package]] name = "byte-slice-cast" @@ -1132,9 +1126,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.2" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70d3ad08698a0568b0562f22710fe6bfc1f4a61a367c77d0398c562eadd453a" +checksum = "c8790cf1286da485c72cf5fc7aeba308438800036ec67d89425924c4807268c9" dependencies = [ "smallvec", ] @@ -1181,7 +1175,7 @@ name = "chain-spec-builder" version = "2.0.0" dependencies = [ "ansi_term", - "clap 4.3.2", + "clap 4.2.7", "node-cli", "rand 0.8.5", "sc-chain-spec", @@ -1192,13 +1186,13 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", + "num-integer", "num-traits", "time 0.1.45", "wasm-bindgen", @@ -1307,9 +1301,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.2" +version = "4.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "401a4694d2bf92537b6867d94de48c4842089645fdcdf6c71865b175d836e9c2" +checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938" dependencies = [ "clap_builder", "clap_derive", @@ -1318,31 +1312,31 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.1" +version = "4.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72394f3339a76daf211e57d4bcb374410f3965dcc606dd0e03738c7888766980" +checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd" dependencies = [ "anstream", "anstyle", "bitflags", - "clap_lex 0.5.0", + "clap_lex 0.4.1", "strsim", ] [[package]] name = "clap_complete" -version = "4.3.1" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6b5c519bab3ea61843a7923d074b04245624bb84a64a8c150f5deb014e388b" +checksum = "1a19591b2ab0e3c04b588a0e04ddde7b9eaa423646d1b4a8092879216bf47473" dependencies = [ - "clap 4.3.2", + "clap 4.2.7", ] [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" dependencies = [ "heck", "proc-macro2", @@ -1361,9 +1355,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" [[package]] name = "codespan-reporting" @@ -1383,9 +1377,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "comfy-table" -version = "7.0.0" +version = "7.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e1f7e5d046697d34b593bdba8ee31f4649366e452a2ccabb3baf3511e503d1" +checksum = "9ab77dbd8adecaf3f0db40581631b995f312a8a5ae3aa9993188bb8f23d83a5b" dependencies = [ "strum", "strum_macros", @@ -1409,15 +1403,15 @@ dependencies = [ [[package]] name = "console" -version = "0.15.7" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.45.0", + "windows-sys 0.42.0", ] [[package]] @@ -1815,9 +1809,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.95" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109308c20e8445959c2792e81871054c6a17e6976489a93d2769641a2ba5839c" +checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" dependencies = [ "cc", "cxxbridge-flags", @@ -1827,9 +1821,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.95" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf4c6755cdf10798b97510e0e2b3edb9573032bd9379de8fffa59d68165494f" +checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" dependencies = [ "cc", "codespan-reporting", @@ -1842,15 +1836,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.95" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882074421238e84fe3b4c65d0081de34e5b323bf64555d3e61991f76eb64a7bb" +checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" [[package]] name = "cxxbridge-macro" -version = "1.0.95" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a076022ece33e7686fb76513518e219cca4fce5750a8ae6d1ce6c0f48fd1af9" +checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote", @@ -1894,15 +1888,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" [[package]] name = "data-encoding-macro" -version = "0.1.13" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c904b33cc60130e1aeea4956ab803d08a3f4a0ca82d64ed757afac3891f2bb99" +checksum = "86927b7cd2fe88fa698b87404b287ab98d1a0063a34071d92e575b72d3029aca" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -1910,9 +1904,9 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.11" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fdf3fce3ce863539ec1d7fd1b6dcc3c645663376b43ed376bbf887733e4f772" +checksum = "a5bbed42daaa95e780b60a50546aa345b8413a1e46f9a40a12907d3598f038db" dependencies = [ "data-encoding", "syn 1.0.109", @@ -1931,9 +1925,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.6" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56acb310e15652100da43d130af8d97b509e95af61aab1c5a7939ef24337ee17" +checksum = "05e58dffcdcc8ee7b22f0c1f71a69243d7c2d9ad87b5a14361f2424a1565c219" dependencies = [ "const-oid", "zeroize", @@ -2063,9 +2057,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.7" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.4", "const-oid", @@ -2139,23 +2133,22 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "docify" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15aa210b350ff62db3149ac5d0b2a0287c01ee91354e16290de344082b2b3ff6" +checksum = "af1b04e6ef3d21119d3eb7b032bca17f99fe041e9c072f30f32cc0e1a2b1f3c4" dependencies = [ "docify_macros", ] [[package]] name = "docify_macros" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bf3504ed030133996c59a9954669a7a4f869f93a7e74389e16149843db16f57" +checksum = "8b5610df7f2acf89a1bb5d1a66ae56b1c7fcdcfe3948856fb3ace3f644d70eb7" dependencies = [ "common-path", "derive-syn-parse", "lazy_static", - "prettyplease 0.2.6", "proc-macro2", "quote", "regex", @@ -2223,16 +2216,15 @@ dependencies = [ [[package]] name = "ecdsa" -version = "0.16.7" +version = "0.16.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +checksum = "a48e5d537b8a30c0b023116d981b16334be1485af7ca68db3a2b7024cbc957fd" dependencies = [ - "der 0.7.6", - "digest 0.10.7", - "elliptic-curve 0.13.5", + "der 0.7.5", + "digest 0.10.6", + "elliptic-curve 0.13.4", "rfc6979 0.4.0", "signature 2.1.0", - "spki 0.7.2", ] [[package]] @@ -2287,7 +2279,7 @@ dependencies = [ "base16ct 0.1.1", "crypto-bigint 0.4.9", "der 0.6.1", - "digest 0.10.7", + "digest 0.10.6", "ff 0.12.1", "generic-array 0.14.7", "group 0.12.1", @@ -2302,13 +2294,13 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.5" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +checksum = "75c71eaa367f2e5d556414a8eea812bc62985c879748d6403edabd9cb03f16e7" dependencies = [ "base16ct 0.2.0", "crypto-bigint 0.5.2", - "digest 0.10.7", + "digest 0.10.6", "ff 0.13.0", "generic-array 0.14.7", "group 0.13.0", @@ -2586,9 +2578,9 @@ dependencies = [ [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ "percent-encoding", ] @@ -2643,7 +2635,7 @@ dependencies = [ "Inflector", "array-bytes 4.2.0", "chrono", - "clap 4.3.2", + "clap 4.2.7", "comfy-table", "frame-benchmarking", "frame-support", @@ -2734,7 +2726,7 @@ dependencies = [ name = "frame-election-solution-type-fuzzer" version = "2.0.0-alpha.5" dependencies = [ - "clap 4.3.2", + "clap 4.2.7", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-support", @@ -3002,9 +2994,9 @@ dependencies = [ [[package]] name = "fs4" -version = "0.6.5" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7672706608ecb74ab2e055c68327ffc25ae4cac1e12349204fd5fb0f3487cce2" +checksum = "a7f5b6908aecca5812a4569056285e58c666588c9573ee59765bf1d3692699e2" dependencies = [ "rustix 0.37.19", "windows-sys 0.48.0", @@ -3293,9 +3285,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21" dependencies = [ "bytes", "fnv", @@ -3318,9 +3310,9 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "handlebars" -version = "4.3.7" +version = "4.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c3372087601b532857d332f5957cbae686da52bb7810bf038c3e3c3cc2fa0d" +checksum = "035ef95d03713f2c347a72547b7cd38cbc9af7cd51e6099fb62d586d4a6dee3a" dependencies = [ "log", "pest", @@ -3440,7 +3432,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", ] [[package]] @@ -3547,22 +3539,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" -dependencies = [ - "http", - "hyper", - "log", - "rustls 0.20.8", - "rustls-native-certs", - "tokio", - "tokio-rustls 0.23.4", - "webpki-roots", -] - [[package]] name = "hyper-rustls" version = "0.24.0" @@ -3575,7 +3551,7 @@ dependencies = [ "rustls 0.21.1", "rustls-native-certs", "tokio", - "tokio-rustls 0.24.0", + "tokio-rustls", ] [[package]] @@ -3594,11 +3570,12 @@ dependencies = [ [[package]] name = "iana-time-zone-haiku" -version = "0.1.2" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" dependencies = [ - "cc", + "cxx", + "cxx-build", ] [[package]] @@ -3620,9 +3597,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -3716,14 +3693,13 @@ checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" [[package]] name = "indicatif" -version = "0.17.5" +version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ff8cc23a7393a397ed1d7f56e6365cba772aba9f9912ab968b03043c395d057" +checksum = "cef509aa9bc73864d6756f0d34d35504af3cf0844373afe9b8669a5b8005a729" dependencies = [ "console", - "instant", "number_prefix", - "portable-atomic", + "portable-atomic 0.3.20", "unicode-width", ] @@ -3775,9 +3751,9 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.11" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" dependencies = [ "hermit-abi 0.3.1", "libc", @@ -3846,18 +3822,18 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.63" +version = "0.3.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "68c16e1bfd491478ab155fd8b4896b86f9ede344949b641e61501e07c2b8b4d5" dependencies = [ "wasm-bindgen", ] [[package]] name = "jsonrpsee" -version = "0.16.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d291e3a5818a2384645fd9756362e6d89cf0541b0b916fa7702ea4a9833608e" +checksum = "e5f3783308bddc49d0218307f66a09330c106fbd792c58bac5c8dc294fdd0f98" dependencies = [ "jsonrpsee-core", "jsonrpsee-http-client", @@ -3870,37 +3846,33 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.16.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965de52763f2004bc91ac5bcec504192440f0b568a5d621c59d9dbd6f886c3fb" +checksum = "abc5630e4fa0096f00ec7b44d520701fda4504170cb85e22dca603ae5d7ad0d7" dependencies = [ "futures-util", "http", "jsonrpsee-core", - "jsonrpsee-types", "pin-project", "rustls-native-certs", "soketto", "thiserror", "tokio", - "tokio-rustls 0.23.4", + "tokio-rustls", "tokio-util", "tracing", - "webpki-roots", ] [[package]] name = "jsonrpsee-core" -version = "0.16.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" +checksum = "5aaa4c4d5fb801dcc316d81f76422db259809037a86b3194ae538dd026b05ed7" dependencies = [ "anyhow", - "arrayvec 0.7.2", "async-lock", "async-trait", "beef", - "futures-channel", "futures-timer", "futures-util", "globset", @@ -3914,33 +3886,34 @@ dependencies = [ "soketto", "thiserror", "tokio", + "tokio-stream", "tracing", ] [[package]] name = "jsonrpsee-http-client" -version = "0.16.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc345b0a43c6bc49b947ebeb936e886a419ee3d894421790c969cc56040542ad" +checksum = "aa7165efcbfbc951d180162ff28fe91b657ed81925e37a35e4a396ce12109f96" dependencies = [ "async-trait", "hyper", - "hyper-rustls 0.23.2", + "hyper-rustls", "jsonrpsee-core", "jsonrpsee-types", - "rustc-hash", "serde", "serde_json", "thiserror", "tokio", + "tower", "tracing", ] [[package]] name = "jsonrpsee-proc-macros" -version = "0.16.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baa6da1e4199c10d7b1d0a6e5e8bd8e55f351163b6f4b3cbb044672a69bd4c1c" +checksum = "21dc12b1d4f16a86e8c522823c4fab219c88c03eb7c924ec0501a64bf12e058b" dependencies = [ "heck", "proc-macro-crate", @@ -3951,13 +3924,11 @@ dependencies = [ [[package]] name = "jsonrpsee-server" -version = "0.16.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb69dad85df79527c019659a992498d03f8495390496da2f07e6c24c2b356fc" +checksum = "6e79d78cfd5abd8394da10753723093c3ff64391602941c9c4b1d80a3414fd53" dependencies = [ - "futures-channel", "futures-util", - "http", "hyper", "jsonrpsee-core", "jsonrpsee-types", @@ -3973,9 +3944,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.16.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd522fe1ce3702fd94812965d7bb7a3364b1c9aba743944c5a00529aae80f8c" +checksum = "00aa7cc87bc42e04e26c8ac3e7186142f7fd2949c763d9b6a7e64a69672d8fb2" dependencies = [ "anyhow", "beef", @@ -3987,9 +3958,9 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.16.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b83daeecfc6517cfe210df24e570fb06213533dfb990318fae781f4c7119dd9" +checksum = "5c71b2597ec1c958c6d5bc94bb61b44d74eb28e69dc421731ab0035706f13882" dependencies = [ "http", "jsonrpsee-client-transport", @@ -4004,8 +3975,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" dependencies = [ "cfg-if", - "ecdsa 0.16.7", - "elliptic-curve 0.13.5", + "ecdsa 0.16.6", + "elliptic-curve 0.13.4", "once_cell", "sha2 0.10.6", ] @@ -4192,9 +4163,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.145" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc86cde3ff845662b8f4ef6cb50ea0e20c524eb3d29ae048287e06a1b3fa6a81" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "libloading" @@ -4214,9 +4185,9 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libm" -version = "0.2.7" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libp2p" @@ -4758,9 +4729,9 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" [[package]] name = "lite-json" @@ -4782,9 +4753,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -4792,9 +4763,12 @@ dependencies = [ [[package]] name = "log" -version = "0.4.18" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] [[package]] name = "lru" @@ -4942,7 +4916,7 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", ] [[package]] @@ -5043,13 +5017,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", + "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "windows-sys 0.45.0", ] [[package]] @@ -5079,7 +5054,6 @@ dependencies = [ name = "mmr-rpc" version = "4.0.0-dev" dependencies = [ - "anyhow", "jsonrpsee", "parity-scale-codec", "serde", @@ -5158,7 +5132,7 @@ dependencies = [ "blake2s_simd", "blake3", "core2", - "digest 0.10.7", + "digest 0.10.6", "multihash-derive", "sha2 0.10.6", "sha3", @@ -5172,7 +5146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835d6ff01d610179fbce3de1694d007e500bf33a7f29689838941d6bf783ae40" dependencies = [ "core2", - "digest 0.10.7", + "digest 0.10.6", "multihash-derive", "sha2 0.10.6", "unsigned-varint", @@ -5345,7 +5319,7 @@ name = "node-bench" version = "0.9.0-dev" dependencies = [ "array-bytes 4.2.0", - "clap 4.3.2", + "clap 4.2.7", "derive_more", "fs_extra", "futures", @@ -5382,7 +5356,7 @@ version = "3.0.0-dev" dependencies = [ "array-bytes 4.2.0", "assert_cmd", - "clap 4.3.2", + "clap 4.2.7", "clap_complete", "criterion", "frame-benchmarking-cli", @@ -5509,7 +5483,7 @@ dependencies = [ name = "node-inspect" version = "0.9.0-dev" dependencies = [ - "clap 4.3.2", + "clap 4.2.7", "parity-scale-codec", "sc-cli", "sc-client-api", @@ -5568,7 +5542,7 @@ dependencies = [ name = "node-runtime-generate-bags" version = "3.0.0" dependencies = [ - "clap 4.3.2", + "clap 4.2.7", "generate-bags", "kitchensink-runtime", ] @@ -5577,7 +5551,7 @@ dependencies = [ name = "node-template" version = "4.0.0-dev" dependencies = [ - "clap 4.3.2", + "clap 4.2.7", "frame-benchmarking", "frame-benchmarking-cli", "frame-system", @@ -5623,7 +5597,7 @@ dependencies = [ name = "node-template-release" version = "3.0.0" dependencies = [ - "clap 4.3.2", + "clap 4.2.7", "flate2", "fs_extra", "glob", @@ -5822,7 +5796,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", - "libm 0.2.7", + "libm 0.2.6", ] [[package]] @@ -5843,9 +5817,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.30.4" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "crc32fast", "hashbrown 0.13.2", @@ -5873,9 +5847,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "oorandom" @@ -7742,7 +7716,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.7", ] [[package]] @@ -7761,15 +7735,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.2.16", "smallvec", - "windows-targets 0.48.0", + "windows-sys 0.45.0", ] [[package]] @@ -7799,7 +7773,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", ] [[package]] @@ -7828,9 +7802,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" @@ -7888,22 +7862,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.0" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 1.0.109", ] [[package]] @@ -7940,7 +7914,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.6", + "der 0.7.5", "spki 0.7.2", ] @@ -8032,14 +8006,23 @@ dependencies = [ "cfg-if", "cpufeatures", "opaque-debug 0.3.0", - "universal-hash 0.5.1", + "universal-hash 0.5.0", ] [[package]] name = "portable-atomic" -version = "1.3.3" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "767eb9f07d4a5ebcb39bbf2d452058a93c011373abf6832e24194a1c3f004794" +checksum = "e30165d31df606f5726b090ec7592c308a0eaf61721ff64c9a3018e344a8753e" +dependencies = [ + "portable-atomic 1.3.1", +] + +[[package]] +name = "portable-atomic" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bbda379e6e462c97ea6afe9f6233619b202bbc4968d7caa6917788d2070a044" [[package]] name = "ppv-lite86" @@ -8113,9 +8096,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.6" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b69d39aab54d069e7f2fe8cb970493e7834601ca2d8c65fd7bbd183578080d1" +checksum = "1ceca8aaf45b5c46ec7ed39fff75f57290368c1846d33d24a122ca81416ab058" dependencies = [ "proc-macro2", "syn 2.0.18", @@ -8576,13 +8559,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" dependencies = [ - "aho-corasick 1.0.2", + "aho-corasick 1.0.1", "memchr", - "regex-syntax 0.7.2", + "regex-syntax 0.7.1", ] [[package]] @@ -8602,9 +8585,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" [[package]] name = "resolv-conf" @@ -8770,9 +8753,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.14" +version = "0.36.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e4d67015953998ad0eb82887a0eb0129e18a7e2f3b7b0f6c422fddcd503d62" +checksum = "3a38f9520be93aba504e8ca974197f46158de5dcaa9fa04b57c57cd6a679d658" dependencies = [ "bitflags", "errno", @@ -8792,7 +8775,7 @@ dependencies = [ "errno", "io-lifetimes", "libc", - "linux-raw-sys 0.3.8", + "linux-raw-sys 0.3.7", "windows-sys 0.48.0", ] @@ -8851,7 +8834,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" dependencies = [ - "base64 0.21.2", + "base64 0.21.0", ] [[package]] @@ -9041,7 +9024,7 @@ version = "0.10.0-dev" dependencies = [ "array-bytes 4.2.0", "chrono", - "clap 4.3.2", + "clap 4.2.7", "fdlimit", "futures", "futures-timer", @@ -9565,7 +9548,7 @@ dependencies = [ "log", "parity-scale-codec", "paste", - "rustix 0.36.14", + "rustix 0.36.13", "sc-allocator", "sc-executor-common", "sc-runtime-test", @@ -9874,7 +9857,7 @@ dependencies = [ "futures", "futures-timer", "hyper", - "hyper-rustls 0.24.0", + "hyper-rustls", "lazy_static", "libp2p", "num_cpus", @@ -9946,6 +9929,7 @@ dependencies = [ "sp-version", "substrate-test-runtime-client", "tokio", + "tracing-subscriber 0.3.17", ] [[package]] @@ -9996,6 +9980,7 @@ dependencies = [ "sc-block-builder", "sc-chain-spec", "sc-client-api", + "sc-rpc", "sc-service", "sc-transaction-pool-api", "sc-utils", @@ -10013,6 +9998,7 @@ dependencies = [ "thiserror", "tokio", "tokio-stream", + "tracing-subscriber 0.3.17", ] [[package]] @@ -10169,7 +10155,7 @@ dependencies = [ name = "sc-storage-monitor" version = "0.1.0" dependencies = [ - "clap 4.3.2", + "clap 4.2.7", "fs4", "futures", "log", @@ -10341,9 +10327,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.7.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b569c32c806ec3abdf3b5869fb8bf1e0d275a7c1c9b0b05603d9464632649edf" +checksum = "dfdef77228a4c05dc94211441595746732131ad7f6530c6c18f045da7b7ab937" dependencies = [ "bitvec", "cfg-if", @@ -10468,7 +10454,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" dependencies = [ "base16ct 0.2.0", - "der 0.7.6", + "der 0.7.5", "generic-array 0.14.7", "pkcs8 0.10.2", "subtle", @@ -10504,9 +10490,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation", @@ -10517,9 +10503,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ "core-foundation-sys", "libc", @@ -10591,9 +10577,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d" +checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" dependencies = [ "serde", ] @@ -10619,7 +10605,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest 0.10.6", ] [[package]] @@ -10655,7 +10641,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest 0.10.6", ] [[package]] @@ -10664,7 +10650,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", "keccak", ] @@ -10698,7 +10684,7 @@ version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", "rand_core 0.6.4", ] @@ -10708,7 +10694,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", "rand_core 0.6.4", ] @@ -11211,7 +11197,7 @@ version = "9.0.0" dependencies = [ "blake2b_simd", "byteorder", - "digest 0.10.7", + "digest 0.10.6", "sha2 0.10.6", "sha3", "sp-std", @@ -11402,7 +11388,7 @@ dependencies = [ name = "sp-npos-elections-fuzzer" version = "2.0.0-alpha.5" dependencies = [ - "clap 4.3.2", + "clap 4.2.7", "honggfuzz", "parity-scale-codec", "rand 0.8.5", @@ -11802,7 +11788,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" dependencies = [ "base64ct", - "der 0.7.6", + "der 0.7.5", ] [[package]] @@ -11911,7 +11897,7 @@ dependencies = [ name = "subkey" version = "3.0.0" dependencies = [ - "clap 4.3.2", + "clap 4.2.7", "sc-cli", ] @@ -11954,7 +11940,7 @@ dependencies = [ name = "substrate-frame-cli" version = "4.0.0-dev" dependencies = [ - "clap 4.3.2", + "clap 4.2.7", "frame-support", "frame-system", "sc-cli", @@ -11999,6 +11985,7 @@ dependencies = [ "sp-runtime", "sp-tracing", "substrate-test-runtime-client", + "thiserror", "tokio", ] @@ -12043,6 +12030,7 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-trie", + "thiserror", "trie-db", ] @@ -12069,6 +12057,7 @@ dependencies = [ "sp-keystore", "sp-runtime", "sp-state-machine", + "tokio", ] [[package]] @@ -12200,7 +12189,7 @@ dependencies = [ "sp-maybe-compressed-blob", "strum", "tempfile", - "toml 0.7.4", + "toml 0.7.3", "walkdir", "wasm-opt", ] @@ -12256,9 +12245,9 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "d75182f12f490e953596550b65ee31bda7c8e043d9386174b353bda50838c3fd" dependencies = [ "bitflags", "core-foundation", @@ -12480,9 +12469,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.2" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f" dependencies = [ "autocfg", "bytes", @@ -12519,17 +12508,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.8", - "tokio", - "webpki 0.22.0", -] - [[package]] name = "tokio-rustls" version = "0.24.0" @@ -12591,9 +12569,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.4" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec" +checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" dependencies = [ "serde", "serde_spanned", @@ -12603,18 +12581,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.10" +version = "0.19.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" +checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" dependencies = [ "indexmap", "serde", @@ -12629,6 +12607,10 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite 0.2.9", "tower-layer", "tower-service", "tracing", @@ -12690,9 +12672,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", "valuable", @@ -12876,7 +12858,7 @@ version = "0.10.0-dev" dependencies = [ "assert_cmd", "async-trait", - "clap 4.3.2", + "clap 4.2.7", "frame-remote-externalities", "frame-try-runtime", "hex", @@ -12960,7 +12942,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", - "digest 0.10.7", + "digest 0.10.6", "rand 0.8.5", "static_assertions", ] @@ -12997,9 +12979,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-normalization" @@ -13034,9 +13016,9 @@ dependencies = [ [[package]] name = "universal-hash" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" dependencies = [ "crypto-common", "subtle", @@ -13062,12 +13044,12 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.4.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", - "idna 0.4.0", + "idna 0.3.0", "percent-encoding", ] @@ -13079,9 +13061,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.3.3" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" +checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2" dependencies = [ "getrandom 0.2.9", ] @@ -13124,7 +13106,7 @@ dependencies = [ "ark-serialize-derive", "arrayref", "constcat", - "digest 0.10.7", + "digest 0.10.6", "rand 0.8.5", "rand_chacha 0.3.1", "rand_core 0.6.4", @@ -13198,9 +13180,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "5b6cb788c4e39112fbe1822277ef6fb3c55cd86b95cb3d3c4c1c9597e4ac74b4" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -13208,9 +13190,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "35e522ed4105a9d626d885b35d62501b30d9666283a5c8be12c14a8bdafe7822" dependencies = [ "bumpalo", "log", @@ -13223,9 +13205,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.36" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" +checksum = "083abe15c5d88556b77bdf7aef403625be9e327ad37c62c4e4129af740168163" dependencies = [ "cfg-if", "js-sys", @@ -13235,9 +13217,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "358a79a0cb89d21db8120cbfb91392335913e4890665b1a7981d9e956903b434" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -13245,9 +13227,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "4783ce29f09b9d93134d41297aded3a712b7b979e9c6f28c32cb88c973a94869" dependencies = [ "proc-macro2", "quote", @@ -13258,15 +13240,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +checksum = "a901d592cafaa4d711bc324edfaff879ac700b19c3dfd60058d2b445be2691eb" [[package]] name = "wasm-encoder" -version = "0.29.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18c41dbd92eaebf3612a39be316540b8377c871cb9bde6b064af962984912881" +checksum = "d05d0b6fcd0aeb98adf16e7975331b3c17222aa815148f5b976370ce589d80ef" dependencies = [ "leb128", ] @@ -13369,7 +13351,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624e6333e861ef49095d2d678b76ebf30b06bf37effca845be7e5b87c90071b7" dependencies = [ "downcast-rs", - "libm 0.2.7", + "libm 0.2.6", "num-traits", "paste", ] @@ -13437,12 +13419,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c86437fa68626fe896e5afc69234bb2b5894949083586535f200385adfd71213" dependencies = [ "anyhow", - "base64 0.21.2", + "base64 0.21.0", "bincode", "directories-next", "file-per-thread-logger", "log", - "rustix 0.36.14", + "rustix 0.36.13", "serde", "sha2 0.10.6", "toml 0.5.11", @@ -13538,7 +13520,7 @@ checksum = "6e0554b84c15a27d76281d06838aed94e13a77d7bf604bbbaf548aa20eb93846" dependencies = [ "object", "once_cell", - "rustix 0.36.14", + "rustix 0.36.13", ] [[package]] @@ -13569,7 +13551,7 @@ dependencies = [ "memoffset 0.8.0", "paste", "rand 0.8.5", - "rustix 0.36.14", + "rustix 0.36.13", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-jit-debug", @@ -13590,9 +13572,9 @@ dependencies = [ [[package]] name = "wast" -version = "60.0.0" +version = "57.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd06cc744b536e30387e72a48fdd492105b9c938bb4f415c39c616a7a0a697ad" +checksum = "6eb0f5ed17ac4421193c7477da05892c2edafd67f9639e3c11a82086416662dc" dependencies = [ "leb128", "memchr", @@ -13602,18 +13584,18 @@ dependencies = [ [[package]] name = "wat" -version = "1.0.66" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5abe520f0ab205366e9ac7d3e6b2fc71de44e32a2b58f2ec871b6b575bdcea3b" +checksum = "ab9ab0d87337c3be2bb6fc5cd331c4ba9fd6bcb4ee85048a0dd59ed9ecf92e53" dependencies = [ "wast", ] [[package]] name = "web-sys" -version = "0.3.63" +version = "0.3.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +checksum = "16b5f940c7edfdc6d12126d98c9ef4d1b3d470011c47c76a6581df47ad9ba721" dependencies = [ "js-sys", "wasm-bindgen", @@ -13711,7 +13693,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "942be5bd85f072c3128396f6e5a9bfb93ca8c1939ded735d177b7bcba9a13d05" dependencies = [ "aes 0.6.0", - "aes-gcm 0.10.2", + "aes-gcm 0.10.1", "async-trait", "bincode", "block-modes", @@ -13870,9 +13852,9 @@ dependencies = [ [[package]] name = "wide" -version = "0.7.9" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0496a71f3cc6bc4bf0ed91346426a5099e93d89807e663162dc5a1069ff65" +checksum = "b689b6c49d6549434bf944e6b0f39238cf63693cb7a147e9d887507fffa3b223" dependencies = [ "bytemuck", "safe_arch", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index bab52f561afdb..392d0fc7aabd4 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -46,7 +46,7 @@ frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" } # These dependencies are used for the node template's RPCs -jsonrpsee = { version = "0.16.2", features = ["server"] } +jsonrpsee = { version = "0.19.0", features = ["server"] } sc-rpc = { version = "4.0.0-dev", path = "../../../client/rpc" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sc-rpc-api = { version = "0.10.0-dev", path = "../../../client/rpc-api" } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 197c0771c1c34..fe4e7d24b4418 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -39,7 +39,7 @@ array-bytes = "4.1" clap = { version = "4.2.5", features = ["derive"], optional = true } codec = { package = "parity-scale-codec", version = "3.6.1" } serde = { version = "1.0.163", features = ["derive"] } -jsonrpsee = { version = "0.16.2", features = ["server"] } +jsonrpsee = { version = "0.19.0", features = ["server"] } futures = "0.3.21" log = "0.4.17" rand = "0.8" diff --git a/bin/node/cli/benches/block_production.rs b/bin/node/cli/benches/block_production.rs index 527b145c62c46..11c49c6854715 100644 --- a/bin/node/cli/benches/block_production.rs +++ b/bin/node/cli/benches/block_production.rs @@ -93,6 +93,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { rpc_id_provider: Default::default(), rpc_max_subs_per_conn: Default::default(), rpc_port: 9944, + rpc_message_buffer_capacity: Default::default(), prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, diff --git a/bin/node/cli/benches/transaction_pool.rs b/bin/node/cli/benches/transaction_pool.rs index 44ebe1e7d4fe6..c9e7be67a5e17 100644 --- a/bin/node/cli/benches/transaction_pool.rs +++ b/bin/node/cli/benches/transaction_pool.rs @@ -87,6 +87,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { rpc_id_provider: Default::default(), rpc_max_subs_per_conn: Default::default(), rpc_port: 9944, + rpc_message_buffer_capacity: Default::default(), prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index 9f5d12e22d372..57e2471520535 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -13,7 +13,7 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee = { version = "0.16.2", features = ["server"] } +jsonrpsee = { version = "0.19.0", features = ["server"] } node-primitives = { version = "2.0.0", path = "../primitives" } pallet-transaction-payment-rpc = { version = "4.0.0-dev", path = "../../../frame/transaction-payment/rpc/" } mmr-rpc = { version = "4.0.0-dev", path = "../../../client/merkle-mountain-range/rpc/" } diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index 975f7638191ea..00010c491fee5 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -25,7 +25,7 @@ use crate::{ }, CliConfiguration, PrometheusParams, RuntimeParams, TelemetryParams, RPC_DEFAULT_MAX_CONNECTIONS, RPC_DEFAULT_MAX_REQUEST_SIZE_MB, RPC_DEFAULT_MAX_RESPONSE_SIZE_MB, - RPC_DEFAULT_MAX_SUBS_PER_CONN, + RPC_DEFAULT_MAX_SUBS_PER_CONN, RPC_DEFAULT_MESSAGE_CAPACITY_PER_CONN, }; use clap::Parser; use regex::Regex; @@ -87,7 +87,7 @@ pub struct RunCmd { #[arg(long, default_value_t = RPC_DEFAULT_MAX_RESPONSE_SIZE_MB)] pub rpc_max_response_size: u32, - /// Set the the maximum concurrent subscriptions per connection. + /// Set the maximum concurrent subscriptions per connection. #[arg(long, default_value_t = RPC_DEFAULT_MAX_SUBS_PER_CONN)] pub rpc_max_subscriptions_per_connection: u32, @@ -107,6 +107,17 @@ pub struct RunCmd { #[arg(long, value_name = "ORIGINS", value_parser = parse_cors)] pub rpc_cors: Option, + /// The number of messages the RPC server is allowed to keep in memory. + /// + /// If the buffer becomes full then the server will not process + /// new messages until the connected client start reading the + /// underlying messages. + /// + /// This applies per connection which includes both + /// JSON-RPC methods calls and subscriptions. + #[arg(long, default_value_t = RPC_DEFAULT_MESSAGE_CAPACITY_PER_CONN)] + pub rpc_message_buffer_capacity_per_connection: u32, + /// The human-readable name for this node. /// It's used as network node name. #[arg(long, value_name = "NAME")] @@ -365,6 +376,10 @@ impl CliConfiguration for RunCmd { Ok(self.rpc_max_subscriptions_per_connection) } + fn rpc_buffer_capacity_per_connection(&self) -> Result { + Ok(self.rpc_message_buffer_capacity_per_connection) + } + fn transaction_pool(&self, is_dev: bool) -> Result { Ok(self.pool_config.transaction_pool(is_dev)) } diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 04c62a73b40ed..5a42568e3c765 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -53,8 +53,11 @@ pub const RPC_DEFAULT_MAX_SUBS_PER_CONN: u32 = 1024; pub const RPC_DEFAULT_MAX_REQUEST_SIZE_MB: u32 = 15; /// The default max response size in MB. pub const RPC_DEFAULT_MAX_RESPONSE_SIZE_MB: u32 = 15; -/// The default number of connection.. +/// The default concurrent connection limit. pub const RPC_DEFAULT_MAX_CONNECTIONS: u32 = 100; +/// The default number of messages the RPC server +/// is allowed to keep in memory per connection. +pub const RPC_DEFAULT_MESSAGE_CAPACITY_PER_CONN: u32 = 64; /// Default configuration values used by Substrate /// @@ -346,6 +349,11 @@ pub trait CliConfiguration: Sized { Ok(RPC_DEFAULT_MAX_SUBS_PER_CONN) } + /// The number of messages the RPC server is allowed to keep in memory per connection. + fn rpc_buffer_capacity_per_connection(&self) -> Result { + Ok(RPC_DEFAULT_MESSAGE_CAPACITY_PER_CONN) + } + /// Get the prometheus configuration (`None` if disabled) /// /// By default this is `None`. @@ -518,6 +526,7 @@ pub trait CliConfiguration: Sized { rpc_id_provider: None, rpc_max_subs_per_conn: self.rpc_max_subscriptions_per_connection()?, rpc_port: DCV::rpc_listen_port(), + rpc_message_buffer_capacity: self.rpc_buffer_capacity_per_connection()?, prometheus_config: self .prometheus_config(DCV::prometheus_listen_port(), &chain_spec)?, telemetry_endpoints, diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index 7b534b37192ad..8b07dca9c7ed7 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -297,6 +297,7 @@ mod tests { rpc_id_provider: Default::default(), rpc_max_subs_per_conn: Default::default(), rpc_port: 9944, + rpc_message_buffer_capacity: Default::default(), prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index c0b20eb11c95a..5b48fe3a91c92 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee = { version = "0.16.2", features = ["client-core", "server", "macros"] } +jsonrpsee = { version = "0.19.0", features = ["client-core", "server", "macros"] } futures = "0.3.21" serde = { version = "1.0.163", features = ["derive"] } thiserror = "1.0" diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index 1ae15cc5453d7..118cff6cc980f 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -22,15 +22,15 @@ use std::{collections::HashMap, sync::Arc}; use futures::TryFutureExt; use jsonrpsee::{ - core::{async_trait, Error as JsonRpseeError, RpcResult}, + core::async_trait, proc_macros::rpc, - types::{error::CallError, ErrorObject}, + types::{ErrorObject, ErrorObjectOwned}, }; use serde::{Deserialize, Serialize}; use sc_consensus_babe::{authorship, BabeWorkerHandle}; use sc_consensus_epochs::Epoch as EpochT; -use sc_rpc_api::DenyUnsafe; +use sc_rpc_api::{DenyUnsafe, UnsafeRpcError}; use sp_api::ProvideRuntimeApi; use sp_application_crypto::AppCrypto; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; @@ -48,7 +48,7 @@ pub trait BabeApi { /// Returns data about which slots (primary or secondary) can be claimed in the current epoch /// with the keys in the keystore. #[method(name = "babe_epochAuthorship")] - async fn epoch_authorship(&self) -> RpcResult>; + async fn epoch_authorship(&self) -> Result, Error>; } /// Provides RPC methods for interacting with Babe. @@ -89,7 +89,7 @@ where C::Api: BabeRuntimeApi, SC: SelectChain + Clone + 'static, { - async fn epoch_authorship(&self) -> RpcResult> { + async fn epoch_authorship(&self) -> Result, Error> { self.deny_unsafe.check_if_safe()?; let best_header = self.select_chain.best_chain().map_err(Error::SelectChain).await?; @@ -147,7 +147,7 @@ where } /// Holds information about the `slot`'s that can be claimed by a given key. -#[derive(Default, Debug, Deserialize, Serialize)] +#[derive(Clone, Default, Debug, Deserialize, Serialize)] pub struct EpochAuthorship { /// the array of primary slots that can be claimed primary: Vec, @@ -166,20 +166,26 @@ pub enum Error { /// Failed to fetch epoch data. #[error("Failed to fetch epoch data")] FetchEpoch, + /// Consensus error + #[error(transparent)] + Consensus(#[from] ConsensusError), + /// Errors that can be formatted as a String + #[error("{0}")] + StringError(String), + /// Call to an unsafe RPC was denied. + #[error(transparent)] + UnsafeRpcCalled(#[from] UnsafeRpcError), } -impl From for JsonRpseeError { +impl From for ErrorObjectOwned { fn from(error: Error) -> Self { - let error_code = match error { - Error::SelectChain(_) => 1, - Error::FetchEpoch => 2, - }; - - JsonRpseeError::Call(CallError::Custom(ErrorObject::owned( - BABE_ERROR + error_code, - error.to_string(), - Some(format!("{:?}", error)), - ))) + match error { + Error::SelectChain(e) => ErrorObject::owned(BABE_ERROR + 1, e.to_string(), None::<()>), + Error::FetchEpoch => ErrorObject::owned(BABE_ERROR + 2, error.to_string(), None::<()>), + Error::Consensus(e) => ErrorObject::owned(BABE_ERROR + 3, e.to_string(), None::<()>), + Error::StringError(e) => ErrorObject::owned(BABE_ERROR + 4, e, None::<()>), + Error::UnsafeRpcCalled(e) => e.into(), + } } } @@ -246,7 +252,7 @@ mod tests { let api = babe_rpc.into_rpc(); let request = r#"{"jsonrpc":"2.0","method":"babe_epochAuthorship","params": [],"id":1}"#; - let (response, _) = api.raw_json_request(request).await.unwrap(); + let (response, _) = api.raw_json_request(request, 1).await.unwrap(); let expected = r#"{"jsonrpc":"2.0","result":{"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY":{"primary":[0],"secondary":[1,2,4],"secondary_vrf":[]}},"id":1}"#; assert_eq!(&response.result, expected); @@ -258,7 +264,7 @@ mod tests { let api = babe_rpc.into_rpc(); let request = r#"{"jsonrpc":"2.0","method":"babe_epochAuthorship","params":[],"id":1}"#; - let (response, _) = api.raw_json_request(request).await.unwrap(); + let (response, _) = api.raw_json_request(request, 1).await.unwrap(); let expected = r#"{"jsonrpc":"2.0","error":{"code":-32601,"message":"RPC call is unsafe to be called externally"},"id":1}"#; assert_eq!(&response.result, expected); diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 219b52294952a..64ff00bb58c35 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -1152,10 +1152,10 @@ where // Verification for imported blocks is skipped in two cases: // 1. When importing blocks below the last finalized block during network initial // synchronization. - // 2. When importing whole state we don't calculate epoch descriptor, but rather - // read it from the state after import. We also skip all verifications - // because there's no parent state and we trust the sync module to verify - // that the state is correct and finalized. + // 2. When importing whole state we don't calculate epoch descriptor, but rather read it + // from the state after import. We also skip all verifications because there's no + // parent state and we trust the sync module to verify that the state is correct and + // finalized. return Ok(block) } diff --git a/client/consensus/beefy/rpc/Cargo.toml b/client/consensus/beefy/rpc/Cargo.toml index 4f6e0d8c84b6b..e208ef978e2f6 100644 --- a/client/consensus/beefy/rpc/Cargo.toml +++ b/client/consensus/beefy/rpc/Cargo.toml @@ -11,7 +11,7 @@ homepage = "https://substrate.io" [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] } futures = "0.3.21" -jsonrpsee = { version = "0.16.2", features = ["client-core", "server", "macros"] } +jsonrpsee = { version = "0.19.0", features = ["client-core", "server", "macros"] } log = "0.4" parking_lot = "0.12.1" serde = { version = "1.0.163", features = ["derive"] } @@ -26,4 +26,4 @@ sp-runtime = { version = "24.0.0", path = "../../../../primitives/runtime" } serde_json = "1.0.85" sc-rpc = { version = "4.0.0-dev", features = ["test-helpers"], path = "../../../rpc" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../../test-utils/runtime/client" } -tokio = { version = "1.22.0", features = ["macros"] } +tokio = { version = "1.22.0", features = ["macros", "time"] } diff --git a/client/consensus/beefy/rpc/src/lib.rs b/client/consensus/beefy/rpc/src/lib.rs index f5c0ff32627d5..0a5bdf1a7e096 100644 --- a/client/consensus/beefy/rpc/src/lib.rs +++ b/client/consensus/beefy/rpc/src/lib.rs @@ -23,15 +23,15 @@ use parking_lot::RwLock; use std::sync::Arc; -use sc_rpc::SubscriptionTaskExecutor; +use sc_rpc::{utils::accept_and_pipe_from_stream, SubscriptionTaskExecutor}; use sp_runtime::traits::Block as BlockT; use futures::{task::SpawnError, FutureExt, StreamExt}; use jsonrpsee::{ - core::{async_trait, Error as JsonRpseeError, RpcResult}, + core::async_trait, proc_macros::rpc, - types::{error::CallError, ErrorObject, SubscriptionResult}, - SubscriptionSink, + types::{ErrorObject, ErrorObjectOwned}, + PendingSubscriptionSink, }; use log::warn; @@ -69,15 +69,11 @@ impl From for ErrorCode { } } -impl From for JsonRpseeError { +impl From for ErrorObjectOwned { fn from(error: Error) -> Self { let message = error.to_string(); let code = ErrorCode::from(error); - JsonRpseeError::Call(CallError::Custom(ErrorObject::owned( - code as i32, - message, - None::<()>, - ))) + ErrorObject::owned(code as i32, message, None::<()>) } } @@ -90,7 +86,7 @@ pub trait BeefyApi { unsubscribe = "beefy_unsubscribeJustifications", item = Notification, )] - fn subscribe_justifications(&self); + async fn subscribe_justifications(&self); /// Returns hash of the latest BEEFY finalized block as seen by this client. /// @@ -98,7 +94,7 @@ pub trait BeefyApi { /// in the network or if the client is still initializing or syncing with the network. /// In such case an error would be returned. #[method(name = "beefy_getFinalizedHead")] - async fn latest_finalized(&self) -> RpcResult; + async fn latest_finalized(&self) -> Result; } /// Implements the BeefyApi RPC trait for interacting with BEEFY. @@ -138,27 +134,17 @@ impl BeefyApiServer SubscriptionResult { + async fn subscribe_justifications(&self, pending: PendingSubscriptionSink) { let stream = self .finality_proof_stream .subscribe(100_000) .map(|vfp| notification::EncodedVersionedFinalityProof::new::(vfp)); - let fut = async move { - sink.pipe_from_stream(stream).await; - }; - - self.executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); - Ok(()) + accept_and_pipe_from_stream::<(), _, _>(pending, stream, &self.executor).await; } - async fn latest_finalized(&self) -> RpcResult { - self.beefy_best_block - .read() - .as_ref() - .cloned() - .ok_or(Error::EndpointNotReady) - .map_err(Into::into) + async fn latest_finalized(&self) -> Result { + self.beefy_best_block.read().as_ref().cloned().ok_or(Error::EndpointNotReady) } } @@ -167,7 +153,7 @@ mod tests { use super::*; use codec::{Decode, Encode}; - use jsonrpsee::{types::EmptyServerParams as EmptyParams, RpcModule}; + use jsonrpsee::{core::EmptyServerParams as EmptyParams, RpcModule}; use sc_consensus_beefy::{ communication::notification::BeefyVersionedFinalityProofSender, justification::BeefyVersionedFinalityProof, @@ -199,7 +185,7 @@ mod tests { let (rpc, _) = setup_io_handler(); let request = r#"{"jsonrpc":"2.0","method":"beefy_getFinalizedHead","params":[],"id":1}"#; let expected_response = r#"{"jsonrpc":"2.0","error":{"code":1,"message":"BEEFY RPC endpoint not ready"},"id":1}"#.to_string(); - let (response, _) = rpc.raw_json_request(&request).await.unwrap(); + let (response, _) = rpc.raw_json_request(&request, 1).await.unwrap(); assert_eq!(expected_response, response.result); } @@ -230,13 +216,13 @@ mod tests { let deadline = std::time::Instant::now() + std::time::Duration::from_secs(2); while std::time::Instant::now() < deadline { - let (response, _) = io.raw_json_request(request).await.expect("RPC requests work"); + let (response, _) = io.raw_json_request(request, 1).await.expect("RPC requests work"); if response.result != not_ready { assert_eq!(response.result, expected); // Success return } - std::thread::sleep(std::time::Duration::from_millis(50)) + tokio::time::sleep(std::time::Duration::from_millis(50)).await; } panic!( @@ -249,7 +235,7 @@ mod tests { let (rpc, _) = setup_io_handler(); // Subscribe call. let _sub = rpc - .subscribe("beefy_subscribeJustifications", EmptyParams::new()) + .subscribe_unbounded("beefy_subscribeJustifications", EmptyParams::new()) .await .unwrap(); @@ -257,6 +243,7 @@ mod tests { let (response, _) = rpc .raw_json_request( r#"{"jsonrpc":"2.0","method":"beefy_unsubscribeJustifications","params":["FOO"],"id":1}"#, + 1, ) .await .unwrap(); @@ -284,7 +271,7 @@ mod tests { // Subscribe let mut sub = rpc - .subscribe("beefy_subscribeJustifications", EmptyParams::new()) + .subscribe_unbounded("beefy_subscribeJustifications", EmptyParams::new()) .await .unwrap(); diff --git a/client/consensus/beefy/src/worker.rs b/client/consensus/beefy/src/worker.rs index cbf58e56b2cdf..91b00ddb2cef0 100644 --- a/client/consensus/beefy/src/worker.rs +++ b/client/consensus/beefy/src/worker.rs @@ -78,11 +78,11 @@ pub(crate) struct VoterOracle { /// /// There are three voter states coresponding to three queue states: /// 1. voter uninitialized: queue empty, - /// 2. up-to-date - all mandatory blocks leading up to current GRANDPA finalized: - /// queue has ONE element, the 'current session' where `mandatory_done == true`, + /// 2. up-to-date - all mandatory blocks leading up to current GRANDPA finalized: queue has ONE + /// element, the 'current session' where `mandatory_done == true`, /// 3. lagging behind GRANDPA: queue has [1, N] elements, where all `mandatory_done == false`. - /// In this state, everytime a session gets its mandatory block BEEFY finalized, it's - /// popped off the queue, eventually getting to state `2. up-to-date`. + /// In this state, everytime a session gets its mandatory block BEEFY finalized, it's popped + /// off the queue, eventually getting to state `2. up-to-date`. sessions: VecDeque>, /// Min delta in block numbers between two blocks, BEEFY should vote on. min_block_delta: u32, diff --git a/client/consensus/common/src/block_import.rs b/client/consensus/common/src/block_import.rs index 70bf0283af2d9..d05b65a01b8b5 100644 --- a/client/consensus/common/src/block_import.rs +++ b/client/consensus/common/src/block_import.rs @@ -43,7 +43,7 @@ pub enum ImportResult { } /// Auxiliary data associated with an imported block result. -#[derive(Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] pub struct ImportedAux { /// Only the header has been imported. Block body verification was skipped. pub header_only: bool, diff --git a/client/consensus/grandpa/rpc/Cargo.toml b/client/consensus/grandpa/rpc/Cargo.toml index 5c3b5a171b928..526d85036087e 100644 --- a/client/consensus/grandpa/rpc/Cargo.toml +++ b/client/consensus/grandpa/rpc/Cargo.toml @@ -12,7 +12,7 @@ homepage = "https://substrate.io" [dependencies] finality-grandpa = { version = "0.16.2", features = ["derive-codec"] } futures = "0.3.16" -jsonrpsee = { version = "0.16.2", features = ["client-core", "server", "macros"] } +jsonrpsee = { version = "0.19.0", features = ["client-core", "server", "macros"] } log = "0.4.8" parity-scale-codec = { version = "3.6.1", features = ["derive"] } serde = { version = "1.0.163", features = ["derive"] } diff --git a/client/consensus/grandpa/rpc/src/error.rs b/client/consensus/grandpa/rpc/src/error.rs index 4884380cd22d0..795077804a4b0 100644 --- a/client/consensus/grandpa/rpc/src/error.rs +++ b/client/consensus/grandpa/rpc/src/error.rs @@ -16,10 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use jsonrpsee::{ - core::Error as JsonRpseeError, - types::error::{CallError, ErrorObject}, -}; +use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned}; #[derive(Debug, thiserror::Error)] /// Top-level error type for the RPC handler @@ -61,15 +58,11 @@ impl From for ErrorCode { } } -impl From for JsonRpseeError { +impl From for ErrorObjectOwned { fn from(error: Error) -> Self { let message = error.to_string(); let code = ErrorCode::from(error); - JsonRpseeError::Call(CallError::Custom(ErrorObject::owned( - code as i32, - message, - None::<()>, - ))) + ErrorObject::owned(code as i32, message, None::<()>) } } diff --git a/client/consensus/grandpa/rpc/src/finality.rs b/client/consensus/grandpa/rpc/src/finality.rs index f8ec01781ac6b..93f6c46e411ec 100644 --- a/client/consensus/grandpa/rpc/src/finality.rs +++ b/client/consensus/grandpa/rpc/src/finality.rs @@ -21,7 +21,7 @@ use serde::{Deserialize, Serialize}; use sc_consensus_grandpa::FinalityProofProvider; use sp_runtime::traits::{Block as BlockT, NumberFor}; -#[derive(Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] pub struct EncodedFinalityProof(pub sp_core::Bytes); /// Local trait mainly to allow mocking in tests. diff --git a/client/consensus/grandpa/rpc/src/lib.rs b/client/consensus/grandpa/rpc/src/lib.rs index c6298bff969bd..246d980fcac92 100644 --- a/client/consensus/grandpa/rpc/src/lib.rs +++ b/client/consensus/grandpa/rpc/src/lib.rs @@ -19,15 +19,13 @@ //! RPC API for GRANDPA. #![warn(missing_docs)] -use futures::{FutureExt, StreamExt}; +use futures::StreamExt; use log::warn; use std::sync::Arc; use jsonrpsee::{ - core::{async_trait, RpcResult}, + core::{async_trait, server::PendingSubscriptionSink}, proc_macros::rpc, - types::SubscriptionResult, - SubscriptionSink, }; mod error; @@ -35,13 +33,13 @@ mod finality; mod notification; mod report; -use sc_consensus_grandpa::GrandpaJustificationStream; -use sc_rpc::SubscriptionTaskExecutor; -use sp_runtime::traits::{Block as BlockT, NumberFor}; - +use error::Error; use finality::{EncodedFinalityProof, RpcFinalityProofProvider}; use notification::JustificationNotification; use report::{ReportAuthoritySet, ReportVoterState, ReportedRoundStates}; +use sc_consensus_grandpa::GrandpaJustificationStream; +use sc_rpc::{utils::accept_and_pipe_from_stream, SubscriptionTaskExecutor}; +use sp_runtime::traits::{Block as BlockT, NumberFor}; /// Provides RPC methods for interacting with GRANDPA. #[rpc(client, server)] @@ -49,7 +47,7 @@ pub trait GrandpaApi { /// Returns the state of the current best round state as well as the /// ongoing background rounds. #[method(name = "grandpa_roundState")] - async fn round_state(&self) -> RpcResult; + async fn round_state(&self) -> Result; /// Returns the block most recently finalized by Grandpa, alongside /// side its justification. @@ -58,12 +56,12 @@ pub trait GrandpaApi { unsubscribe = "grandpa_unsubscribeJustifications", item = Notification )] - fn subscribe_justifications(&self); + async fn subscribe_justifications(&self); /// Prove finality for the given block number by returning the Justification for the last block /// in the set and all the intermediary headers to link them together. #[method(name = "grandpa_proveFinality")] - async fn prove_finality(&self, block: Number) -> RpcResult>; + async fn prove_finality(&self, block: Number) -> Result, Error>; } /// Provides RPC methods for interacting with GRANDPA. @@ -99,36 +97,28 @@ where Block: BlockT, ProofProvider: RpcFinalityProofProvider + Send + Sync + 'static, { - async fn round_state(&self) -> RpcResult { - ReportedRoundStates::from(&self.authority_set, &self.voter_state).map_err(Into::into) + async fn round_state(&self) -> Result { + ReportedRoundStates::from(&self.authority_set, &self.voter_state) } - fn subscribe_justifications(&self, mut sink: SubscriptionSink) -> SubscriptionResult { + async fn subscribe_justifications(&self, pending: PendingSubscriptionSink) { let stream = self.justification_stream.subscribe(100_000).map( |x: sc_consensus_grandpa::GrandpaJustification| { JustificationNotification::from(x) }, ); - let fut = async move { - sink.pipe_from_stream(stream).await; - }; - - self.executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); - Ok(()) + accept_and_pipe_from_stream::<(), _, _>(pending, stream, &self.executor).await; } async fn prove_finality( &self, block: NumberFor, - ) -> RpcResult> { - self.finality_proof_provider - .rpc_prove_finality(block) - .map_err(|e| { - warn!("Error proving finality: {}", e); - error::Error::ProveFinalityFailed(e) - }) - .map_err(Into::into) + ) -> Result, Error> { + self.finality_proof_provider.rpc_prove_finality(block).map_err(|e| { + warn!("Error proving finality: {}", e); + error::Error::ProveFinalityFailed(e) + }) } } @@ -137,17 +127,15 @@ mod tests { use super::*; use std::{collections::HashSet, convert::TryInto, sync::Arc}; - use jsonrpsee::{ - types::{EmptyServerParams as EmptyParams, SubscriptionId}, - RpcModule, - }; + use jsonrpsee::{core::EmptyServerParams as EmptyParams, types::SubscriptionId, RpcModule}; use parity_scale_codec::{Decode, Encode}; use sc_block_builder::{BlockBuilder, RecordProof}; use sc_consensus_grandpa::{ report, AuthorityId, FinalityProof, GrandpaJustification, GrandpaJustificationSender, }; + use sc_rpc::testing::test_executor; use sp_blockchain::HeaderBackend; - use sp_core::{crypto::ByteArray, testing::TaskExecutor}; + use sp_core::crypto::ByteArray; use sp_keyring::Ed25519Keyring; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use substrate_test_runtime_client::{ @@ -264,7 +252,7 @@ mod tests { { let (justification_sender, justification_stream) = GrandpaJustificationStream::channel(); let finality_proof_provider = Arc::new(TestFinalityProofProvider { finality_proof }); - let executor = Arc::new(TaskExecutor::default()); + let executor = test_executor(); let rpc = Grandpa::new( executor, @@ -283,7 +271,7 @@ mod tests { let (rpc, _) = setup_io_handler(EmptyVoterState); let expected_response = r#"{"jsonrpc":"2.0","error":{"code":1,"message":"GRANDPA RPC endpoint not ready"},"id":0}"#.to_string(); let request = r#"{"jsonrpc":"2.0","method":"grandpa_roundState","params":[],"id":0}"#; - let (response, _) = rpc.raw_json_request(&request).await.unwrap(); + let (response, _) = rpc.raw_json_request(&request, 1).await.unwrap(); assert_eq!(expected_response, response.result); } @@ -306,7 +294,7 @@ mod tests { },\"id\":0}".to_string(); let request = r#"{"jsonrpc":"2.0","method":"grandpa_roundState","params":[],"id":0}"#; - let (response, _) = rpc.raw_json_request(&request).await.unwrap(); + let (response, _) = rpc.raw_json_request(&request, 1).await.unwrap(); assert_eq!(expected_response, response.result); } @@ -315,7 +303,7 @@ mod tests { let (rpc, _) = setup_io_handler(TestVoterState); // Subscribe call. let _sub = rpc - .subscribe("grandpa_subscribeJustifications", EmptyParams::new()) + .subscribe_unbounded("grandpa_subscribeJustifications", EmptyParams::new()) .await .unwrap(); @@ -323,6 +311,7 @@ mod tests { let (response, _) = rpc .raw_json_request( r#"{"jsonrpc":"2.0","method":"grandpa_unsubscribeJustifications","params":["FOO"],"id":1}"#, + 1, ) .await .unwrap(); @@ -390,7 +379,7 @@ mod tests { let (rpc, justification_sender) = setup_io_handler(TestVoterState); let mut sub = rpc - .subscribe("grandpa_subscribeJustifications", EmptyParams::new()) + .subscribe_unbounded("grandpa_subscribeJustifications", EmptyParams::new()) .await .unwrap(); diff --git a/client/consensus/grandpa/rpc/src/report.rs b/client/consensus/grandpa/rpc/src/report.rs index ae4fd76d2857a..b41d090afac85 100644 --- a/client/consensus/grandpa/rpc/src/report.rs +++ b/client/consensus/grandpa/rpc/src/report.rs @@ -57,21 +57,21 @@ impl ReportVoterState for SharedVoterState { } } -#[derive(Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct Prevotes { current_weight: u32, missing: BTreeSet, } -#[derive(Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct Precommits { current_weight: u32, missing: BTreeSet, } -#[derive(Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct RoundState { round: u32, @@ -111,7 +111,7 @@ impl RoundState { /// The state of the current best round, as well as the background rounds in a /// form suitable for serialization. -#[derive(Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ReportedRoundStates { set_id: u32, diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index 4bc389ac3f4cd..a0b52a625512f 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee = { version = "0.16.2", features = ["client-core", "server", "macros"] } +jsonrpsee = { version = "0.19.0", features = ["client-core", "server", "macros"] } assert_matches = "1.3.0" async-trait = "0.1.57" codec = { package = "parity-scale-codec", version = "3.6.1" } diff --git a/client/consensus/manual-seal/src/error.rs b/client/consensus/manual-seal/src/error.rs index eeae1d153e81b..d7bb00eff6b73 100644 --- a/client/consensus/manual-seal/src/error.rs +++ b/client/consensus/manual-seal/src/error.rs @@ -20,10 +20,7 @@ //! This is suitable for a testing environment. use futures::channel::{mpsc::SendError, oneshot}; -use jsonrpsee::{ - core::Error as JsonRpseeError, - types::error::{CallError, ErrorObject}, -}; +use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned}; use sc_consensus::ImportResult; use sp_blockchain::Error as BlockchainError; use sp_consensus::Error as ConsensusError; @@ -106,8 +103,8 @@ impl Error { } } -impl From for JsonRpseeError { +impl From for ErrorObjectOwned { fn from(err: Error) -> Self { - CallError::Custom(ErrorObject::owned(err.to_code(), err.to_string(), None::<()>)).into() + ErrorObject::owned(err.to_code(), err.to_string(), None::<()>) } } diff --git a/client/consensus/manual-seal/src/rpc.rs b/client/consensus/manual-seal/src/rpc.rs index 85abcdc08574b..2b3341b9d2846 100644 --- a/client/consensus/manual-seal/src/rpc.rs +++ b/client/consensus/manual-seal/src/rpc.rs @@ -23,10 +23,7 @@ use futures::{ channel::{mpsc, oneshot}, SinkExt, }; -use jsonrpsee::{ - core::{async_trait, Error as JsonRpseeError, RpcResult}, - proc_macros::rpc, -}; +use jsonrpsee::{core::async_trait, proc_macros::rpc}; use sc_consensus::ImportedAux; use serde::{Deserialize, Serialize}; use sp_runtime::EncodedJustification; @@ -74,7 +71,7 @@ pub trait ManualSealApi { create_empty: bool, finalize: bool, parent_hash: Option, - ) -> RpcResult>; + ) -> Result, Error>; /// Instructs the manual-seal authorship task to finalize a block #[method(name = "engine_finalizeBlock")] @@ -82,7 +79,7 @@ pub trait ManualSealApi { &self, hash: Hash, justification: Option, - ) -> RpcResult; + ) -> Result; } /// A struct that implements the [`ManualSealApiServer`]. @@ -91,7 +88,7 @@ pub struct ManualSeal { } /// return type of `engine_createBlock` -#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] pub struct CreatedBlock { /// hash of the created block. pub hash: Hash, @@ -113,7 +110,7 @@ impl ManualSealApiServer for ManualSeal { create_empty: bool, finalize: bool, parent_hash: Option, - ) -> RpcResult> { + ) -> Result, Error> { let mut sink = self.import_block_channel.clone(); let (sender, receiver) = oneshot::channel(); // NOTE: this sends a Result over the channel. @@ -129,7 +126,7 @@ impl ManualSealApiServer for ManualSeal { match receiver.await { Ok(Ok(rx)) => Ok(rx), Ok(Err(e)) => Err(e.into()), - Err(e) => Err(JsonRpseeError::to_call_error(e)), + Err(e) => Err(e.into()), } } @@ -137,12 +134,12 @@ impl ManualSealApiServer for ManualSeal { &self, hash: Hash, justification: Option, - ) -> RpcResult { + ) -> Result { let mut sink = self.import_block_channel.clone(); let (sender, receiver) = oneshot::channel(); let command = EngineCommand::FinalizeBlock { hash, sender: Some(sender), justification }; sink.send(command).await?; - receiver.await.map(|_| true).map_err(|e| JsonRpseeError::to_call_error(e)) + receiver.await.map(|_| true).map_err(Into::into) } } diff --git a/client/merkle-mountain-range/rpc/Cargo.toml b/client/merkle-mountain-range/rpc/Cargo.toml index c6f8652c7e843..3f2ccb2c6eb87 100644 --- a/client/merkle-mountain-range/rpc/Cargo.toml +++ b/client/merkle-mountain-range/rpc/Cargo.toml @@ -13,14 +13,13 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1" } -jsonrpsee = { version = "0.16.2", features = ["client-core", "server", "macros"] } +jsonrpsee = { version = "0.19.0", features = ["client-core", "server", "macros"] } serde = { version = "1.0.163", features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "21.0.0", path = "../../../primitives/core" } sp-mmr-primitives = { version = "4.0.0-dev", path = "../../../primitives/merkle-mountain-range" } sp-runtime = { version = "24.0.0", path = "../../../primitives/runtime" } -anyhow = "1" [dev-dependencies] serde_json = "1.0.85" diff --git a/client/merkle-mountain-range/rpc/src/lib.rs b/client/merkle-mountain-range/rpc/src/lib.rs index daf2cd1ec298b..c5530d9bf3f3f 100644 --- a/client/merkle-mountain-range/rpc/src/lib.rs +++ b/client/merkle-mountain-range/rpc/src/lib.rs @@ -26,7 +26,7 @@ use codec::{Codec, Decode, Encode}; use jsonrpsee::{ core::{async_trait, RpcResult}, proc_macros::rpc, - types::error::{CallError, ErrorObject}, + types::{error::ErrorObject, ErrorObjectOwned}, }; use serde::{Deserialize, Serialize}; @@ -187,11 +187,9 @@ where fn verify_proof(&self, proof: LeavesProof<::Hash>) -> RpcResult { let api = self.client.runtime_api(); - let leaves = Decode::decode(&mut &proof.leaves.0[..]) - .map_err(|e| CallError::InvalidParams(anyhow::Error::new(e)))?; + let leaves = Decode::decode(&mut &proof.leaves.0[..]).map_err(invalid_params)?; - let decoded_proof = Decode::decode(&mut &proof.proof.0[..]) - .map_err(|e| CallError::InvalidParams(anyhow::Error::new(e)))?; + let decoded_proof = Decode::decode(&mut &proof.proof.0[..]).map_err(invalid_params)?; api.verify_proof_with_context( proof.block_hash, @@ -212,11 +210,9 @@ where ) -> RpcResult { let api = self.client.runtime_api(); - let leaves = Decode::decode(&mut &proof.leaves.0[..]) - .map_err(|e| CallError::InvalidParams(anyhow::Error::new(e)))?; + let leaves = Decode::decode(&mut &proof.leaves.0[..]).map_err(invalid_params)?; - let decoded_proof = Decode::decode(&mut &proof.proof.0[..]) - .map_err(|e| CallError::InvalidParams(anyhow::Error::new(e)))?; + let decoded_proof = Decode::decode(&mut &proof.proof.0[..]).map_err(invalid_params)?; api.verify_proof_stateless(proof.block_hash, mmr_root, leaves, decoded_proof) .map_err(runtime_error_into_rpc_error)? @@ -227,7 +223,7 @@ where } /// Converts an mmr-specific error into a [`CallError`]. -fn mmr_error_into_rpc_error(err: MmrError) -> CallError { +fn mmr_error_into_rpc_error(err: MmrError) -> ErrorObjectOwned { let error_code = MMR_ERROR + match err { MmrError::LeafNotFound => 1, @@ -238,16 +234,20 @@ fn mmr_error_into_rpc_error(err: MmrError) -> CallError { _ => 0, }; - CallError::Custom(ErrorObject::owned(error_code, err.to_string(), Some(format!("{:?}", err)))) + ErrorObject::owned(error_code, err.to_string(), Some(format!("{:?}", err))) } /// Converts a runtime trap into a [`CallError`]. -fn runtime_error_into_rpc_error(err: impl std::fmt::Debug) -> CallError { - CallError::Custom(ErrorObject::owned( - RUNTIME_ERROR, - "Runtime trapped", - Some(format!("{:?}", err)), - )) +fn runtime_error_into_rpc_error(err: impl std::fmt::Debug) -> ErrorObjectOwned { + ErrorObject::owned(RUNTIME_ERROR, "Runtime trapped", Some(format!("{:?}", err))) +} + +fn invalid_params(e: impl std::error::Error) -> ErrorObjectOwned { + ErrorObject::owned( + jsonrpsee::types::error::ErrorCode::InvalidParams.code(), + e.to_string(), + None::<()>, + ) } #[cfg(test)] diff --git a/client/network/src/protocol/notifications/behaviour.rs b/client/network/src/protocol/notifications/behaviour.rs index 42233288afe08..1659626cae4c8 100644 --- a/client/network/src/protocol/notifications/behaviour.rs +++ b/client/network/src/protocol/notifications/behaviour.rs @@ -84,19 +84,17 @@ use std::{ /// the API of this behaviour and towards the peerset manager is aggregated in /// the following way: /// -/// 1. The enabled/disabled status is the same across all connections, as -/// decided by the peerset manager. -/// 2. `send_packet` and `write_notification` always send all data over -/// the same connection to preserve the ordering provided by the transport, -/// as long as that connection is open. If it closes, a second open -/// connection may take over, if one exists, but that case should be no -/// different than a single connection failing and being re-established -/// in terms of potential reordering and dropped messages. Messages can -/// be received on any connection. -/// 3. The behaviour reports `NotificationsOut::CustomProtocolOpen` when the -/// first connection reports `NotifsHandlerOut::OpenResultOk`. -/// 4. The behaviour reports `NotificationsOut::CustomProtocolClosed` when the -/// last connection reports `NotifsHandlerOut::ClosedResult`. +/// 1. The enabled/disabled status is the same across all connections, as decided by the peerset +/// manager. +/// 2. `send_packet` and `write_notification` always send all data over the same connection to +/// preserve the ordering provided by the transport, as long as that connection is open. If it +/// closes, a second open connection may take over, if one exists, but that case should be no +/// different than a single connection failing and being re-established in terms of potential +/// reordering and dropped messages. Messages can be received on any connection. +/// 3. The behaviour reports `NotificationsOut::CustomProtocolOpen` when the first connection +/// reports `NotifsHandlerOut::OpenResultOk`. +/// 4. The behaviour reports `NotificationsOut::CustomProtocolClosed` when the last connection +/// reports `NotifsHandlerOut::ClosedResult`. /// /// In this way, the number of actual established connections to the peer is /// an implementation detail of this behaviour. Note that, in practice and at diff --git a/client/network/src/service/traits.rs b/client/network/src/service/traits.rs index 97680a9eb73b7..bebf5a5713c45 100644 --- a/client/network/src/service/traits.rs +++ b/client/network/src/service/traits.rs @@ -402,9 +402,9 @@ pub trait NetworkNotification { /// a receiver. With a `NotificationSender` at hand, sending a notification is done in two /// steps: /// - /// 1. [`NotificationSender::ready`] is used to wait for the sender to become ready + /// 1. [`NotificationSender::ready`] is used to wait for the sender to become ready /// for another notification, yielding a [`NotificationSenderReady`] token. - /// 2. [`NotificationSenderReady::send`] enqueues the notification for sending. This operation + /// 2. [`NotificationSenderReady::send`] enqueues the notification for sending. This operation /// can only fail if the underlying notification substream or connection has suddenly closed. /// /// An error is returned by [`NotificationSenderReady::send`] if there exists no open diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 5efb10f719c20..535ecf7282cb5 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -24,4 +24,4 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-rpc = { version = "6.0.0", path = "../../primitives/rpc" } sp-runtime = { version = "24.0.0", path = "../../primitives/runtime" } sp-version = { version = "22.0.0", path = "../../primitives/version" } -jsonrpsee = { version = "0.16.2", features = ["server", "client-core", "macros"] } +jsonrpsee = { version = "0.19.0", features = ["server", "client-core", "macros"] } diff --git a/client/rpc-api/src/author/error.rs b/client/rpc-api/src/author/error.rs index 648dbb295d8d0..0ccd82fc0b64c 100644 --- a/client/rpc-api/src/author/error.rs +++ b/client/rpc-api/src/author/error.rs @@ -18,10 +18,7 @@ //! Authoring RPC module errors. -use jsonrpsee::{ - core::Error as JsonRpseeError, - types::error::{CallError, ErrorObject}, -}; +use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned}; use sp_runtime::transaction_validity::InvalidTransaction; /// Author RPC Result type. @@ -86,98 +83,104 @@ const POOL_NO_TAGS: i32 = POOL_INVALID_TX + 9; const POOL_INVALID_BLOCK_ID: i32 = POOL_INVALID_TX + 10; /// The pool is not accepting future transactions. const POOL_FUTURE_TX: i32 = POOL_INVALID_TX + 11; +/// Other error. +const OTHER_ERR: i32 = BASE_ERROR + 40; -impl From for JsonRpseeError { - fn from(e: Error) -> Self { +impl From for ErrorObjectOwned { + fn from(e: Error) -> ErrorObjectOwned { use sc_transaction_pool_api::error::Error as PoolError; match e { - Error::BadFormat(e) => CallError::Custom(ErrorObject::owned( + Error::BadFormat(e) => ErrorObject::owned( BAD_FORMAT, format!("Extrinsic has invalid format: {}", e), None::<()>, - )), - Error::Verification(e) => CallError::Custom(ErrorObject::owned( + ), + Error::Verification(e) => ErrorObject::owned( VERIFICATION_ERROR, format!("Verification Error: {}", e), Some(format!("{:?}", e)), - )), + ), Error::Pool(PoolError::InvalidTransaction(InvalidTransaction::Custom(e))) => { - CallError::Custom(ErrorObject::owned( + ErrorObject::owned( POOL_INVALID_TX, "Invalid Transaction", Some(format!("Custom error: {}", e)), - )) + ) }, Error::Pool(PoolError::InvalidTransaction(e)) => { let msg: &str = e.into(); - CallError::Custom(ErrorObject::owned( + ErrorObject::owned( POOL_INVALID_TX, "Invalid Transaction", Some(msg), - )) + ) }, Error::Pool(PoolError::UnknownTransaction(e)) => { - CallError::Custom(ErrorObject::owned( + ErrorObject::owned( POOL_UNKNOWN_VALIDITY, "Unknown Transaction Validity", Some(format!("{:?}", e)), - )) + ) }, Error::Pool(PoolError::TemporarilyBanned) => - CallError::Custom(ErrorObject::owned( + ErrorObject::owned( POOL_TEMPORARILY_BANNED, "Transaction is temporarily banned", None::<()>, - )), + ), Error::Pool(PoolError::AlreadyImported(hash)) => - CallError::Custom(ErrorObject::owned( + ErrorObject::owned( POOL_ALREADY_IMPORTED, "Transaction Already Imported", Some(format!("{:?}", hash)), - )), - Error::Pool(PoolError::TooLowPriority { old, new }) => CallError::Custom(ErrorObject::owned( + ), + Error::Pool(PoolError::TooLowPriority { old, new }) => ErrorObject::owned( POOL_TOO_LOW_PRIORITY, format!("Priority is too low: ({} vs {})", old, new), Some("The transaction has too low priority to replace another transaction already in the pool.") - )), + ), Error::Pool(PoolError::CycleDetected) => - CallError::Custom(ErrorObject::owned( + ErrorObject::owned( POOL_CYCLE_DETECTED, "Cycle Detected", None::<()> - )), - Error::Pool(PoolError::ImmediatelyDropped) => CallError::Custom(ErrorObject::owned( + ), + Error::Pool(PoolError::ImmediatelyDropped) => ErrorObject::owned( POOL_IMMEDIATELY_DROPPED, "Immediately Dropped", Some("The transaction couldn't enter the pool because of the limit"), - )), - Error::Pool(PoolError::Unactionable) => CallError::Custom(ErrorObject::owned( + ), + Error::Pool(PoolError::Unactionable) => ErrorObject::owned( POOL_UNACTIONABLE, "Unactionable", Some("The transaction is unactionable since it is not propagable and \ the local node does not author blocks") - )), - Error::Pool(PoolError::NoTagsProvided) => CallError::Custom(ErrorObject::owned( + ), + Error::Pool(PoolError::NoTagsProvided) => ErrorObject::owned( POOL_NO_TAGS, "No tags provided", Some("Transaction does not provide any tags, so the pool can't identify it") - )), + ), Error::Pool(PoolError::InvalidBlockId(_)) => - CallError::Custom(ErrorObject::owned( + ErrorObject::owned( POOL_INVALID_BLOCK_ID, "The provided block ID is not valid", None::<()> - )), + ), Error::Pool(PoolError::RejectedFutureTransaction) => { - CallError::Custom(ErrorObject::owned( + ErrorObject::owned( POOL_FUTURE_TX, "The pool is not accepting future transactions", None::<()>, - )) + ) }, Error::UnsafeRpcCalled(e) => e.into(), - e => CallError::Failed(e.into()), - }.into() + other => ErrorObject::owned( + OTHER_ERR, + other.to_string(), + None::<()>, + ) + } } } diff --git a/client/rpc-api/src/author/mod.rs b/client/rpc-api/src/author/mod.rs index 55881e62152e3..ab477173bcf42 100644 --- a/client/rpc-api/src/author/mod.rs +++ b/client/rpc-api/src/author/mod.rs @@ -18,27 +18,28 @@ //! Substrate block-author/full-node API. -use jsonrpsee::{core::RpcResult, proc_macros::rpc}; -use sc_transaction_pool_api::TransactionStatus; -use sp_core::Bytes; - pub mod error; pub mod hash; +use error::Error; +use jsonrpsee::proc_macros::rpc; +use sc_transaction_pool_api::TransactionStatus; +use sp_core::Bytes; + /// Substrate authoring RPC API #[rpc(client, server)] pub trait AuthorApi { /// Submit hex-encoded extrinsic for inclusion in block. #[method(name = "author_submitExtrinsic")] - async fn submit_extrinsic(&self, extrinsic: Bytes) -> RpcResult; + async fn submit_extrinsic(&self, extrinsic: Bytes) -> Result; /// Insert a key into the keystore. #[method(name = "author_insertKey")] - fn insert_key(&self, key_type: String, suri: String, public: Bytes) -> RpcResult<()>; + fn insert_key(&self, key_type: String, suri: String, public: Bytes) -> Result<(), Error>; /// Generate new session keys and returns the corresponding public keys. #[method(name = "author_rotateKeys")] - fn rotate_keys(&self) -> RpcResult; + fn rotate_keys(&self) -> Result; /// Checks if the keystore has private keys for the given session public keys. /// @@ -46,24 +47,24 @@ pub trait AuthorApi { /// /// Returns `true` iff all private keys could be found. #[method(name = "author_hasSessionKeys")] - fn has_session_keys(&self, session_keys: Bytes) -> RpcResult; + fn has_session_keys(&self, session_keys: Bytes) -> Result; /// Checks if the keystore has private keys for the given public key and key type. /// /// Returns `true` if a private key could be found. #[method(name = "author_hasKey")] - fn has_key(&self, public_key: Bytes, key_type: String) -> RpcResult; + fn has_key(&self, public_key: Bytes, key_type: String) -> Result; /// Returns all pending extrinsics, potentially grouped by sender. #[method(name = "author_pendingExtrinsics")] - fn pending_extrinsics(&self) -> RpcResult>; + fn pending_extrinsics(&self) -> Result, Error>; /// Remove given extrinsic from the pool and temporarily ban it to prevent reimporting. #[method(name = "author_removeExtrinsic")] fn remove_extrinsic( &self, bytes_or_hash: Vec>, - ) -> RpcResult>; + ) -> Result, Error>; /// Submit an extrinsic to watch. /// @@ -74,5 +75,5 @@ pub trait AuthorApi { unsubscribe = "author_unwatchExtrinsic", item = TransactionStatus, )] - fn watch_extrinsic(&self, bytes: Bytes); + async fn watch_extrinsic(&self, bytes: Bytes); } diff --git a/client/rpc-api/src/chain/error.rs b/client/rpc-api/src/chain/error.rs index 6521929425888..ff3593557bdbc 100644 --- a/client/rpc-api/src/chain/error.rs +++ b/client/rpc-api/src/chain/error.rs @@ -18,10 +18,7 @@ //! Error helpers for Chain RPC module. -use jsonrpsee::{ - core::Error as JsonRpseeError, - types::error::{CallError, ErrorObject}, -}; +use jsonrpsee::types::{error::ErrorObject, ErrorObjectOwned}; /// Chain RPC Result type. pub type Result = std::result::Result; @@ -39,12 +36,11 @@ pub enum Error { /// Base error code for all chain errors. const BASE_ERROR: i32 = crate::error::base::CHAIN; -impl From for JsonRpseeError { - fn from(e: Error) -> Self { +impl From for ErrorObjectOwned { + fn from(e: Error) -> ErrorObjectOwned { match e { - Error::Other(message) => - CallError::Custom(ErrorObject::owned(BASE_ERROR + 1, message, None::<()>)).into(), - e => e.into(), + Error::Other(message) => ErrorObject::owned(BASE_ERROR + 1, message, None::<()>), + e => ErrorObject::owned(BASE_ERROR + 2, e.to_string(), None::<()>), } } } diff --git a/client/rpc-api/src/chain/mod.rs b/client/rpc-api/src/chain/mod.rs index f215cd978f03a..650fcc405f7e1 100644 --- a/client/rpc-api/src/chain/mod.rs +++ b/client/rpc-api/src/chain/mod.rs @@ -18,20 +18,21 @@ //! Substrate blockchain API. -use jsonrpsee::{core::RpcResult, proc_macros::rpc}; -use sp_rpc::{list::ListOrValue, number::NumberOrHex}; - pub mod error; +use error::Error; +use jsonrpsee::proc_macros::rpc; +use sp_rpc::{list::ListOrValue, number::NumberOrHex}; + #[rpc(client, server)] pub trait ChainApi { /// Get header. #[method(name = "chain_getHeader", blocking)] - fn header(&self, hash: Option) -> RpcResult>; + fn header(&self, hash: Option) -> Result, Error>; /// Get header and body of a block. #[method(name = "chain_getBlock", blocking)] - fn block(&self, hash: Option) -> RpcResult>; + fn block(&self, hash: Option) -> Result, Error>; /// Get hash of the n-th block in the canon chain. /// @@ -40,11 +41,11 @@ pub trait ChainApi { fn block_hash( &self, hash: Option>, - ) -> RpcResult>>; + ) -> Result>, Error>; /// Get hash of the last finalized block in the canon chain. #[method(name = "chain_getFinalizedHead", aliases = ["chain_getFinalisedHead"], blocking)] - fn finalized_head(&self) -> RpcResult; + fn finalized_head(&self) -> Result; /// All head subscription. #[subscription( @@ -52,7 +53,7 @@ pub trait ChainApi { unsubscribe = "chain_unsubscribeAllHeads", item = Header )] - fn subscribe_all_heads(&self); + async fn subscribe_all_heads(&self); /// New head subscription. #[subscription( @@ -62,7 +63,7 @@ pub trait ChainApi { unsubscribe_aliases = ["unsubscribe_newHead", "chain_unsubscribeNewHead"], item = Header )] - fn subscribe_new_heads(&self); + async fn subscribe_new_heads(&self); /// Finalized head subscription. #[subscription( @@ -72,5 +73,5 @@ pub trait ChainApi { unsubscribe_aliases = ["chain_unsubscribeFinalisedHeads"], item = Header )] - fn subscribe_finalized_heads(&self); + async fn subscribe_finalized_heads(&self); } diff --git a/client/rpc-api/src/child_state/mod.rs b/client/rpc-api/src/child_state/mod.rs index a184677a721b5..70f304ea8e02d 100644 --- a/client/rpc-api/src/child_state/mod.rs +++ b/client/rpc-api/src/child_state/mod.rs @@ -17,8 +17,8 @@ // along with this program. If not, see . //! Substrate child state API -use crate::state::ReadProof; -use jsonrpsee::{core::RpcResult, proc_macros::rpc}; +use crate::state::{Error, ReadProof}; +use jsonrpsee::proc_macros::rpc; use sp_core::storage::{PrefixedStorageKey, StorageData, StorageKey}; /// Substrate child state API @@ -35,7 +35,7 @@ pub trait ChildStateApi { child_storage_key: PrefixedStorageKey, prefix: StorageKey, hash: Option, - ) -> RpcResult>; + ) -> Result, Error>; /// Returns the keys with prefix from a child storage with pagination support. /// Up to `count` keys will be returned. @@ -48,7 +48,7 @@ pub trait ChildStateApi { count: u32, start_key: Option, hash: Option, - ) -> RpcResult>; + ) -> Result, Error>; /// Returns a child storage entry at a specific block's state. #[method(name = "childstate_getStorage", blocking)] @@ -57,7 +57,7 @@ pub trait ChildStateApi { child_storage_key: PrefixedStorageKey, key: StorageKey, hash: Option, - ) -> RpcResult>; + ) -> Result, Error>; /// Returns child storage entries for multiple keys at a specific block's state. #[method(name = "childstate_getStorageEntries", blocking)] @@ -66,7 +66,7 @@ pub trait ChildStateApi { child_storage_key: PrefixedStorageKey, keys: Vec, hash: Option, - ) -> RpcResult>>; + ) -> Result>, Error>; /// Returns the hash of a child storage entry at a block's state. #[method(name = "childstate_getStorageHash", blocking)] @@ -75,7 +75,7 @@ pub trait ChildStateApi { child_storage_key: PrefixedStorageKey, key: StorageKey, hash: Option, - ) -> RpcResult>; + ) -> Result, Error>; /// Returns the size of a child storage entry at a block's state. #[method(name = "childstate_getStorageSize", blocking)] @@ -84,7 +84,7 @@ pub trait ChildStateApi { child_storage_key: PrefixedStorageKey, key: StorageKey, hash: Option, - ) -> RpcResult>; + ) -> Result, Error>; /// Returns proof of storage for child key entries at a specific block's state. #[method(name = "state_getChildReadProof", blocking)] @@ -93,5 +93,5 @@ pub trait ChildStateApi { child_storage_key: PrefixedStorageKey, keys: Vec, hash: Option, - ) -> RpcResult>; + ) -> Result, Error>; } diff --git a/client/rpc-api/src/dev/error.rs b/client/rpc-api/src/dev/error.rs index 8e4ddb55e35d7..f70e368b87389 100644 --- a/client/rpc-api/src/dev/error.rs +++ b/client/rpc-api/src/dev/error.rs @@ -18,10 +18,10 @@ //! Error helpers for Dev RPC module. -use jsonrpsee::{ - core::Error as JsonRpseeError, - types::error::{CallError, ErrorObject}, -}; +use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned}; + +/// Dev RPC Result type. +pub type Result = std::result::Result; /// Dev RPC errors. #[derive(Debug, thiserror::Error)] @@ -46,21 +46,16 @@ pub enum Error { /// Base error code for all dev errors. const BASE_ERROR: i32 = crate::error::base::DEV; -impl From for JsonRpseeError { +impl From for ErrorObjectOwned { fn from(e: Error) -> Self { let msg = e.to_string(); match e { - Error::BlockQueryError(_) => - CallError::Custom(ErrorObject::owned(BASE_ERROR + 1, msg, None::<()>)), - Error::BlockExecutionFailed => - CallError::Custom(ErrorObject::owned(BASE_ERROR + 3, msg, None::<()>)), - Error::WitnessCompactionFailed => - CallError::Custom(ErrorObject::owned(BASE_ERROR + 4, msg, None::<()>)), - Error::ProofExtractionFailed => - CallError::Custom(ErrorObject::owned(BASE_ERROR + 5, msg, None::<()>)), + Error::BlockQueryError(_) => ErrorObject::owned(BASE_ERROR + 1, msg, None::<()>), + Error::BlockExecutionFailed => ErrorObject::owned(BASE_ERROR + 3, msg, None::<()>), + Error::WitnessCompactionFailed => ErrorObject::owned(BASE_ERROR + 4, msg, None::<()>), + Error::ProofExtractionFailed => ErrorObject::owned(BASE_ERROR + 5, msg, None::<()>), Error::UnsafeRpcCalled(e) => e.into(), } - .into() } } diff --git a/client/rpc-api/src/dev/mod.rs b/client/rpc-api/src/dev/mod.rs index bc7216199dd74..5bee6df73ba93 100644 --- a/client/rpc-api/src/dev/mod.rs +++ b/client/rpc-api/src/dev/mod.rs @@ -23,7 +23,8 @@ pub mod error; use codec::{Decode, Encode}; -use jsonrpsee::{core::RpcResult, proc_macros::rpc}; +use error::Error; +use jsonrpsee::proc_macros::rpc; use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; @@ -59,5 +60,5 @@ pub trait DevApi { /// at the queried node. If either the specified block or the parent is pruned, /// this function will return `None`. #[method(name = "dev_getBlockStats")] - fn block_stats(&self, block_hash: Hash) -> RpcResult>; + fn block_stats(&self, block_hash: Hash) -> Result, Error>; } diff --git a/client/rpc-api/src/lib.rs b/client/rpc-api/src/lib.rs index b99c237dc859b..a152c5a0de503 100644 --- a/client/rpc-api/src/lib.rs +++ b/client/rpc-api/src/lib.rs @@ -25,7 +25,7 @@ mod error; mod policy; -pub use policy::DenyUnsafe; +pub use policy::{DenyUnsafe, UnsafeRpcError}; pub mod author; pub mod chain; diff --git a/client/rpc-api/src/offchain/error.rs b/client/rpc-api/src/offchain/error.rs index 679e100089734..ae5771981ea96 100644 --- a/client/rpc-api/src/offchain/error.rs +++ b/client/rpc-api/src/offchain/error.rs @@ -18,10 +18,7 @@ //! Offchain RPC errors. -use jsonrpsee::{ - core::Error as JsonRpseeError, - types::error::{CallError, ErrorObject}, -}; +use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned}; /// Offchain RPC Result type. pub type Result = std::result::Result; @@ -40,15 +37,14 @@ pub enum Error { /// Base error code for all offchain errors. const BASE_ERROR: i32 = crate::error::base::OFFCHAIN; -impl From for JsonRpseeError { +impl From for ErrorObjectOwned { fn from(e: Error) -> Self { match e { - Error::UnavailableStorageKind => CallError::Custom(ErrorObject::owned( + Error::UnavailableStorageKind => ErrorObject::owned( BASE_ERROR + 1, "This storage kind is not available yet", None::<()>, - )) - .into(), + ), Error::UnsafeRpcCalled(e) => e.into(), } } diff --git a/client/rpc-api/src/offchain/mod.rs b/client/rpc-api/src/offchain/mod.rs index cd42d6db35081..469e22d2b3fae 100644 --- a/client/rpc-api/src/offchain/mod.rs +++ b/client/rpc-api/src/offchain/mod.rs @@ -18,19 +18,20 @@ //! Substrate offchain API. -use jsonrpsee::{core::RpcResult, proc_macros::rpc}; -use sp_core::{offchain::StorageKind, Bytes}; - pub mod error; +use error::Error; +use jsonrpsee::proc_macros::rpc; +use sp_core::{offchain::StorageKind, Bytes}; + /// Substrate offchain RPC API #[rpc(client, server)] pub trait OffchainApi { /// Set offchain local storage under given key and prefix. #[method(name = "offchain_localStorageSet")] - fn set_local_storage(&self, kind: StorageKind, key: Bytes, value: Bytes) -> RpcResult<()>; + fn set_local_storage(&self, kind: StorageKind, key: Bytes, value: Bytes) -> Result<(), Error>; /// Get offchain local storage under given key and prefix. #[method(name = "offchain_localStorageGet")] - fn get_local_storage(&self, kind: StorageKind, key: Bytes) -> RpcResult>; + fn get_local_storage(&self, kind: StorageKind, key: Bytes) -> Result, Error>; } diff --git a/client/rpc-api/src/policy.rs b/client/rpc-api/src/policy.rs index 799898fb7cf53..c0847de89d2c6 100644 --- a/client/rpc-api/src/policy.rs +++ b/client/rpc-api/src/policy.rs @@ -21,13 +21,7 @@ //! Contains a `DenyUnsafe` type that can be used to deny potentially unsafe //! RPC when accessed externally. -use jsonrpsee::{ - core::Error as JsonRpseeError, - types::{ - error::{CallError, ErrorCode}, - ErrorObject, - }, -}; +use jsonrpsee::types::{error::ErrorCode, ErrorObject, ErrorObjectOwned}; /// Signifies whether a potentially unsafe RPC should be denied. #[derive(Clone, Copy, Debug)] @@ -61,18 +55,8 @@ impl std::fmt::Display for UnsafeRpcError { impl std::error::Error for UnsafeRpcError {} -impl From for CallError { - fn from(e: UnsafeRpcError) -> CallError { - CallError::Custom(ErrorObject::owned( - ErrorCode::MethodNotFound.code(), - e.to_string(), - None::<()>, - )) - } -} - -impl From for JsonRpseeError { - fn from(e: UnsafeRpcError) -> JsonRpseeError { - JsonRpseeError::Call(e.into()) +impl From for ErrorObjectOwned { + fn from(e: UnsafeRpcError) -> ErrorObjectOwned { + ErrorObject::owned(ErrorCode::MethodNotFound.code(), e.to_string(), None::<()>) } } diff --git a/client/rpc-api/src/state/error.rs b/client/rpc-api/src/state/error.rs index 9857784e3545c..f2396c63815c5 100644 --- a/client/rpc-api/src/state/error.rs +++ b/client/rpc-api/src/state/error.rs @@ -18,10 +18,8 @@ //! State RPC errors. -use jsonrpsee::{ - core::Error as JsonRpseeError, - types::error::{CallError, ErrorObject}, -}; +use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned}; + /// State RPC Result type. pub type Result = std::result::Result; @@ -57,16 +55,14 @@ pub enum Error { /// Base code for all state errors. const BASE_ERROR: i32 = crate::error::base::STATE; -impl From for JsonRpseeError { - fn from(e: Error) -> Self { +impl From for ErrorObjectOwned { + fn from(e: Error) -> ErrorObjectOwned { match e { Error::InvalidBlockRange { .. } => - CallError::Custom(ErrorObject::owned(BASE_ERROR + 1, e.to_string(), None::<()>)) - .into(), + ErrorObject::owned(BASE_ERROR + 1, e.to_string(), None::<()>), Error::InvalidCount { .. } => - CallError::Custom(ErrorObject::owned(BASE_ERROR + 2, e.to_string(), None::<()>)) - .into(), - e => Self::to_call_error(e), + ErrorObject::owned(BASE_ERROR + 2, e.to_string(), None::<()>), + e => ErrorObject::owned(BASE_ERROR + 3, e.to_string(), None::<()>), } } } diff --git a/client/rpc-api/src/state/helpers.rs b/client/rpc-api/src/state/helpers.rs index de20ee6f1bdfc..58b79ab64ea38 100644 --- a/client/rpc-api/src/state/helpers.rs +++ b/client/rpc-api/src/state/helpers.rs @@ -22,7 +22,7 @@ use serde::{Deserialize, Serialize}; use sp_core::Bytes; /// ReadProof struct returned by the RPC -#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ReadProof { /// Block hash used to generate the proof diff --git a/client/rpc-api/src/state/mod.rs b/client/rpc-api/src/state/mod.rs index dbc2a505456a5..62d846f8e51de 100644 --- a/client/rpc-api/src/state/mod.rs +++ b/client/rpc-api/src/state/mod.rs @@ -18,7 +18,7 @@ //! Substrate state API. -use jsonrpsee::{core::RpcResult, proc_macros::rpc}; +use jsonrpsee::proc_macros::rpc; use sp_core::{ storage::{StorageChangeSet, StorageData, StorageKey}, Bytes, @@ -29,18 +29,23 @@ pub mod error; pub mod helpers; pub use self::helpers::ReadProof; +pub use error::Error; /// Substrate state API #[rpc(client, server)] pub trait StateApi { /// Call a method from the runtime API at a block's state. #[method(name = "state_call", aliases = ["state_callAt"], blocking)] - fn call(&self, name: String, bytes: Bytes, hash: Option) -> RpcResult; + fn call(&self, name: String, bytes: Bytes, hash: Option) -> Result; /// Returns the keys with prefix, leave empty to get all the keys. #[method(name = "state_getKeys", blocking)] #[deprecated(since = "2.0.0", note = "Please use `getKeysPaged` with proper paging support")] - fn storage_keys(&self, prefix: StorageKey, hash: Option) -> RpcResult>; + fn storage_keys( + &self, + prefix: StorageKey, + hash: Option, + ) -> Result, Error>; /// Returns the keys with prefix, leave empty to get all the keys #[method(name = "state_getPairs", blocking)] @@ -48,7 +53,7 @@ pub trait StateApi { &self, prefix: StorageKey, hash: Option, - ) -> RpcResult>; + ) -> Result, Error>; /// Returns the keys with prefix with pagination support. /// Up to `count` keys will be returned. @@ -60,27 +65,28 @@ pub trait StateApi { count: u32, start_key: Option, hash: Option, - ) -> RpcResult>; + ) -> Result, Error>; /// Returns a storage entry at a specific block's state. #[method(name = "state_getStorage", aliases = ["state_getStorageAt"], blocking)] - fn storage(&self, key: StorageKey, hash: Option) -> RpcResult>; + fn storage(&self, key: StorageKey, hash: Option) -> Result, Error>; /// Returns the hash of a storage entry at a block's state. #[method(name = "state_getStorageHash", aliases = ["state_getStorageHashAt"], blocking)] - fn storage_hash(&self, key: StorageKey, hash: Option) -> RpcResult>; + fn storage_hash(&self, key: StorageKey, hash: Option) -> Result, Error>; /// Returns the size of a storage entry at a block's state. #[method(name = "state_getStorageSize", aliases = ["state_getStorageSizeAt"])] - async fn storage_size(&self, key: StorageKey, hash: Option) -> RpcResult>; + async fn storage_size(&self, key: StorageKey, hash: Option) + -> Result, Error>; /// Returns the runtime metadata as an opaque blob. #[method(name = "state_getMetadata", blocking)] - fn metadata(&self, hash: Option) -> RpcResult; + fn metadata(&self, hash: Option) -> Result; /// Get the runtime version. #[method(name = "state_getRuntimeVersion", aliases = ["chain_getRuntimeVersion"], blocking)] - fn runtime_version(&self, hash: Option) -> RpcResult; + fn runtime_version(&self, hash: Option) -> Result; /// Query historical storage entries (by key) starting from a block given as the second /// parameter. @@ -95,7 +101,7 @@ pub trait StateApi { keys: Vec, block: Hash, hash: Option, - ) -> RpcResult>>; + ) -> Result>, Error>; /// Query storage entries (by key) at a block hash given as the second parameter. /// NOTE: Each StorageChangeSet in the result corresponds to exactly one element -- @@ -105,11 +111,15 @@ pub trait StateApi { &self, keys: Vec, at: Option, - ) -> RpcResult>>; + ) -> Result>, Error>; /// Returns proof of storage entries at a specific block's state. #[method(name = "state_getReadProof", blocking)] - fn read_proof(&self, keys: Vec, hash: Option) -> RpcResult>; + fn read_proof( + &self, + keys: Vec, + hash: Option, + ) -> Result, Error>; /// New runtime version subscription #[subscription( @@ -119,7 +129,7 @@ pub trait StateApi { unsubscribe_aliases = ["chain_unsubscribeRuntimeVersion"], item = RuntimeVersion, )] - fn subscribe_runtime_version(&self); + async fn subscribe_runtime_version(&self); /// New storage subscription #[subscription( @@ -127,7 +137,7 @@ pub trait StateApi { unsubscribe = "state_unsubscribeStorage", item = StorageChangeSet, )] - fn subscribe_storage(&self, keys: Option>); + async fn subscribe_storage(&self, keys: Option>); /// The `traceBlock` RPC provides a way to trace the re-execution of a single /// block, collecting Spans and Events from both the client and the relevant WASM runtime. @@ -288,5 +298,5 @@ pub trait StateApi { targets: Option, storage_keys: Option, methods: Option, - ) -> RpcResult; + ) -> Result; } diff --git a/client/rpc-api/src/statement/error.rs b/client/rpc-api/src/statement/error.rs index 8438cc3ec9e94..f8041864facad 100644 --- a/client/rpc-api/src/statement/error.rs +++ b/client/rpc-api/src/statement/error.rs @@ -18,10 +18,7 @@ //! Statement RPC errors. -use jsonrpsee::{ - core::Error as JsonRpseeError, - types::error::{CallError, ErrorObject}, -}; +use jsonrpsee::types::error::{ErrorObject, ErrorObjectOwned}; /// Statement RPC Result type. pub type Result = std::result::Result; @@ -40,15 +37,14 @@ pub enum Error { /// Base error code for all statement errors. const BASE_ERROR: i32 = crate::error::base::STATEMENT; -impl From for JsonRpseeError { +impl From for ErrorObjectOwned { fn from(e: Error) -> Self { match e { - Error::StatementStore(message) => CallError::Custom(ErrorObject::owned( + Error::StatementStore(message) => ErrorObject::owned( BASE_ERROR + 1, format!("Statement store error: {message}"), None::<()>, - )) - .into(), + ), Error::UnsafeRpcCalled(e) => e.into(), } } diff --git a/client/rpc-api/src/system/error.rs b/client/rpc-api/src/system/error.rs index 713ade9210d32..1e826a75ae622 100644 --- a/client/rpc-api/src/system/error.rs +++ b/client/rpc-api/src/system/error.rs @@ -19,9 +19,9 @@ //! System RPC module errors. use crate::system::helpers::Health; -use jsonrpsee::{ - core::Error as JsonRpseeError, - types::error::{CallError, ErrorObject}, +use jsonrpsee::types::{ + error::{ErrorCode, ErrorObject}, + ErrorObjectOwned, }; /// System RPC Result type. @@ -36,6 +36,12 @@ pub enum Error { /// Peer argument is malformatted. #[error("{0}")] MalformattedPeerArg(String), + /// Call to an unsafe RPC was denied. + #[error(transparent)] + UnsafeRpcCalled(#[from] crate::policy::UnsafeRpcError), + /// Internal error. + #[error("{0}")] + Internal(String), } // Base code for all system errors. @@ -45,17 +51,16 @@ const NOT_HEALTHY_ERROR: i32 = BASE_ERROR + 1; // Peer argument is malformatted. const MALFORMATTED_PEER_ARG_ERROR: i32 = BASE_ERROR + 2; -impl From for JsonRpseeError { - fn from(e: Error) -> Self { +impl From for ErrorObjectOwned { + fn from(e: Error) -> ErrorObjectOwned { match e { Error::NotHealthy(ref h) => - CallError::Custom(ErrorObject::owned(NOT_HEALTHY_ERROR, e.to_string(), Some(h))), - Error::MalformattedPeerArg(e) => CallError::Custom(ErrorObject::owned( - MALFORMATTED_PEER_ARG_ERROR + 2, - e, - None::<()>, - )), + ErrorObject::owned(NOT_HEALTHY_ERROR, e.to_string(), Some(h)), + Error::MalformattedPeerArg(e) => + ErrorObject::owned(MALFORMATTED_PEER_ARG_ERROR, e, None::<()>), + Error::UnsafeRpcCalled(e) => e.into(), + Error::Internal(e) => + ErrorObjectOwned::owned(ErrorCode::InternalError.code(), e, None::<()>), } - .into() } } diff --git a/client/rpc-api/src/system/helpers.rs b/client/rpc-api/src/system/helpers.rs index ad56dc3850093..ed642e0679eb3 100644 --- a/client/rpc-api/src/system/helpers.rs +++ b/client/rpc-api/src/system/helpers.rs @@ -38,7 +38,7 @@ pub struct SystemInfo { } /// Health struct returned by the RPC -#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Health { /// Number of connected peers @@ -58,7 +58,7 @@ impl fmt::Display for Health { } /// Network Peer information -#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PeerInfo { /// Peer ID @@ -72,7 +72,7 @@ pub struct PeerInfo { } /// The role the node is running as -#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum NodeRole { /// The node is a full node Full, @@ -81,7 +81,7 @@ pub enum NodeRole { } /// The state of the syncing of the node. -#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SyncState { /// Height of the block at which syncing started. diff --git a/client/rpc-api/src/system/mod.rs b/client/rpc-api/src/system/mod.rs index bf2e92bc27a01..c38fa8f3d8176 100644 --- a/client/rpc-api/src/system/mod.rs +++ b/client/rpc-api/src/system/mod.rs @@ -18,38 +18,36 @@ //! Substrate system API. -use jsonrpsee::{ - core::{JsonValue, RpcResult}, - proc_macros::rpc, -}; - -pub use self::helpers::{Health, NodeRole, PeerInfo, SyncState, SystemInfo}; - pub mod error; pub mod helpers; +use jsonrpsee::{core::JsonValue, proc_macros::rpc}; + +pub use self::helpers::{Health, NodeRole, PeerInfo, SyncState, SystemInfo}; +pub use error::Error; + /// Substrate system RPC API #[rpc(client, server)] pub trait SystemApi { /// Get the node's implementation name. Plain old string. #[method(name = "system_name")] - fn system_name(&self) -> RpcResult; + fn system_name(&self) -> Result; /// Get the node implementation's version. Should be a semver string. #[method(name = "system_version")] - fn system_version(&self) -> RpcResult; + fn system_version(&self) -> Result; /// Get the chain's name. Given as a string identifier. #[method(name = "system_chain")] - fn system_chain(&self) -> RpcResult; + fn system_chain(&self) -> Result; /// Get the chain's type. #[method(name = "system_chainType")] - fn system_type(&self) -> RpcResult; + fn system_type(&self) -> Result; /// Get a custom set of properties as a JSON object, defined in the chain spec. #[method(name = "system_properties")] - fn system_properties(&self) -> RpcResult; + fn system_properties(&self) -> Result; /// Return health status of the node. /// @@ -57,22 +55,22 @@ pub trait SystemApi { /// - connected to some peers (unless running in dev mode) /// - not performing a major sync #[method(name = "system_health")] - async fn system_health(&self) -> RpcResult; + async fn system_health(&self) -> Result; /// Returns the base58-encoded PeerId of the node. #[method(name = "system_localPeerId")] - async fn system_local_peer_id(&self) -> RpcResult; + async fn system_local_peer_id(&self) -> Result; /// Returns the multi-addresses that the local node is listening on /// /// The addresses include a trailing `/p2p/` with the local PeerId, and are thus suitable to /// be passed to `addReservedPeer` or as a bootnode address for example. #[method(name = "system_localListenAddresses")] - async fn system_local_listen_addresses(&self) -> RpcResult>; + async fn system_local_listen_addresses(&self) -> Result, Error>; /// Returns currently connected peers #[method(name = "system_peers")] - async fn system_peers(&self) -> RpcResult>>; + async fn system_peers(&self) -> Result>, Error>; /// Returns current state of the network. /// @@ -81,7 +79,7 @@ pub trait SystemApi { // TODO: the future of this call is uncertain: https://github.com/paritytech/substrate/issues/1890 // https://github.com/paritytech/substrate/issues/5541 #[method(name = "system_unstable_networkState")] - async fn system_network_state(&self) -> RpcResult; + async fn system_network_state(&self) -> Result; /// Adds a reserved peer. Returns the empty string or an error. The string /// parameter should encode a `p2p` multiaddr. @@ -89,25 +87,25 @@ pub trait SystemApi { /// `/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV` /// is an example of a valid, passing multiaddr with PeerId attached. #[method(name = "system_addReservedPeer")] - async fn system_add_reserved_peer(&self, peer: String) -> RpcResult<()>; + async fn system_add_reserved_peer(&self, peer: String) -> Result<(), Error>; /// Remove a reserved peer. Returns the empty string or an error. The string /// should encode only the PeerId e.g. `QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV`. #[method(name = "system_removeReservedPeer")] - async fn system_remove_reserved_peer(&self, peer_id: String) -> RpcResult<()>; + async fn system_remove_reserved_peer(&self, peer_id: String) -> Result<(), Error>; /// Returns the list of reserved peers #[method(name = "system_reservedPeers")] - async fn system_reserved_peers(&self) -> RpcResult>; + async fn system_reserved_peers(&self) -> Result, Error>; /// Returns the roles the node is running as. #[method(name = "system_nodeRoles")] - async fn system_node_roles(&self) -> RpcResult>; + async fn system_node_roles(&self) -> Result, Error>; /// Returns the state of the syncing of the node: starting block, current best block, highest /// known block. #[method(name = "system_syncState")] - async fn system_sync_state(&self) -> RpcResult>; + async fn system_sync_state(&self) -> Result, Error>; /// Adds the supplied directives to the current log filter /// @@ -115,9 +113,9 @@ pub trait SystemApi { /// /// `sync=debug,state=trace` #[method(name = "system_addLogFilter")] - fn system_add_log_filter(&self, directives: String) -> RpcResult<()>; + fn system_add_log_filter(&self, directives: String) -> Result<(), Error>; /// Resets the log filter to Substrate defaults #[method(name = "system_resetLogFilter")] - fn system_reset_log_filter(&self) -> RpcResult<()>; + fn system_reset_log_filter(&self) -> Result<(), Error>; } diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index 7047991126184..d985269dbd949 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee = { version = "0.16.2", features = ["server"] } +jsonrpsee = { version = "0.19.0", features = ["server"] } log = "0.4.17" serde_json = "1.0.85" tokio = { version = "1.22.0", features = ["parking_lot"] } diff --git a/client/rpc-servers/src/lib.rs b/client/rpc-servers/src/lib.rs index 92b31937a0cbb..f183a32389c8b 100644 --- a/client/rpc-servers/src/lib.rs +++ b/client/rpc-servers/src/lib.rs @@ -24,10 +24,7 @@ pub mod middleware; use http::header::HeaderValue; use jsonrpsee::{ - server::{ - middleware::proxy_get_request::ProxyGetRequestLayer, AllowHosts, ServerBuilder, - ServerHandle, - }, + server::{middleware::proxy_get_request::ProxyGetRequestLayer, AllowHosts}, RpcModule, }; use std::{error::Error as StdError, net::SocketAddr}; @@ -42,7 +39,7 @@ pub use jsonrpsee::core::{ const MEGABYTE: u32 = 1024 * 1024; /// Type alias for the JSON-RPC server. -pub type Server = ServerHandle; +pub type Server = jsonrpsee::server::ServerHandle; /// RPC server configuration. #[derive(Debug)] @@ -61,6 +58,8 @@ pub struct Config<'a, M: Send + Sync + 'static> { pub max_payload_out_mb: u32, /// Metrics. pub metrics: Option, + /// Message buffer size + pub message_buffer_capacity: u32, /// RPC API. pub rpc_api: RpcModule, /// Subscription ID provider. @@ -72,7 +71,7 @@ pub struct Config<'a, M: Send + Sync + 'static> { /// Start RPC server listening on given address. pub async fn start_server( config: Config<'_, M>, -) -> Result> { +) -> Result> { let Config { addrs, cors, @@ -81,6 +80,7 @@ pub async fn start_server( max_connections, max_subs_per_conn, metrics, + message_buffer_capacity, id_provider, tokio_handle, rpc_api, @@ -93,7 +93,7 @@ pub async fn start_server( .layer(ProxyGetRequestLayer::new("/health", "system_health")?) .layer(try_into_cors(cors)?); - let mut builder = ServerBuilder::new() + let mut builder = jsonrpsee::server::Server::builder() .max_request_body_size(max_payload_in_mb.saturating_mul(MEGABYTE)) .max_response_body_size(max_payload_out_mb.saturating_mul(MEGABYTE)) .max_connections(max_connections) @@ -101,6 +101,7 @@ pub async fn start_server( .ping_interval(std::time::Duration::from_secs(30)) .set_host_filtering(host_filter) .set_middleware(middleware) + .set_message_buffer_capacity(message_buffer_capacity) .custom_tokio_runtime(tokio_handle); if let Some(provider) = id_provider { @@ -113,11 +114,11 @@ pub async fn start_server( let (handle, addr) = if let Some(metrics) = metrics { let server = builder.set_logger(metrics).build(&addrs[..]).await?; let addr = server.local_addr(); - (server.start(rpc_api)?, addr) + (server.start(rpc_api), addr) } else { let server = builder.build(&addrs[..]).await?; let addr = server.local_addr(); - (server.start(rpc_api)?, addr) + (server.start(rpc_api), addr) }; log::info!( @@ -149,9 +150,9 @@ fn build_rpc_api(mut rpc_api: RpcModule) -> RpcModu rpc_api .register_method("rpc_methods", move |_, _| { - Ok(serde_json::json!({ + serde_json::json!({ "methods": available_methods, - })) + }) }) .expect("infallible all other methods have their own address space; qed"); diff --git a/client/rpc-servers/src/middleware.rs b/client/rpc-servers/src/middleware.rs index c3e17c7852f10..fabb64eafa797 100644 --- a/client/rpc-servers/src/middleware.rs +++ b/client/rpc-servers/src/middleware.rs @@ -18,7 +18,9 @@ //! RPC middleware to collect prometheus metrics on RPC calls. -use jsonrpsee::server::logger::{HttpRequest, Logger, MethodKind, Params, TransportProtocol}; +use jsonrpsee::server::logger::{ + HttpRequest, Logger, MethodKind, Params, SuccessOrError, TransportProtocol, +}; use prometheus_endpoint::{ register, Counter, CounterVec, HistogramOpts, HistogramVec, Opts, PrometheusError, Registry, U64, @@ -176,7 +178,7 @@ impl Logger for RpcMetrics { fn on_result( &self, name: &str, - success: bool, + success_or_error: SuccessOrError, started_at: Self::Instant, transport: TransportProtocol, ) { @@ -197,7 +199,7 @@ impl Logger for RpcMetrics { name, // the label "is_error", so `success` should be regarded as false // and vice-versa to be registrered correctly. - if success { "false" } else { "true" }, + if success_or_error.is_success() { "false" } else { "true" }, ]) .inc(); } diff --git a/client/rpc-spec-v2/Cargo.toml b/client/rpc-spec-v2/Cargo.toml index 59abeefcf26ec..68a55d2074f6d 100644 --- a/client/rpc-spec-v2/Cargo.toml +++ b/client/rpc-spec-v2/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee = { version = "0.16.2", features = ["client-core", "server", "macros"] } +jsonrpsee = { version = "0.19.0", features = ["client-core", "server", "macros"] } # Internal chain structures for "chain_spec". sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" } # Pool for submitting extrinsics required by "transaction" @@ -34,15 +34,18 @@ tokio-stream = { version = "0.1", features = ["sync"] } array-bytes = "4.1" log = "0.4.17" futures-util = { version = "0.3.19", default-features = false } +sc-rpc = { path = "../rpc" } [dev-dependencies] serde_json = "1.0" -tokio = { version = "1.22.0", features = ["macros"] } +tokio = { version = "1.22.0", features = ["macros", "time", "rt-multi-thread"] } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" } sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } +sc-rpc = { path = "../rpc", features = ["test-helpers"] } sc-service = { version = "0.10.0-dev", features = ["test-helpers"], path = "../service" } sc-utils = { version = "4.0.0-dev", path = "../utils" } assert_matches = "1.3.0" +tracing-subscriber = { version = "0.3.3", features = ["env-filter"] } diff --git a/client/rpc-spec-v2/src/chain_head/api.rs b/client/rpc-spec-v2/src/chain_head/api.rs index ee8caa37bafbe..61e6792bb4198 100644 --- a/client/rpc-spec-v2/src/chain_head/api.rs +++ b/client/rpc-spec-v2/src/chain_head/api.rs @@ -21,6 +21,7 @@ //! API trait of the chain head. use crate::chain_head::event::{ChainHeadEvent, FollowEvent, NetworkConfig}; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; +use sc_rpc::utils::SubscriptionResponse; #[rpc(client, server)] pub trait ChainHeadApi { @@ -34,7 +35,10 @@ pub trait ChainHeadApi { unsubscribe = "chainHead_unstable_unfollow", item = FollowEvent, )] - fn chain_head_unstable_follow(&self, with_runtime: bool); + async fn chain_head_unstable_follow( + &self, + with_runtime: bool, + ) -> SubscriptionResponse>; /// Retrieves the body (list of transactions) of a pinned block. /// @@ -52,12 +56,12 @@ pub trait ChainHeadApi { unsubscribe = "chainHead_unstable_stopBody", item = ChainHeadEvent, )] - fn chain_head_unstable_body( + async fn chain_head_unstable_body( &self, follow_subscription: String, hash: Hash, network_config: Option, - ); + ) -> SubscriptionResponse>; /// Retrieves the header of a pinned block. /// @@ -96,14 +100,14 @@ pub trait ChainHeadApi { unsubscribe = "chainHead_unstable_stopStorage", item = ChainHeadEvent, )] - fn chain_head_unstable_storage( + async fn chain_head_unstable_storage( &self, follow_subscription: String, hash: Hash, key: String, child_key: Option, network_config: Option, - ); + ) -> SubscriptionResponse>>; /// Call into the Runtime API at a specified block's state. /// @@ -115,14 +119,14 @@ pub trait ChainHeadApi { unsubscribe = "chainHead_unstable_stopCall", item = ChainHeadEvent, )] - fn chain_head_unstable_call( + async fn chain_head_unstable_call( &self, follow_subscription: String, hash: Hash, function: String, call_parameters: String, network_config: Option, - ); + ) -> SubscriptionResponse>; /// Unpin a block reported by the `follow` method. /// diff --git a/client/rpc-spec-v2/src/chain_head/chain_head.rs b/client/rpc-spec-v2/src/chain_head/chain_head.rs index 0f2d55f100929..3fb2ae94279fb 100644 --- a/client/rpc-spec-v2/src/chain_head/chain_head.rs +++ b/client/rpc-spec-v2/src/chain_head/chain_head.rs @@ -29,17 +29,17 @@ use crate::{ SubscriptionTaskExecutor, }; use codec::Encode; -use futures::future::FutureExt; use jsonrpsee::{ core::{async_trait, RpcResult}, - types::{SubscriptionEmptyError, SubscriptionId, SubscriptionResult}, - SubscriptionSink, + types::{ErrorObjectOwned, SubscriptionId}, + PendingSubscriptionAcceptError, PendingSubscriptionSink, SubscriptionSink, }; use log::debug; use sc_client_api::{ Backend, BlockBackend, BlockchainEvents, CallExecutor, ChildInfo, ExecutorProvider, StorageKey, StorageProvider, }; +use sc_rpc::utils::SubscriptionResponse; use sp_api::CallApiAt; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; use sp_core::{hexdisplay::HexDisplay, storage::well_known_keys, traits::CallContext, Bytes}; @@ -91,45 +91,62 @@ impl, Block: BlockT, Client> ChainHead { } /// Accept the subscription and return the subscription ID on success. - fn accept_subscription( + async fn accept_subscription( &self, - sink: &mut SubscriptionSink, - ) -> Result { + pending: PendingSubscriptionSink, + ) -> Result<(SubscriptionSink, String), PendingSubscriptionAcceptError> { // The subscription must be accepted before it can provide a valid subscription ID. - sink.accept()?; - - let Some(sub_id) = sink.subscription_id() else { - // This can only happen if the subscription was not accepted. - return Err(SubscriptionEmptyError) - }; + let sink = pending.accept().await?; // Get the string representation for the subscription. - let sub_id = match sub_id { + let sub_id = match sink.subscription_id() { SubscriptionId::Num(num) => num.to_string(), SubscriptionId::Str(id) => id.into_owned().into(), }; - Ok(sub_id) + Ok((sink, sub_id)) + } +} + +struct MaybePendingSubscription(Option); + +impl MaybePendingSubscription { + pub fn new(p: PendingSubscriptionSink) -> Self { + Self(Some(p)) + } + + pub async fn accept(&mut self) -> Result { + if let Some(p) = self.0.take() { + p.accept().await + } else { + Err(PendingSubscriptionAcceptError) + } + } + + pub async fn reject(&mut self, err: impl Into) { + if let Some(p) = self.0.take() { + p.reject(err).await; + } } } /// Parse hex-encoded string parameter as raw bytes. /// /// If the parsing fails, the subscription is rejected. -fn parse_hex_param( - sink: &mut SubscriptionSink, +async fn parse_hex_param( + pending: &mut MaybePendingSubscription, param: String, -) -> Result, SubscriptionEmptyError> { +) -> Result, PendingSubscriptionAcceptError> { // Methods can accept empty parameters. if param.is_empty() { - return Ok(Default::default()) + return Ok(Vec::new()) } match array_bytes::hex2bytes(¶m) { Ok(bytes) => Ok(bytes), Err(_) => { - let _ = sink.reject(ChainHeadRpcError::InvalidParam(param)); - Err(SubscriptionEmptyError) + pending.reject(ChainHeadRpcError::InvalidParam(param)).await; + Err(PendingSubscriptionAcceptError) }, } } @@ -149,77 +166,74 @@ where + StorageProvider + 'static, { - fn chain_head_unstable_follow( + async fn chain_head_unstable_follow( &self, - mut sink: SubscriptionSink, - with_runtime: bool, - ) -> SubscriptionResult { - let sub_id = match self.accept_subscription(&mut sink) { - Ok(sub_id) => sub_id, - Err(err) => { - sink.close(ChainHeadRpcError::InvalidSubscriptionID); - return Err(err) - }, + pending: PendingSubscriptionSink, + runtime_updates: bool, + ) -> SubscriptionResponse> { + let Ok((sink, sub_id)) = self.accept_subscription(pending).await else { + return SubscriptionResponse::Closed; }; // Keep track of the subscription. - let Some(rx_stop) = self.subscriptions.insert_subscription(sub_id.clone(), with_runtime) else { + let Some(rx_stop) = self.subscriptions.insert_subscription(sub_id.clone(), runtime_updates) else { // Inserting the subscription can only fail if the JsonRPSee // generated a duplicate subscription ID. debug!(target: LOG_TARGET, "[follow][id={:?}] Subscription already accepted", sub_id); - let _ = sink.send(&FollowEvent::::Stop); - return Ok(()) + return SubscriptionResponse::Event(FollowEvent::Stop); }; debug!(target: LOG_TARGET, "[follow][id={:?}] Subscription accepted", sub_id); let subscriptions = self.subscriptions.clone(); let backend = self.backend.clone(); let client = self.client.clone(); - let fut = async move { - let mut chain_head_follow = ChainHeadFollower::new( - client, - backend, - subscriptions.clone(), - with_runtime, - sub_id.clone(), - ); + let sub_id2 = sub_id.clone(); - chain_head_follow.generate_events(sink, rx_stop).await; + let res = sc_rpc::utils::spawn_subscription_task(&self.executor, async move { + let mut chain_head_follow = + ChainHeadFollower::new(client, backend, subscriptions, runtime_updates, sub_id2); - subscriptions.remove_subscription(&sub_id); - debug!(target: LOG_TARGET, "[follow][id={:?}] Subscription removed", sub_id); - }; + chain_head_follow.generate_events(sink, rx_stop).await + }) + .await; - self.executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); - Ok(()) + self.subscriptions.remove_subscription(&sub_id); + debug!(target: LOG_TARGET, "[follow][id={:?}] Subscription removed", sub_id); + + res } - fn chain_head_unstable_body( + async fn chain_head_unstable_body( &self, - mut sink: SubscriptionSink, + pending: PendingSubscriptionSink, follow_subscription: String, hash: Block::Hash, _network_config: Option, - ) -> SubscriptionResult { + ) -> SubscriptionResponse> { let client = self.client.clone(); let subscriptions = self.subscriptions.clone(); let block_guard = match subscriptions.lock_block(&follow_subscription, hash) { - Ok(block) => block, + Ok(block) => { + if pending.accept().await.is_err() { + return SubscriptionResponse::Closed + } + block + }, Err(SubscriptionManagementError::SubscriptionAbsent) => { // Invalid invalid subscription ID. - let _ = sink.send(&ChainHeadEvent::::Disjoint); - return Ok(()) + let _sink = pending.accept().await; + return SubscriptionResponse::Event(ChainHeadEvent::Disjoint) }, Err(SubscriptionManagementError::BlockHashAbsent) => { // Block is not part of the subscription. - let _ = sink.reject(ChainHeadRpcError::InvalidBlock); - return Ok(()) + pending.reject(ChainHeadRpcError::InvalidBlock).await; + return SubscriptionResponse::Closed }, Err(error) => { - let _ = sink.send(&ChainHeadEvent::::Error(ErrorEvent { + let _sink = pending.accept().await; + return SubscriptionResponse::Event(ChainHeadEvent::Error(ErrorEvent { error: error.to_string(), - })); - return Ok(()) + })) }, }; @@ -244,11 +258,10 @@ where }, Err(error) => ChainHeadEvent::Error(ErrorEvent { error: error.to_string() }), }; - let _ = sink.send(&event); + SubscriptionResponse::Event(event) }; - self.executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); - Ok(()) + sc_rpc::utils::spawn_subscription_task(&self.executor, fut).await } fn chain_head_unstable_header( @@ -280,42 +293,55 @@ where Ok(self.genesis_hash.clone()) } - fn chain_head_unstable_storage( + async fn chain_head_unstable_storage( &self, - mut sink: SubscriptionSink, + pending: PendingSubscriptionSink, follow_subscription: String, hash: Block::Hash, key: String, child_key: Option, _network_config: Option, - ) -> SubscriptionResult { - let key = StorageKey(parse_hex_param(&mut sink, key)?); + ) -> SubscriptionResponse>> { + let mut pending = MaybePendingSubscription::new(pending); + let Ok(key) = parse_hex_param(&mut pending, key).await.map(|k| StorageKey(k)) else { + return SubscriptionResponse::Closed; + }; - let child_key = child_key - .map(|child_key| parse_hex_param(&mut sink, child_key)) - .transpose()? - .map(ChildInfo::new_default_from_vec); + let child_key = match child_key { + Some(k) => { + let Ok(key) = parse_hex_param(&mut pending, k).await else { + return SubscriptionResponse::Closed; + }; + Some(ChildInfo::new_default_from_vec(key)) + }, + None => None, + }; let client = self.client.clone(); let subscriptions = self.subscriptions.clone(); let block_guard = match subscriptions.lock_block(&follow_subscription, hash) { - Ok(block) => block, + Ok(block) => { + if pending.accept().await.is_err() { + return SubscriptionResponse::Closed + } + block + }, Err(SubscriptionManagementError::SubscriptionAbsent) => { + let _sink = pending.accept().await; // Invalid invalid subscription ID. - let _ = sink.send(&ChainHeadEvent::::Disjoint); - return Ok(()) + return SubscriptionResponse::Event(ChainHeadEvent::Disjoint) }, Err(SubscriptionManagementError::BlockHashAbsent) => { // Block is not part of the subscription. - let _ = sink.reject(ChainHeadRpcError::InvalidBlock); - return Ok(()) + pending.reject(ChainHeadRpcError::InvalidBlock).await; + return SubscriptionResponse::Closed }, Err(error) => { - let _ = sink.send(&ChainHeadEvent::::Error(ErrorEvent { + let _sink = pending.accept().await; + return SubscriptionResponse::Event(ChainHeadEvent::Error(ErrorEvent { error: error.to_string(), - })); - return Ok(()) + })) }, }; @@ -328,9 +354,9 @@ where if well_known_keys::is_default_child_storage_key(child_key.storage_key()) || well_known_keys::is_child_storage_key(child_key.storage_key()) { - let _ = sink - .send(&ChainHeadEvent::Done(ChainHeadResult { result: None:: })); - return + return SubscriptionResponse::Event(ChainHeadEvent::Done(ChainHeadResult { + result: None::, + })) } let res = client @@ -343,8 +369,7 @@ where .unwrap_or_else(|error| { ChainHeadEvent::Error(ErrorEvent { error: error.to_string() }) }); - let _ = sink.send(&res); - return + return SubscriptionResponse::Event(res) } // The main key must not be prefixed with b":child_storage:" nor @@ -352,9 +377,9 @@ where if well_known_keys::is_default_child_storage_key(&key.0) || well_known_keys::is_child_storage_key(&key.0) { - let _ = - sink.send(&ChainHeadEvent::Done(ChainHeadResult { result: None:: })); - return + return SubscriptionResponse::Event(ChainHeadEvent::Done(ChainHeadResult { + result: None::, + })) } // Main root trie storage query. @@ -368,23 +393,27 @@ where .unwrap_or_else(|error| { ChainHeadEvent::Error(ErrorEvent { error: error.to_string() }) }); - let _ = sink.send(&res); + + SubscriptionResponse::Event(res) }; - self.executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); - Ok(()) + sc_rpc::utils::spawn_subscription_task(&self.executor, fut).await } - fn chain_head_unstable_call( + async fn chain_head_unstable_call( &self, - mut sink: SubscriptionSink, + pending: PendingSubscriptionSink, follow_subscription: String, hash: Block::Hash, function: String, call_parameters: String, _network_config: Option, - ) -> SubscriptionResult { - let call_parameters = Bytes::from(parse_hex_param(&mut sink, call_parameters)?); + ) -> SubscriptionResponse> { + let mut pending = MaybePendingSubscription::new(pending); + + let Ok(call_parameters) = parse_hex_param(&mut pending, call_parameters).await.map(|b| Bytes::from(b)) else { + return SubscriptionResponse::Closed + }; let client = self.client.clone(); let subscriptions = self.subscriptions.clone(); @@ -392,30 +421,36 @@ where let block_guard = match subscriptions.lock_block(&follow_subscription, hash) { Ok(block) => block, Err(SubscriptionManagementError::SubscriptionAbsent) => { + let _ = pending.accept().await; // Invalid invalid subscription ID. - let _ = sink.send(&ChainHeadEvent::::Disjoint); - return Ok(()) + return SubscriptionResponse::Event(ChainHeadEvent::Disjoint) }, Err(SubscriptionManagementError::BlockHashAbsent) => { // Block is not part of the subscription. - let _ = sink.reject(ChainHeadRpcError::InvalidBlock); - return Ok(()) + pending.reject(ChainHeadRpcError::InvalidBlock).await; + return SubscriptionResponse::Closed }, Err(error) => { - let _ = sink.send(&ChainHeadEvent::::Error(ErrorEvent { + let _ = pending.accept().await; + return SubscriptionResponse::Event(ChainHeadEvent::Error(ErrorEvent { error: error.to_string(), - })); - return Ok(()) + })) }, }; let fut = async move { - // Reject subscription if with_runtime is false. + // Reject subscription if runtime_updates is false. if !block_guard.has_runtime() { - let _ = sink.reject(ChainHeadRpcError::InvalidParam( - "The runtime updates flag must be set".into(), - )); - return + pending + .reject(ChainHeadRpcError::InvalidParam( + "The runtime updates flag must be set".into(), + )) + .await; + return SubscriptionResponse::Closed + } + + if pending.accept().await.is_err() { + return SubscriptionResponse::Closed } let res = client @@ -435,11 +470,10 @@ where ChainHeadEvent::Error(ErrorEvent { error: error.to_string() }) }); - let _ = sink.send(&res); + SubscriptionResponse::Event(res) }; - self.executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); - Ok(()) + sc_rpc::utils::spawn_subscription_task(&self.executor, fut).await } fn chain_head_unstable_unpin( diff --git a/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs b/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs index cb6af8bd590b3..9b3fef6a9ccc0 100644 --- a/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs +++ b/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs @@ -31,17 +31,18 @@ use futures::{ stream::{self, Stream, StreamExt}, }; use futures_util::future::Either; -use jsonrpsee::SubscriptionSink; +use jsonrpsee::{SendTimeoutError, SubscriptionSink}; use log::{debug, error}; use sc_client_api::{ Backend, BlockBackend, BlockImportNotification, BlockchainEvents, FinalityNotification, }; +use sc_rpc::utils::SubscriptionResponse; use sp_api::CallApiAt; use sp_blockchain::{ Backend as BlockChainBackend, Error as BlockChainError, HeaderBackend, HeaderMetadata, Info, }; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use std::{collections::HashSet, sync::Arc}; +use std::{collections::HashSet, sync::Arc, time::Duration}; /// Generates the events of the `chainHead_follow` method. pub struct ChainHeadFollower, Block: BlockT, Client> { @@ -500,9 +501,10 @@ where startup_point: &StartupPoint, mut stream: EventStream, mut to_ignore: HashSet, - mut sink: SubscriptionSink, + sink: SubscriptionSink, rx_stop: oneshot::Receiver<()>, - ) where + ) -> SubscriptionResponse> + where EventStream: Stream> + Unpin, { let mut stream_item = stream.next(); @@ -528,37 +530,20 @@ where self.sub_id, err ); - let _ = sink.send(&FollowEvent::::Stop); - return + return SubscriptionResponse::Event(FollowEvent::Stop) }, }; for event in events { - let result = sink.send(&event); - - // Migration note: the new version of jsonrpsee returns Result<(), DisconnectError> - // The logic from `Err(err)` should be moved when building the new - // `SubscriptionMessage`. - - // For now, jsonrpsee returns: - // Ok(true): message sent - // Ok(false): client disconnected or subscription closed - // Err(err): serder serialization error of the event - if let Err(err) = result { - // Failed to submit event. - debug!( - target: LOG_TARGET, - "[follow][id={:?}] Failed to send event {:?}", self.sub_id, err - ); - - let _ = sink.send(&FollowEvent::::Stop); - return - } - - if let Ok(false) = result { - // Client disconnected or subscription was closed. - return - } + match sink + .send_timeout(sc_rpc::utils::to_sub_message(&event), Duration::from_secs(60)) + .await + { + Ok(_) => (), + Err(SendTimeoutError::Closed(_)) => return SubscriptionResponse::Closed, + Err(SendTimeoutError::Timeout(_)) => + return SubscriptionResponse::Event(FollowEvent::Stop), + }; } stream_item = stream.next(); @@ -567,27 +552,27 @@ where // If we got here either the substrate streams have closed // or the `Stop` receiver was triggered. - let _ = sink.send(&FollowEvent::::Stop); + SubscriptionResponse::Event(FollowEvent::Stop) } /// Generate the block events for the `chainHead_follow` method. pub async fn generate_events( &mut self, - mut sink: SubscriptionSink, + sink: SubscriptionSink, rx_stop: oneshot::Receiver<()>, - ) { + ) -> SubscriptionResponse> { + let client = self.client.clone(); + // Register for the new block and finalized notifications. - let stream_import = self - .client + let stream_import = client .import_notification_stream() .map(|notification| NotificationType::NewBlock(notification)); - let stream_finalized = self - .client + let stream_finalized = client .finality_notification_stream() .map(|notification| NotificationType::Finalized(notification)); - let startup_point = StartupPoint::from(self.client.info()); + let startup_point = StartupPoint::from(client.info()); let (initial_events, pruned_forks) = match self.generate_init_events(&startup_point) { Ok(blocks) => blocks, Err(err) => { @@ -597,8 +582,7 @@ where self.sub_id, err ); - let _ = sink.send(&FollowEvent::::Stop); - return + return SubscriptionResponse::Event(FollowEvent::Stop) }, }; @@ -607,6 +591,6 @@ where let stream = stream::once(futures::future::ready(initial)).chain(merged); self.submit_events(&startup_point, stream.boxed(), pruned_forks, sink, rx_stop) - .await; + .await } } diff --git a/client/rpc-spec-v2/src/chain_head/error.rs b/client/rpc-spec-v2/src/chain_head/error.rs index 3f31d985de0ff..680458a9cb1ef 100644 --- a/client/rpc-spec-v2/src/chain_head/error.rs +++ b/client/rpc-spec-v2/src/chain_head/error.rs @@ -18,10 +18,7 @@ //! Error helpers for `chainHead` RPC module. -use jsonrpsee::{ - core::Error as RpcError, - types::error::{CallError, ErrorObject}, -}; +use jsonrpsee::types::{error::ErrorObject, ErrorObjectOwned}; use sp_blockchain::Error as BlockchainError; /// ChainHead RPC errors. @@ -52,7 +49,7 @@ const INVALID_PARAM_ERROR: i32 = BASE_ERROR + 3; /// Invalid subscription ID. const INVALID_SUB_ID: i32 = BASE_ERROR + 4; -impl From for ErrorObject<'static> { +impl From for ErrorObjectOwned { fn from(e: Error) -> Self { let msg = e.to_string(); @@ -63,12 +60,5 @@ impl From for ErrorObject<'static> { Error::InvalidParam(_) => ErrorObject::owned(INVALID_PARAM_ERROR, msg, None::<()>), Error::InvalidSubscriptionID => ErrorObject::owned(INVALID_SUB_ID, msg, None::<()>), } - .into() - } -} - -impl From for RpcError { - fn from(e: Error) -> Self { - CallError::Custom(e.into()).into() } } diff --git a/client/rpc-spec-v2/src/chain_head/event.rs b/client/rpc-spec-v2/src/chain_head/event.rs index d0d4d1d43ac03..3c970729d6ab1 100644 --- a/client/rpc-spec-v2/src/chain_head/event.rs +++ b/client/rpc-spec-v2/src/chain_head/event.rs @@ -192,12 +192,10 @@ pub struct Finalized { /// The event generated by the `follow` method. /// /// The events are generated in the following order: -/// 1. Initialized - generated only once to signal the -/// latest finalized block +/// 1. Initialized - generated only once to signal the latest finalized block /// 2. NewBlock - a new block was added. -/// 3. BestBlockChanged - indicate that the best block -/// is now the one from this event. The block was -/// announced priorly with the `NewBlock` event. +/// 3. BestBlockChanged - indicate that the best block is now the one from this event. The block was +/// announced priorly with the `NewBlock` event. /// 4. Finalized - State the finalized and pruned blocks. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] diff --git a/client/rpc-spec-v2/src/chain_head/tests.rs b/client/rpc-spec-v2/src/chain_head/tests.rs index cb6e65f859133..79e4af0d94551 100644 --- a/client/rpc-spec-v2/src/chain_head/tests.rs +++ b/client/rpc-spec-v2/src/chain_head/tests.rs @@ -5,12 +5,14 @@ use assert_matches::assert_matches; use codec::{Decode, Encode}; use futures::Future; use jsonrpsee::{ - core::{error::Error, server::rpc_module::Subscription as RpcSubscription}, - types::{error::CallError, EmptyServerParams as EmptyParams}, + core::{ + error::Error, server::Subscription as RpcSubscription, EmptyServerParams as EmptyParams, + }, RpcModule, }; use sc_block_builder::BlockBuilderProvider; use sc_client_api::ChildInfo; +use sc_rpc::testing::{test_executor, TokioTestExecutor}; use sc_service::client::new_in_mem; use sp_api::BlockT; use sp_blockchain::HeaderBackend; @@ -18,7 +20,6 @@ use sp_consensus::BlockOrigin; use sp_core::{ hexdisplay::HexDisplay, storage::well_known_keys::{self, CODE}, - testing::TaskExecutor, }; use sp_version::RuntimeVersion; use std::{sync::Arc, time::Duration}; @@ -39,6 +40,12 @@ const VALUE: &[u8] = b"hello world"; const CHILD_STORAGE_KEY: &[u8] = b"child"; const CHILD_VALUE: &[u8] = b"child value"; +pub fn init_logger() { + let _ = tracing_subscriber::FmtSubscriber::builder() + .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .try_init(); +} + async fn get_next_event(sub: &mut RpcSubscription) -> T { let (event, _sub_id) = tokio::time::timeout(std::time::Duration::from_secs(60), sub.next()) .await @@ -73,14 +80,14 @@ async fn setup_api() -> ( let api = ChainHead::new( client.clone(), backend, - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, MAX_PINNED_BLOCKS, Duration::from_secs(MAX_PINNED_SECS), ) .into_rpc(); - let mut sub = api.subscribe("chainHead_unstable_follow", [true]).await.unwrap(); + let mut sub = api.subscribe_unbounded("chainHead_unstable_follow", [true]).await.unwrap(); let sub_id = sub.subscription_id(); let sub_id = serde_json::to_string(&sub_id).unwrap(); @@ -113,7 +120,7 @@ async fn follow_subscription_produces_blocks() { let api = ChainHead::new( client.clone(), backend, - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, MAX_PINNED_BLOCKS, Duration::from_secs(MAX_PINNED_SECS), @@ -121,7 +128,7 @@ async fn follow_subscription_produces_blocks() { .into_rpc(); let finalized_hash = client.info().finalized_hash; - let mut sub = api.subscribe("chainHead_unstable_follow", [false]).await.unwrap(); + let mut sub = api.subscribe_unbounded("chainHead_unstable_follow", [false]).await.unwrap(); // Initialized must always be reported first. let event: FollowEvent = get_next_event(&mut sub).await; @@ -171,7 +178,7 @@ async fn follow_with_runtime() { let api = ChainHead::new( client.clone(), backend, - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, MAX_PINNED_BLOCKS, Duration::from_secs(MAX_PINNED_SECS), @@ -179,7 +186,7 @@ async fn follow_with_runtime() { .into_rpc(); let finalized_hash = client.info().finalized_hash; - let mut sub = api.subscribe("chainHead_unstable_follow", [true]).await.unwrap(); + let mut sub = api.subscribe_unbounded("chainHead_unstable_follow", [true]).await.unwrap(); // Initialized must always be reported first. let event: FollowEvent = get_next_event(&mut sub).await; @@ -278,7 +285,7 @@ async fn get_genesis() { let api = ChainHead::new( client.clone(), backend, - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, MAX_PINNED_BLOCKS, Duration::from_secs(MAX_PINNED_SECS), @@ -309,7 +316,7 @@ async fn get_header() { .await .unwrap_err(); assert_matches!(err, - Error::Call(CallError::Custom(ref err)) if err.code() == 2001 && err.message() == "Invalid block hash" + Error::Call(e) if e.code() == 2001 && e.message() == "Invalid block hash" ); // Obtain the valid header. @@ -327,7 +334,7 @@ async fn get_body() { // Subscription ID is stale the disjoint event is emitted. let mut sub = api - .subscribe("chainHead_unstable_body", ["invalid_sub_id", &invalid_hash]) + .subscribe_unbounded("chainHead_unstable_body", ["invalid_sub_id", &invalid_hash]) .await .unwrap(); let event: ChainHeadEvent = get_next_event(&mut sub).await; @@ -335,15 +342,18 @@ async fn get_body() { // Valid subscription ID with invalid block hash will error. let err = api - .subscribe("chainHead_unstable_body", [&sub_id, &invalid_hash]) + .subscribe_unbounded("chainHead_unstable_body", [&sub_id, &invalid_hash]) .await .unwrap_err(); assert_matches!(err, - Error::Call(CallError::Custom(ref err)) if err.code() == 2001 && err.message() == "Invalid block hash" + Error::Call(err) if err.code() == 2001 && err.message() == "Invalid block hash" ); // Obtain valid the body (list of extrinsics). - let mut sub = api.subscribe("chainHead_unstable_body", [&sub_id, &block_hash]).await.unwrap(); + let mut sub = api + .subscribe_unbounded("chainHead_unstable_body", [&sub_id, &block_hash]) + .await + .unwrap(); let event: ChainHeadEvent = get_next_event(&mut sub).await; // Block contains no extrinsics. assert_matches!(event, @@ -373,7 +383,10 @@ async fn get_body() { FollowEvent::BestBlockChanged(_) ); - let mut sub = api.subscribe("chainHead_unstable_body", [&sub_id, &block_hash]).await.unwrap(); + let mut sub = api + .subscribe_unbounded("chainHead_unstable_body", [&sub_id, &block_hash]) + .await + .unwrap(); let event: ChainHeadEvent = get_next_event(&mut sub).await; // Hex encoded scale encoded string for the vector of extrinsics. let expected = format!("0x{:?}", HexDisplay::from(&block.extrinsics.encode())); @@ -384,13 +397,15 @@ async fn get_body() { #[tokio::test] async fn call_runtime() { + init_logger(); + let (_client, api, _sub, sub_id, block) = setup_api().await; let block_hash = format!("{:?}", block.header.hash()); let invalid_hash = format!("0x{:?}", HexDisplay::from(&INVALID_HASH)); // Subscription ID is stale the disjoint event is emitted. let mut sub = api - .subscribe( + .subscribe_unbounded( "chainHead_unstable_call", ["invalid_sub_id", &block_hash, "BabeApi_current_epoch", "0x00"], ) @@ -401,33 +416,33 @@ async fn call_runtime() { // Valid subscription ID with invalid block hash will error. let err = api - .subscribe( + .subscribe_unbounded( "chainHead_unstable_call", [&sub_id, &invalid_hash, "BabeApi_current_epoch", "0x00"], ) .await .unwrap_err(); assert_matches!(err, - Error::Call(CallError::Custom(ref err)) if err.code() == 2001 && err.message() == "Invalid block hash" + Error::Call(err) if err.code() == 2001 && err.message() == "Invalid block hash" ); - // Pass an invalid parameters that cannot be decode. + // Pass invalid parameters that cannot be decoded. let err = api - .subscribe( + .subscribe_unbounded( "chainHead_unstable_call", [&sub_id, &block_hash, "BabeApi_current_epoch", "0x0"], ) .await .unwrap_err(); assert_matches!(err, - Error::Call(CallError::Custom(ref err)) if err.code() == 2003 && err.message().contains("Invalid parameter") + Error::Call(err) if err.code() == 2003 && err.message().contains("Invalid parameter") ); let alice_id = AccountKeyring::Alice.to_account_id(); // Hex encoded scale encoded bytes representing the call parameters. let call_parameters = format!("0x{:?}", HexDisplay::from(&alice_id.encode())); let mut sub = api - .subscribe( + .subscribe_unbounded( "chainHead_unstable_call", [&sub_id, &block_hash, "AccountNonceApi_account_nonce", &call_parameters], ) @@ -442,7 +457,7 @@ async fn call_runtime() { // The `current_epoch` takes no parameters and not draining the input buffer // will cause the execution to fail. let mut sub = api - .subscribe( + .subscribe_unbounded( "chainHead_unstable_call", [&sub_id, &block_hash, "BabeApi_current_epoch", "0x00"], ) @@ -463,14 +478,14 @@ async fn call_runtime_without_flag() { let api = ChainHead::new( client.clone(), backend, - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, MAX_PINNED_BLOCKS, Duration::from_secs(MAX_PINNED_SECS), ) .into_rpc(); - let mut sub = api.subscribe("chainHead_unstable_follow", [false]).await.unwrap(); + let mut sub = api.subscribe_unbounded("chainHead_unstable_follow", [false]).await.unwrap(); let sub_id = sub.subscription_id(); let sub_id = serde_json::to_string(&sub_id).unwrap(); @@ -496,7 +511,7 @@ async fn call_runtime_without_flag() { let alice_id = AccountKeyring::Alice.to_account_id(); let call_parameters = format!("0x{:?}", HexDisplay::from(&alice_id.encode())); let err = api - .subscribe( + .subscribe_unbounded( "chainHead_unstable_call", [&sub_id, &block_hash, "AccountNonceApi_account_nonce", &call_parameters], ) @@ -504,12 +519,14 @@ async fn call_runtime_without_flag() { .unwrap_err(); assert_matches!(err, - Error::Call(CallError::Custom(ref err)) if err.code() == 2003 && err.message().contains("The runtime updates flag must be set") + Error::Call(err) if err.code() == 2003 && err.message().contains("The runtime updates flag must be set") ); } #[tokio::test] async fn get_storage() { + init_logger(); + let (mut client, api, mut block_sub, sub_id, block) = setup_api().await; let block_hash = format!("{:?}", block.header.hash()); let invalid_hash = format!("0x{:?}", HexDisplay::from(&INVALID_HASH)); @@ -517,7 +534,7 @@ async fn get_storage() { // Subscription ID is stale the disjoint event is emitted. let mut sub = api - .subscribe("chainHead_unstable_storage", ["invalid_sub_id", &invalid_hash, &key]) + .subscribe_unbounded("chainHead_unstable_storage", ["invalid_sub_id", &invalid_hash, &key]) .await .unwrap(); let event: ChainHeadEvent = get_next_event(&mut sub).await; @@ -525,16 +542,16 @@ async fn get_storage() { // Valid subscription ID with invalid block hash will error. let err = api - .subscribe("chainHead_unstable_storage", [&sub_id, &invalid_hash, &key]) + .subscribe_unbounded("chainHead_unstable_storage", [&sub_id, &invalid_hash, &key]) .await .unwrap_err(); assert_matches!(err, - Error::Call(CallError::Custom(ref err)) if err.code() == 2001 && err.message() == "Invalid block hash" + Error::Call(err) if err.code() == 2001 && err.message() == "Invalid block hash" ); // Valid call without storage at the key. let mut sub = api - .subscribe("chainHead_unstable_storage", [&sub_id, &block_hash, &key]) + .subscribe_unbounded("chainHead_unstable_storage", [&sub_id, &block_hash, &key]) .await .unwrap(); let event: ChainHeadEvent> = get_next_event(&mut sub).await; @@ -560,7 +577,7 @@ async fn get_storage() { // Valid call with storage at the key. let expected_value = Some(format!("0x{:?}", HexDisplay::from(&VALUE))); let mut sub = api - .subscribe("chainHead_unstable_storage", [&sub_id, &block_hash, &key]) + .subscribe_unbounded("chainHead_unstable_storage", [&sub_id, &block_hash, &key]) .await .unwrap(); let event: ChainHeadEvent> = get_next_event(&mut sub).await; @@ -571,7 +588,10 @@ async fn get_storage() { let genesis_hash = format!("{:?}", client.genesis_hash()); let expected_value = Some(format!("0x{:?}", HexDisplay::from(&CHILD_VALUE))); let mut sub = api - .subscribe("chainHead_unstable_storage", [&sub_id, &genesis_hash, &key, &child_info]) + .subscribe_unbounded( + "chainHead_unstable_storage", + [&sub_id, &genesis_hash, &key, &child_info], + ) .await .unwrap(); let event: ChainHeadEvent> = get_next_event(&mut sub).await; @@ -589,7 +609,7 @@ async fn get_storage_wrong_key() { prefixed_key.extend_from_slice(&KEY); let prefixed_key = format!("0x{:?}", HexDisplay::from(&prefixed_key)); let mut sub = api - .subscribe("chainHead_unstable_storage", [&sub_id, &block_hash, &prefixed_key]) + .subscribe_unbounded("chainHead_unstable_storage", [&sub_id, &block_hash, &prefixed_key]) .await .unwrap(); let event: ChainHeadEvent> = get_next_event(&mut sub).await; @@ -600,7 +620,7 @@ async fn get_storage_wrong_key() { prefixed_key.extend_from_slice(&KEY); let prefixed_key = format!("0x{:?}", HexDisplay::from(&prefixed_key)); let mut sub = api - .subscribe("chainHead_unstable_storage", [&sub_id, &block_hash, &prefixed_key]) + .subscribe_unbounded("chainHead_unstable_storage", [&sub_id, &block_hash, &prefixed_key]) .await .unwrap(); let event: ChainHeadEvent> = get_next_event(&mut sub).await; @@ -611,7 +631,10 @@ async fn get_storage_wrong_key() { prefixed_key.extend_from_slice(b"child"); let prefixed_key = format!("0x{:?}", HexDisplay::from(&prefixed_key)); let mut sub = api - .subscribe("chainHead_unstable_storage", [&sub_id, &block_hash, &key, &prefixed_key]) + .subscribe_unbounded( + "chainHead_unstable_storage", + [&sub_id, &block_hash, &key, &prefixed_key], + ) .await .unwrap(); let event: ChainHeadEvent> = get_next_event(&mut sub).await; @@ -622,7 +645,10 @@ async fn get_storage_wrong_key() { prefixed_key.extend_from_slice(b"child"); let prefixed_key = format!("0x{:?}", HexDisplay::from(&prefixed_key)); let mut sub = api - .subscribe("chainHead_unstable_storage", [&sub_id, &block_hash, &key, &prefixed_key]) + .subscribe_unbounded( + "chainHead_unstable_storage", + [&sub_id, &block_hash, &key, &prefixed_key], + ) .await .unwrap(); let event: ChainHeadEvent> = get_next_event(&mut sub).await; @@ -638,7 +664,7 @@ async fn follow_generates_initial_blocks() { let api = ChainHead::new( client.clone(), backend, - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, MAX_PINNED_BLOCKS, Duration::from_secs(MAX_PINNED_SECS), @@ -674,7 +700,7 @@ async fn follow_generates_initial_blocks() { let block_3_hash = block_3.header.hash(); client.import(BlockOrigin::Own, block_3.clone()).await.unwrap(); - let mut sub = api.subscribe("chainHead_unstable_follow", [false]).await.unwrap(); + let mut sub = api.subscribe_unbounded("chainHead_unstable_follow", [false]).await.unwrap(); // Initialized must always be reported first. let event: FollowEvent = get_next_event(&mut sub).await; @@ -766,14 +792,14 @@ async fn follow_exceeding_pinned_blocks() { let api = ChainHead::new( client.clone(), backend, - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, 2, Duration::from_secs(MAX_PINNED_SECS), ) .into_rpc(); - let mut sub = api.subscribe("chainHead_unstable_follow", [false]).await.unwrap(); + let mut sub = api.subscribe_unbounded("chainHead_unstable_follow", [false]).await.unwrap(); let block = client.new_block(Default::default()).unwrap().build().unwrap().block; client.import(BlockOrigin::Own, block.clone()).await.unwrap(); @@ -810,6 +836,8 @@ async fn follow_exceeding_pinned_blocks() { #[tokio::test] async fn follow_with_unpin() { + init_logger(); + let builder = TestClientBuilder::new(); let backend = builder.backend(); let mut client = Arc::new(builder.build()); @@ -817,14 +845,14 @@ async fn follow_with_unpin() { let api = ChainHead::new( client.clone(), backend, - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, 2, Duration::from_secs(MAX_PINNED_SECS), ) .into_rpc(); - let mut sub = api.subscribe("chainHead_unstable_follow", [false]).await.unwrap(); + let mut sub = api.subscribe_unbounded("chainHead_unstable_follow", [false]).await.unwrap(); let sub_id = sub.subscription_id(); let sub_id = serde_json::to_string(&sub_id).unwrap(); @@ -860,7 +888,7 @@ async fn follow_with_unpin() { .await .unwrap_err(); assert_matches!(err, - Error::Call(CallError::Custom(ref err)) if err.code() == 2001 && err.message() == "Invalid block hash" + Error::Call(err) if err.code() == 2001 && err.message() == "Invalid block hash" ); // To not exceed the number of pinned blocks, we need to unpin before the next import. @@ -898,7 +926,7 @@ async fn follow_prune_best_block() { let api = ChainHead::new( client.clone(), backend, - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, MAX_PINNED_BLOCKS, Duration::from_secs(MAX_PINNED_SECS), @@ -906,7 +934,7 @@ async fn follow_prune_best_block() { .into_rpc(); let finalized_hash = client.info().finalized_hash; - let mut sub = api.subscribe("chainHead_unstable_follow", [false]).await.unwrap(); + let mut sub = api.subscribe_unbounded("chainHead_unstable_follow", [false]).await.unwrap(); // Initialized must always be reported first. let event: FollowEvent = get_next_event(&mut sub).await; @@ -1055,7 +1083,7 @@ async fn follow_forks_pruned_block() { let api = ChainHead::new( client.clone(), backend, - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, MAX_PINNED_BLOCKS, Duration::from_secs(MAX_PINNED_SECS), @@ -1111,7 +1139,7 @@ async fn follow_forks_pruned_block() { // Block 4 and 5 are not pruned, pruning happens at height (N - 1). client.finalize_block(block_3_hash, None).unwrap(); - let mut sub = api.subscribe("chainHead_unstable_follow", [false]).await.unwrap(); + let mut sub = api.subscribe_unbounded("chainHead_unstable_follow", [false]).await.unwrap(); // Initialized must always be reported first. let event: FollowEvent = get_next_event(&mut sub).await; @@ -1169,7 +1197,7 @@ async fn follow_report_multiple_pruned_block() { let api = ChainHead::new( client.clone(), backend, - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, MAX_PINNED_BLOCKS, Duration::from_secs(MAX_PINNED_SECS), @@ -1226,7 +1254,7 @@ async fn follow_report_multiple_pruned_block() { let block_5 = block_builder.build().unwrap().block; let block_5_hash = block_5.header.hash(); client.import(BlockOrigin::Own, block_5.clone()).await.unwrap(); - let mut sub = api.subscribe("chainHead_unstable_follow", [false]).await.unwrap(); + let mut sub = api.subscribe_unbounded("chainHead_unstable_follow", [false]).await.unwrap(); // Initialized must always be reported first. let event: FollowEvent = get_next_event(&mut sub).await; @@ -1366,7 +1394,7 @@ async fn pin_block_references() { None, None, None, - Box::new(TaskExecutor::new()), + Box::new(TokioTestExecutor::new()), client_config, ) .unwrap(), @@ -1375,7 +1403,7 @@ async fn pin_block_references() { let api = ChainHead::new( client.clone(), backend.clone(), - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, 3, Duration::from_secs(MAX_PINNED_SECS), @@ -1399,7 +1427,7 @@ async fn pin_block_references() { } } - let mut sub = api.subscribe("chainHead_unstable_follow", [false]).await.unwrap(); + let mut sub = api.subscribe_unbounded("chainHead_unstable_follow", [false]).await.unwrap(); let sub_id = sub.subscription_id(); let sub_id = serde_json::to_string(&sub_id).unwrap(); @@ -1485,7 +1513,7 @@ async fn follow_finalized_before_new_block() { let api = ChainHead::new( client_mock.clone(), backend, - Arc::new(TaskExecutor::default()), + test_executor(), CHAIN_GENESIS, MAX_PINNED_BLOCKS, Duration::from_secs(MAX_PINNED_SECS), @@ -1497,7 +1525,7 @@ async fn follow_finalized_before_new_block() { let block_1_hash = block_1.header.hash(); client.import(BlockOrigin::Own, block_1.clone()).await.unwrap(); - let mut sub = api.subscribe("chainHead_unstable_follow", [false]).await.unwrap(); + let mut sub = api.subscribe_unbounded("chainHead_unstable_follow", [false]).await.unwrap(); // Trigger the `FinalizedNotification` for block 1 before the `BlockImportNotification`, and // expect for the `chainHead` to generate `NewBlock`, `BestBlock` and `Finalized` events. diff --git a/client/rpc-spec-v2/src/chain_spec/tests.rs b/client/rpc-spec-v2/src/chain_spec/tests.rs index 74aec01a2113e..64dcf164a7c8f 100644 --- a/client/rpc-spec-v2/src/chain_spec/tests.rs +++ b/client/rpc-spec-v2/src/chain_spec/tests.rs @@ -17,7 +17,7 @@ // along with this program. If not, see . use super::*; -use jsonrpsee::{types::EmptyServerParams as EmptyParams, RpcModule}; +use jsonrpsee::{core::EmptyServerParams as EmptyParams, RpcModule}; use sc_chain_spec::Properties; const CHAIN_NAME: &'static str = "TEST_CHAIN_NAME"; diff --git a/client/rpc-spec-v2/src/transaction/api.rs b/client/rpc-spec-v2/src/transaction/api.rs index c226ab86787e9..ff36ce7a9c589 100644 --- a/client/rpc-spec-v2/src/transaction/api.rs +++ b/client/rpc-spec-v2/src/transaction/api.rs @@ -20,6 +20,7 @@ use crate::transaction::event::TransactionEvent; use jsonrpsee::proc_macros::rpc; +use sc_rpc::utils::SubscriptionResponse; use sp_core::Bytes; #[rpc(client, server)] @@ -33,5 +34,5 @@ pub trait TransactionApi { unsubscribe = "transaction_unstable_unwatch", item = TransactionEvent, )] - fn submit_and_watch(&self, bytes: Bytes); + async fn submit_and_watch(&self, bytes: Bytes) -> SubscriptionResponse>; } diff --git a/client/rpc-spec-v2/src/transaction/transaction.rs b/client/rpc-spec-v2/src/transaction/transaction.rs index 44f4bd36c8b8b..55a20107cb67a 100644 --- a/client/rpc-spec-v2/src/transaction/transaction.rs +++ b/client/rpc-spec-v2/src/transaction/transaction.rs @@ -29,27 +29,22 @@ use crate::{ }, SubscriptionTaskExecutor, }; -use jsonrpsee::{ - core::async_trait, - types::{ - error::{CallError, ErrorObject}, - SubscriptionResult, - }, - SubscriptionSink, -}; +use jsonrpsee::{core::async_trait, types::error::ErrorObject, PendingSubscriptionSink}; +use sc_rpc::utils::SubscriptionResponse; use sc_transaction_pool_api::{ error::IntoPoolError, BlockHash, TransactionFor, TransactionPool, TransactionSource, TransactionStatus, }; use std::sync::Arc; +use sc_rpc::utils::accept_and_pipe_from_stream; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; use sp_core::Bytes; use sp_runtime::{generic, traits::Block as BlockT}; use codec::Decode; -use futures::{FutureExt, StreamExt, TryFutureExt}; +use futures::{StreamExt, TryFutureExt}; /// An API for transaction RPC calls. pub struct Transaction { @@ -90,19 +85,23 @@ where ::Hash: Unpin, Client: HeaderBackend + ProvideRuntimeApi + Send + Sync + 'static, { - fn submit_and_watch(&self, mut sink: SubscriptionSink, xt: Bytes) -> SubscriptionResult { + async fn submit_and_watch( + &self, + pending: PendingSubscriptionSink, + xt: Bytes, + ) -> SubscriptionResponse::Hash>> { // This is the only place where the RPC server can return an error for this // subscription. Other defects must be signaled as events to the sink. let decoded_extrinsic = match TransactionFor::::decode(&mut &xt[..]) { Ok(decoded_extrinsic) => decoded_extrinsic, Err(e) => { - let err = CallError::Custom(ErrorObject::owned( + let err = ErrorObject::owned( BAD_FORMAT, format!("Extrinsic has invalid format: {}", e), None::<()>, - )); - let _ = sink.reject(err); - return Ok(()) + ); + pending.reject(err).await; + return SubscriptionResponse::Closed }, }; @@ -121,25 +120,26 @@ where .unwrap_or_else(|e| Error::Verification(Box::new(e))) }); - let fut = async move { - match submit.await { - Ok(stream) => { - let mut state = TransactionState::new(); - let stream = - stream.filter_map(|event| async move { state.handle_event(event) }); - sink.pipe_from_stream(stream.boxed()).await; - }, - Err(err) => { - // We have not created an `Watcher` for the tx. Make sure the - // error is still propagated as an event. - let event: TransactionEvent<::Hash> = err.into(); - sink.pipe_from_stream(futures::stream::once(async { event }).boxed()).await; - }, - }; - }; + match submit.await { + Ok(stream) => { + let mut state = TransactionState::new(); + let stream = + stream.filter_map(move |event| async move { state.handle_event(event) }); - self.executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); - Ok(()) + accept_and_pipe_from_stream(pending, stream.boxed(), &self.executor).await + }, + Err(err) => { + // We have not created an `Watcher` for the tx. Make sure the + // error is still propagated as an event. + let event: TransactionEvent<::Hash> = err.into(); + accept_and_pipe_from_stream( + pending, + futures::stream::once(async { event }).boxed(), + &self.executor, + ) + .await + }, + } } } diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index f9c36bf57c684..3842fbe0787ce 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1" } futures = "0.3.21" -jsonrpsee = { version = "0.16.2", features = ["server"] } +jsonrpsee = { version = "0.19.0", features = ["server"] } log = "0.4.17" parking_lot = "0.12.1" serde_json = "1.0.85" @@ -40,6 +40,7 @@ sp-statement-store = { version = "4.0.0-dev", path = "../../primitives/statement tokio = "1.22.0" [dev-dependencies] +tracing-subscriber = { version = "0.3", features = ["env-filter"] } env_logger = "0.9" assert_matches = "1.3.0" sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } diff --git a/client/rpc/src/author/mod.rs b/client/rpc/src/author/mod.rs index 00a126500e26d..4968f49b1cc5b 100644 --- a/client/rpc/src/author/mod.rs +++ b/client/rpc/src/author/mod.rs @@ -23,15 +23,11 @@ mod tests; use std::sync::Arc; -use crate::SubscriptionTaskExecutor; +use crate::{utils::accept_and_pipe_from_stream, SubscriptionTaskExecutor}; use codec::{Decode, Encode}; -use futures::{FutureExt, TryFutureExt}; -use jsonrpsee::{ - core::{async_trait, Error as JsonRpseeError, RpcResult}, - types::SubscriptionResult, - SubscriptionSink, -}; +use futures::TryFutureExt; +use jsonrpsee::{core::async_trait, PendingSubscriptionSink}; use sc_rpc_api::DenyUnsafe; use sc_transaction_pool_api::{ error::IntoPoolError, BlockHash, InPoolTransaction, TransactionFor, TransactionPool, @@ -91,7 +87,7 @@ where P::Hash: Unpin, ::Hash: Unpin, { - async fn submit_extrinsic(&self, ext: Bytes) -> RpcResult> { + async fn submit_extrinsic(&self, ext: Bytes) -> Result> { let xt = match Decode::decode(&mut &ext[..]) { Ok(xt) => xt, Err(err) => return Err(Error::Client(Box::new(err)).into()), @@ -108,7 +104,7 @@ where }) } - fn insert_key(&self, key_type: String, suri: String, public: Bytes) -> RpcResult<()> { + fn insert_key(&self, key_type: String, suri: String, public: Bytes) -> Result<()> { self.deny_unsafe.check_if_safe()?; let key_type = key_type.as_str().try_into().map_err(|_| Error::BadKeyType)?; @@ -118,7 +114,7 @@ where Ok(()) } - fn rotate_keys(&self) -> RpcResult { + fn rotate_keys(&self) -> Result { self.deny_unsafe.check_if_safe()?; let best_block_hash = self.client.info().best_hash; @@ -129,7 +125,7 @@ where .map_err(|api_err| Error::Client(Box::new(api_err)).into()) } - fn has_session_keys(&self, session_keys: Bytes) -> RpcResult { + fn has_session_keys(&self, session_keys: Bytes) -> Result { self.deny_unsafe.check_if_safe()?; let best_block_hash = self.client.info().best_hash; @@ -143,21 +139,21 @@ where Ok(self.keystore.has_keys(&keys)) } - fn has_key(&self, public_key: Bytes, key_type: String) -> RpcResult { + fn has_key(&self, public_key: Bytes, key_type: String) -> Result { self.deny_unsafe.check_if_safe()?; let key_type = key_type.as_str().try_into().map_err(|_| Error::BadKeyType)?; Ok(self.keystore.has_keys(&[(public_key.to_vec(), key_type)])) } - fn pending_extrinsics(&self) -> RpcResult> { + fn pending_extrinsics(&self) -> Result> { Ok(self.pool.ready().map(|tx| tx.data().encode().into()).collect()) } fn remove_extrinsic( &self, bytes_or_hash: Vec>>, - ) -> RpcResult>> { + ) -> Result>> { self.deny_unsafe.check_if_safe()?; let hashes = bytes_or_hash .into_iter() @@ -178,13 +174,13 @@ where .collect()) } - fn watch_extrinsic(&self, mut sink: SubscriptionSink, xt: Bytes) -> SubscriptionResult { + async fn watch_extrinsic(&self, pending: PendingSubscriptionSink, xt: Bytes) { let best_block_hash = self.client.info().best_hash; let dxt = match TransactionFor::

::decode(&mut &xt[..]).map_err(|e| Error::from(e)) { Ok(dxt) => dxt, Err(e) => { - let _ = sink.reject(JsonRpseeError::from(e)); - return Ok(()) + pending.reject(e).await; + return }, }; @@ -197,19 +193,14 @@ where .unwrap_or_else(|e| error::Error::Verification(Box::new(e))) }); - let fut = async move { - let stream = match submit.await { - Ok(stream) => stream, - Err(err) => { - let _ = sink.reject(JsonRpseeError::from(err)); - return - }, - }; - - sink.pipe_from_stream(stream).await; + let stream = match submit.await { + Ok(stream) => stream, + Err(err) => { + pending.reject(err).await; + return + }, }; - self.executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); - Ok(()) + accept_and_pipe_from_stream::<(), _, _>(pending, stream, &self.executor).await; } } diff --git a/client/rpc/src/author/tests.rs b/client/rpc/src/author/tests.rs index 1f688e8e85e05..8d21b4305d0c3 100644 --- a/client/rpc/src/author/tests.rs +++ b/client/rpc/src/author/tests.rs @@ -22,8 +22,7 @@ use crate::testing::{test_executor, timeout_secs}; use assert_matches::assert_matches; use codec::Encode; use jsonrpsee::{ - core::Error as RpcError, - types::{error::CallError, EmptyServerParams as EmptyParams}, + core::{EmptyServerParams as EmptyParams, Error as RpcError}, RpcModule, }; use sc_transaction_pool::{BasicPool, FullChainApi}; @@ -105,7 +104,7 @@ async fn author_submit_transaction_should_not_cause_error() { assert_matches!( api.call::<_, H256>("author_submitExtrinsic", [xt]).await, - Err(RpcError::Call(CallError::Custom(err))) if err.message().contains("Already Imported") && err.code() == 1013 + Err(RpcError::Call(err)) if err.message().contains("Already Imported") && err.code() == 1013 ); } @@ -120,7 +119,7 @@ async fn author_should_watch_extrinsic() { true, ); - let mut sub = api.subscribe("author_submitAndWatchExtrinsic", [xt]).await.unwrap(); + let mut sub = api.subscribe_unbounded("author_submitAndWatchExtrinsic", [xt]).await.unwrap(); let (tx, sub_id) = timeout_secs(10, sub.next::>()) .await .unwrap() @@ -158,11 +157,11 @@ async fn author_should_return_watch_validation_error() { let invalid_xt = ExtrinsicBuilder::new_fill_block(Perbill::from_percent(100)).build(); let api = TestSetup::into_rpc(); - let failed_sub = api.subscribe(METHOD, [to_hex(&invalid_xt.encode(), true)]).await; + let failed_sub = api.subscribe_unbounded(METHOD, [to_hex(&invalid_xt.encode(), true)]).await; assert_matches!( failed_sub, - Err(RpcError::Call(CallError::Custom(err))) if err.message().contains("Invalid Transaction") && err.code() == 1010 + Err(RpcError::Call(err)) if err.message().contains("Invalid Transaction") && err.code() == 1010 ); } @@ -278,7 +277,7 @@ async fn author_has_session_keys() { assert_matches!( api.call::<_, bool>("author_hasSessionKeys", vec![Bytes::from(vec![1, 2, 3])]).await, - Err(RpcError::Call(CallError::Custom(err))) if err.message().contains("Session keys are not encoded correctly") + Err(RpcError::Call(err)) if err.message().contains("Session keys are not encoded correctly") ); } diff --git a/client/rpc/src/chain/chain_full.rs b/client/rpc/src/chain/chain_full.rs index a88291eb7bd35..d3db4b0053340 100644 --- a/client/rpc/src/chain/chain_full.rs +++ b/client/rpc/src/chain/chain_full.rs @@ -19,14 +19,14 @@ //! Blockchain API backend for full nodes. use super::{client_err, ChainBackend, Error}; -use crate::SubscriptionTaskExecutor; +use crate::{utils::pipe_from_stream, SubscriptionTaskExecutor}; use std::{marker::PhantomData, sync::Arc}; use futures::{ - future::{self, FutureExt}, + future::{self}, stream::{self, Stream, StreamExt}, }; -use jsonrpsee::SubscriptionSink; +use jsonrpsee::{core::async_trait, SubscriptionSink}; use sc_client_api::{BlockBackend, BlockchainEvents}; use sp_blockchain::HeaderBackend; use sp_runtime::{generic::SignedBlock, traits::Block as BlockT}; @@ -48,6 +48,7 @@ impl FullChain { } } +#[async_trait] impl ChainBackend for FullChain where Block: BlockT + 'static, @@ -66,7 +67,7 @@ where self.client.block(self.unwrap_or_best(hash)).map_err(client_err) } - fn subscribe_all_heads(&self, sink: SubscriptionSink) { + async fn subscribe_all_heads(&self, sink: SubscriptionSink) { subscribe_headers( &self.client, &self.executor, @@ -78,9 +79,10 @@ where .map(|notification| notification.header) }, ) + .await } - fn subscribe_new_heads(&self, sink: SubscriptionSink) { + async fn subscribe_new_heads(&self, sink: SubscriptionSink) { subscribe_headers( &self.client, &self.executor, @@ -93,9 +95,10 @@ where .map(|notification| notification.header) }, ) + .await } - fn subscribe_finalized_heads(&self, sink: SubscriptionSink) { + async fn subscribe_finalized_heads(&self, sink: SubscriptionSink) { subscribe_headers( &self.client, &self.executor, @@ -107,14 +110,15 @@ where .map(|notification| notification.header) }, ) + .await } } /// Subscribe to new headers. -fn subscribe_headers( +async fn subscribe_headers( client: &Arc, executor: &SubscriptionTaskExecutor, - mut sink: SubscriptionSink, + sink: SubscriptionSink, best_block_hash: G, stream: F, ) where @@ -139,9 +143,5 @@ fn subscribe_headers( // duplicates at the beginning of the stream though. let stream = stream::iter(maybe_header).chain(stream()); - let fut = async move { - sink.pipe_from_stream(stream).await; - }; - - executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); + pipe_from_stream::<(), _, _>(sink, stream, executor).await; } diff --git a/client/rpc/src/chain/mod.rs b/client/rpc/src/chain/mod.rs index 2b5994f217df3..4e55cd1a777d7 100644 --- a/client/rpc/src/chain/mod.rs +++ b/client/rpc/src/chain/mod.rs @@ -27,7 +27,7 @@ use std::sync::Arc; use crate::SubscriptionTaskExecutor; -use jsonrpsee::{core::RpcResult, types::SubscriptionResult, SubscriptionSink}; +use jsonrpsee::{core::async_trait, PendingSubscriptionSink, SubscriptionSink}; use sc_client_api::BlockchainEvents; use sp_rpc::{list::ListOrValue, number::NumberOrHex}; use sp_runtime::{ @@ -42,6 +42,7 @@ pub use sc_rpc_api::chain::*; use sp_blockchain::HeaderBackend; /// Blockchain backend API +#[async_trait] trait ChainBackend: Send + Sync + 'static where Block: BlockT + 'static, @@ -91,13 +92,13 @@ where } /// All new head subscription - fn subscribe_all_heads(&self, sink: SubscriptionSink); + async fn subscribe_all_heads(&self, sink: SubscriptionSink); /// New best head subscription - fn subscribe_new_heads(&self, sink: SubscriptionSink); + async fn subscribe_new_heads(&self, sink: SubscriptionSink); /// Finalized head subscription - fn subscribe_finalized_heads(&self, sink: SubscriptionSink); + async fn subscribe_finalized_heads(&self, sink: SubscriptionSink); } /// Create new state API that works on full node. @@ -118,6 +119,7 @@ pub struct Chain { backend: Box>, } +#[async_trait] impl ChainApiServer, Block::Hash, Block::Header, SignedBlock> for Chain where @@ -125,20 +127,20 @@ where Block::Header: Unpin, Client: HeaderBackend + BlockchainEvents + 'static, { - fn header(&self, hash: Option) -> RpcResult> { - self.backend.header(hash).map_err(Into::into) + fn header(&self, hash: Option) -> Result, Error> { + self.backend.header(hash) } - fn block(&self, hash: Option) -> RpcResult>> { - self.backend.block(hash).map_err(Into::into) + fn block(&self, hash: Option) -> Result>, Error> { + self.backend.block(hash) } fn block_hash( &self, number: Option>, - ) -> RpcResult>> { + ) -> Result>, Error> { match number { - None => self.backend.block_hash(None).map(ListOrValue::Value).map_err(Into::into), + None => self.backend.block_hash(None).map(ListOrValue::Value), Some(ListOrValue::Value(number)) => self .backend .block_hash(Some(number)) @@ -152,23 +154,29 @@ where } } - fn finalized_head(&self) -> RpcResult { - self.backend.finalized_head().map_err(Into::into) + fn finalized_head(&self) -> Result { + self.backend.finalized_head() } - fn subscribe_all_heads(&self, sink: SubscriptionSink) -> SubscriptionResult { - self.backend.subscribe_all_heads(sink); - Ok(()) + async fn subscribe_all_heads(&self, pending: PendingSubscriptionSink) { + let Ok(sink) = pending.accept().await else { + return; + }; + self.backend.subscribe_all_heads(sink).await; } - fn subscribe_new_heads(&self, sink: SubscriptionSink) -> SubscriptionResult { - self.backend.subscribe_new_heads(sink); - Ok(()) + async fn subscribe_new_heads(&self, pending: PendingSubscriptionSink) { + let Ok(sink) = pending.accept().await else { + return; + }; + self.backend.subscribe_new_heads(sink).await; } - fn subscribe_finalized_heads(&self, sink: SubscriptionSink) -> SubscriptionResult { - self.backend.subscribe_finalized_heads(sink); - Ok(()) + async fn subscribe_finalized_heads(&self, pending: PendingSubscriptionSink) { + let Ok(sink) = pending.accept().await else { + return; + }; + self.backend.subscribe_finalized_heads(sink).await; } } diff --git a/client/rpc/src/chain/tests.rs b/client/rpc/src/chain/tests.rs index 75211a43bd9f1..6e9e4ebad3248 100644 --- a/client/rpc/src/chain/tests.rs +++ b/client/rpc/src/chain/tests.rs @@ -19,7 +19,7 @@ use super::*; use crate::testing::{test_executor, timeout_secs}; use assert_matches::assert_matches; -use jsonrpsee::types::EmptyServerParams as EmptyParams; +use jsonrpsee::core::EmptyServerParams as EmptyParams; use sc_block_builder::BlockBuilderProvider; use sp_consensus::BlockOrigin; use sp_rpc::list::ListOrValue; @@ -231,7 +231,7 @@ async fn test_head_subscription(method: &str) { let mut sub = { let api = new_full(client.clone(), test_executor()).into_rpc(); - let sub = api.subscribe(method, EmptyParams::new()).await.unwrap(); + let sub = api.subscribe_unbounded(method, EmptyParams::new()).await.unwrap(); let block = client.new_block(Default::default()).unwrap().build().unwrap().block; let block_hash = block.hash(); client.import(BlockOrigin::Own, block).await.unwrap(); diff --git a/client/rpc/src/dev/mod.rs b/client/rpc/src/dev/mod.rs index 4d2e8618d553a..424ef72b694e2 100644 --- a/client/rpc/src/dev/mod.rs +++ b/client/rpc/src/dev/mod.rs @@ -22,7 +22,6 @@ #[cfg(test)] mod tests; -use jsonrpsee::core::RpcResult; use sc_client_api::{BlockBackend, HeaderBackend}; use sc_rpc_api::{dev::error::Error, DenyUnsafe}; use sp_api::{ApiExt, Core, ProvideRuntimeApi}; @@ -65,7 +64,7 @@ where + 'static, Client::Api: Core, { - fn block_stats(&self, hash: Block::Hash) -> RpcResult> { + fn block_stats(&self, hash: Block::Hash) -> Result, Error> { self.deny_unsafe.check_if_safe()?; let block = { diff --git a/client/rpc/src/dev/tests.rs b/client/rpc/src/dev/tests.rs index db6a9a119da0a..4082d6aaff087 100644 --- a/client/rpc/src/dev/tests.rs +++ b/client/rpc/src/dev/tests.rs @@ -83,7 +83,7 @@ async fn deny_unsafe_works() { "{{\"jsonrpc\":\"2.0\",\"method\":\"dev_getBlockStats\",\"params\":[{}],\"id\":1}}", best_hash_param ); - let (resp, _) = api.raw_json_request(&request).await.expect("Raw calls should succeed"); + let (resp, _) = api.raw_json_request(&request, 1).await.expect("Raw calls should succeed"); assert_eq!( resp.result, diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs index 475fc77a9b5bd..bf308f4217582 100644 --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -44,3 +44,135 @@ pub mod testing; /// Task executor that is being used by RPC subscriptions. pub type SubscriptionTaskExecutor = std::sync::Arc; + +/// JSON-RPC helpers. +pub mod utils { + use futures::{channel::oneshot, Future, FutureExt, Stream, StreamExt}; + use jsonrpsee::{ + types::SubscriptionId, IntoSubscriptionCloseResponse, PendingSubscriptionSink, + SendTimeoutError, SubscriptionCloseResponse, SubscriptionMessage, SubscriptionSink, + }; + use sp_runtime::Serialize; + + use crate::SubscriptionTaskExecutor; + + /// Similar to [`pipe_from_stream`] but also attempts to accept the subscription. + pub async fn accept_and_pipe_from_stream( + pending: PendingSubscriptionSink, + stream: S, + executor: &SubscriptionTaskExecutor, + ) -> SubscriptionResponse + where + S: Stream + Unpin + Send + 'static, + T: Serialize + Send + 'static, + R: Serialize + Send + 'static, + { + let Ok(sink) = pending.accept().await else { + return SubscriptionResponse::Closed + }; + pipe_from_stream(sink, stream, executor).await + } + + /// Feed items to the subscription from the underlying stream. + /// If the subscription can't keep up with the underlying stream + /// then it's dropped. + /// + /// This is simply a way to keep previous behaviour with unbounded streams + /// and should be replaced by specific RPC endpoint behaviour. + pub async fn pipe_from_stream( + sink: SubscriptionSink, + mut stream: S, + executor: &SubscriptionTaskExecutor, + ) -> SubscriptionResponse + where + S: Stream + Unpin + Send + 'static, + T: Serialize + Send + 'static, + R: Serialize + Send + 'static, + { + let (tx, rx) = oneshot::channel(); + + let fut = async move { + let res = loop { + tokio::select! { + biased; + _ = sink.closed() => break SubscriptionResponse::::Closed, + + maybe_item = stream.next() => { + let msg = match maybe_item { + Some(item) => crate::utils::to_sub_message(&item), + None => break SubscriptionResponse::Closed, + }; + + match sink.send_timeout(msg, std::time::Duration::from_secs(60)).await { + Ok(_) => (), + Err(SendTimeoutError::Closed(_)) => break SubscriptionResponse::Closed, + Err(SendTimeoutError::Timeout(_)) => { + log::warn!(target: "rpc", "dropping subscription; timeout"); + break SubscriptionResponse::Closed + } + } + } + } + }; + let _ = tx.send(res); + }; + + executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); + + // The RPC server is not gracefully shutdown + // and it's possible that the message isn't + // received here. + rx.await.unwrap_or(SubscriptionResponse::Closed) + } + + /// Subscription response type for substrate. + pub enum SubscriptionResponse { + /// The subscription was closed, no further message is sent. + /// + /// This is used to exit from subscription without any additional message. + /// May be used if the subscription was closed or the subscription was already rejected. + Closed, + /// Send out a notification. + Event(T), + } + + impl IntoSubscriptionCloseResponse for SubscriptionResponse { + fn into_response(self) -> SubscriptionCloseResponse { + match self { + Self::Closed => SubscriptionCloseResponse::None, + Self::Event(ev) => SubscriptionCloseResponse::Notif(to_sub_message(&ev)), + } + } + } + + /// Build a subscription message. + /// + /// # Panics + /// + /// This function panics if the `Serialize` fails and is treated a bug. + pub fn to_sub_message(result: &impl Serialize) -> SubscriptionMessage { + SubscriptionMessage::from_json(result).expect("JSON serialization infallible; qed") + } + + /// Spawn a subscription task and wait until it completes. + pub async fn spawn_subscription_task( + executor: &SubscriptionTaskExecutor, + fut: impl Future> + Send + 'static, + ) -> SubscriptionResponse + where + R: Send + 'static, + { + let (tx, rx) = oneshot::channel(); + + let fut = async move { + _ = tx.send(fut.await); + }; + + executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); + + // The RPC server is not gracefully shutdown + // and it's possible that the message isn't + // received here. + rx.await.unwrap_or(SubscriptionResponse::Closed) + } +} diff --git a/client/rpc/src/offchain/mod.rs b/client/rpc/src/offchain/mod.rs index de711accdcc12..6616738660530 100644 --- a/client/rpc/src/offchain/mod.rs +++ b/client/rpc/src/offchain/mod.rs @@ -22,7 +22,7 @@ mod tests; use self::error::Error; -use jsonrpsee::core::{async_trait, Error as JsonRpseeError, RpcResult}; +use jsonrpsee::core::async_trait; use parking_lot::RwLock; /// Re-export the API for backward compatibility. pub use sc_rpc_api::offchain::*; @@ -50,23 +50,23 @@ impl Offchain { #[async_trait] impl OffchainApiServer for Offchain { - fn set_local_storage(&self, kind: StorageKind, key: Bytes, value: Bytes) -> RpcResult<()> { + fn set_local_storage(&self, kind: StorageKind, key: Bytes, value: Bytes) -> Result<(), Error> { self.deny_unsafe.check_if_safe()?; let prefix = match kind { StorageKind::PERSISTENT => sp_offchain::STORAGE_PREFIX, - StorageKind::LOCAL => return Err(JsonRpseeError::from(Error::UnavailableStorageKind)), + StorageKind::LOCAL => return Err(Error::UnavailableStorageKind), }; self.storage.write().set(prefix, &key, &value); Ok(()) } - fn get_local_storage(&self, kind: StorageKind, key: Bytes) -> RpcResult> { + fn get_local_storage(&self, kind: StorageKind, key: Bytes) -> Result, Error> { self.deny_unsafe.check_if_safe()?; let prefix = match kind { StorageKind::PERSISTENT => sp_offchain::STORAGE_PREFIX, - StorageKind::LOCAL => return Err(JsonRpseeError::from(Error::UnavailableStorageKind)), + StorageKind::LOCAL => return Err(Error::UnavailableStorageKind), }; Ok(self.storage.read().get(prefix, &key).map(Into::into)) diff --git a/client/rpc/src/offchain/tests.rs b/client/rpc/src/offchain/tests.rs index 62a846d0887cd..7758fac7fabdb 100644 --- a/client/rpc/src/offchain/tests.rs +++ b/client/rpc/src/offchain/tests.rs @@ -39,7 +39,6 @@ fn local_storage_should_work() { #[test] fn offchain_calls_considered_unsafe() { - use jsonrpsee::types::error::CallError; let storage = InMemOffchainStorage::default(); let offchain = Offchain::new(storage, DenyUnsafe::Yes); let key = Bytes(b"offchain_storage".to_vec()); @@ -47,14 +46,14 @@ fn offchain_calls_considered_unsafe() { assert_matches!( offchain.set_local_storage(StorageKind::PERSISTENT, key.clone(), value.clone()), - Err(JsonRpseeError::Call(CallError::Custom(err))) => { - assert_eq!(err.message(), "RPC call is unsafe to be called externally") + Err(Error::UnsafeRpcCalled(e)) => { + assert_eq!(e.to_string(), "RPC call is unsafe to be called externally") } ); assert_matches!( offchain.get_local_storage(StorageKind::PERSISTENT, key), - Err(JsonRpseeError::Call(CallError::Custom(err))) => { - assert_eq!(err.message(), "RPC call is unsafe to be called externally") + Err(Error::UnsafeRpcCalled(e)) => { + assert_eq!(e.to_string(), "RPC call is unsafe to be called externally") } ); } diff --git a/client/rpc/src/state/mod.rs b/client/rpc/src/state/mod.rs index 057661d6ec7f5..1e1fe78ea2eba 100644 --- a/client/rpc/src/state/mod.rs +++ b/client/rpc/src/state/mod.rs @@ -28,10 +28,7 @@ use std::sync::Arc; use crate::SubscriptionTaskExecutor; -use jsonrpsee::{ - core::{async_trait, server::rpc_module::SubscriptionSink, Error as JsonRpseeError, RpcResult}, - types::SubscriptionResult, -}; +use jsonrpsee::{core::async_trait, types::ErrorObject, PendingSubscriptionSink}; use sc_rpc_api::DenyUnsafe; use sp_core::{ @@ -158,10 +155,14 @@ where ) -> Result; /// New runtime version subscription - fn subscribe_runtime_version(&self, sink: SubscriptionSink); + async fn subscribe_runtime_version(&self, pending: PendingSubscriptionSink); /// New storage subscription - fn subscribe_storage(&self, sink: SubscriptionSink, keys: Option>); + async fn subscribe_storage( + &self, + pending: PendingSubscriptionSink, + keys: Option>, + ); } /// Create new state API that works on full node. @@ -207,7 +208,12 @@ where Block: BlockT + 'static, Client: Send + Sync + 'static, { - fn call(&self, method: String, data: Bytes, block: Option) -> RpcResult { + fn call( + &self, + method: String, + data: Bytes, + block: Option, + ) -> Result { self.backend.call(block, method, data).map_err(Into::into) } @@ -215,7 +221,7 @@ where &self, key_prefix: StorageKey, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { self.backend.storage_keys(block, key_prefix).map_err(Into::into) } @@ -223,7 +229,7 @@ where &self, key_prefix: StorageKey, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { self.deny_unsafe.check_if_safe()?; self.backend.storage_pairs(block, key_prefix).map_err(Into::into) } @@ -234,12 +240,9 @@ where count: u32, start_key: Option, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { if count > STORAGE_KEYS_PAGED_MAX_COUNT { - return Err(JsonRpseeError::from(Error::InvalidCount { - value: count, - max: STORAGE_KEYS_PAGED_MAX_COUNT, - })) + return Err(Error::InvalidCount { value: count, max: STORAGE_KEYS_PAGED_MAX_COUNT }) } self.backend .storage_keys_paged(block, prefix, count, start_key) @@ -250,7 +253,7 @@ where &self, key: StorageKey, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { self.backend.storage(block, key).map_err(Into::into) } @@ -258,7 +261,7 @@ where &self, key: StorageKey, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { self.backend.storage_hash(block, key).map_err(Into::into) } @@ -266,18 +269,18 @@ where &self, key: StorageKey, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { self.backend .storage_size(block, key, self.deny_unsafe) .await .map_err(Into::into) } - fn metadata(&self, block: Option) -> RpcResult { + fn metadata(&self, block: Option) -> Result { self.backend.metadata(block).map_err(Into::into) } - fn runtime_version(&self, at: Option) -> RpcResult { + fn runtime_version(&self, at: Option) -> Result { self.backend.runtime_version(at).map_err(Into::into) } @@ -286,7 +289,7 @@ where keys: Vec, from: Block::Hash, to: Option, - ) -> RpcResult>> { + ) -> Result>, Error> { self.deny_unsafe.check_if_safe()?; self.backend.query_storage(from, to, keys).map_err(Into::into) } @@ -295,7 +298,7 @@ where &self, keys: Vec, at: Option, - ) -> RpcResult>> { + ) -> Result>, Error> { self.backend.query_storage_at(keys, at).map_err(Into::into) } @@ -303,7 +306,7 @@ where &self, keys: Vec, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { self.backend.read_proof(block, keys).map_err(Into::into) } @@ -318,32 +321,30 @@ where targets: Option, storage_keys: Option, methods: Option, - ) -> RpcResult { + ) -> Result { self.deny_unsafe.check_if_safe()?; self.backend .trace_block(block, targets, storage_keys, methods) .map_err(Into::into) } - fn subscribe_runtime_version(&self, sink: SubscriptionSink) -> SubscriptionResult { - self.backend.subscribe_runtime_version(sink); - Ok(()) + async fn subscribe_runtime_version(&self, pending: PendingSubscriptionSink) { + _ = self.backend.subscribe_runtime_version(pending).await; } - fn subscribe_storage( + async fn subscribe_storage( &self, - mut sink: SubscriptionSink, + pending: PendingSubscriptionSink, keys: Option>, - ) -> SubscriptionResult { + ) { if keys.is_none() { if let Err(err) = self.deny_unsafe.check_if_safe() { - let _ = sink.reject(JsonRpseeError::from(err)); - return Ok(()) + pending.reject(ErrorObject::from(err)).await; + return } } - self.backend.subscribe_storage(sink, keys); - Ok(()) + _ = self.backend.subscribe_storage(pending, keys).await; } } @@ -430,7 +431,7 @@ where storage_key: PrefixedStorageKey, key_prefix: StorageKey, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { self.backend.storage_keys(block, storage_key, key_prefix).map_err(Into::into) } @@ -441,7 +442,7 @@ where count: u32, start_key: Option, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { self.backend .storage_keys_paged(block, storage_key, prefix, count, start_key) .map_err(Into::into) @@ -452,7 +453,7 @@ where storage_key: PrefixedStorageKey, key: StorageKey, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { self.backend.storage(block, storage_key, key).map_err(Into::into) } @@ -461,7 +462,7 @@ where storage_key: PrefixedStorageKey, keys: Vec, block: Option, - ) -> RpcResult>> { + ) -> Result>, Error> { self.backend.storage_entries(block, storage_key, keys).map_err(Into::into) } @@ -470,7 +471,7 @@ where storage_key: PrefixedStorageKey, key: StorageKey, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { self.backend.storage_hash(block, storage_key, key).map_err(Into::into) } @@ -479,7 +480,7 @@ where storage_key: PrefixedStorageKey, key: StorageKey, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { self.backend.storage_size(block, storage_key, key).map_err(Into::into) } @@ -488,7 +489,7 @@ where child_storage_key: PrefixedStorageKey, keys: Vec, block: Option, - ) -> RpcResult> { + ) -> Result, Error> { self.backend .read_child_proof(block, child_storage_key, keys) .map_err(Into::into) diff --git a/client/rpc/src/state/state_full.rs b/client/rpc/src/state/state_full.rs index 20ca5f7131e71..2dfc677cda759 100644 --- a/client/rpc/src/state/state_full.rs +++ b/client/rpc/src/state/state_full.rs @@ -25,13 +25,10 @@ use super::{ error::{Error, Result}, ChildStateBackend, StateBackend, }; -use crate::{DenyUnsafe, SubscriptionTaskExecutor}; +use crate::{utils::accept_and_pipe_from_stream, DenyUnsafe, SubscriptionTaskExecutor}; -use futures::{future, stream, FutureExt, StreamExt}; -use jsonrpsee::{ - core::{async_trait, Error as JsonRpseeError}, - SubscriptionSink, -}; +use futures::{future, stream, StreamExt}; +use jsonrpsee::{core::async_trait, PendingSubscriptionSink}; use sc_client_api::{ Backend, BlockBackend, BlockchainEvents, CallExecutor, ExecutorProvider, ProofProvider, StorageProvider, @@ -377,9 +374,7 @@ where .map_err(client_err) } - fn subscribe_runtime_version(&self, mut sink: SubscriptionSink) { - let client = self.client.clone(); - + async fn subscribe_runtime_version(&self, pending: PendingSubscriptionSink) { let initial = match self .block_or_best(None) .and_then(|block| self.client.runtime_version_at(block).map_err(Into::into)) @@ -387,12 +382,13 @@ where { Ok(initial) => initial, Err(e) => { - let _ = sink.reject(JsonRpseeError::from(e)); + pending.reject(e).await; return }, }; let mut previous_version = initial.clone(); + let client = self.client.clone(); // A stream of new versions let version_stream = client @@ -412,24 +408,22 @@ where }); let stream = futures::stream::once(future::ready(initial)).chain(version_stream); - - let fut = async move { - sink.pipe_from_stream(stream).await; - }; - - self.executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); + accept_and_pipe_from_stream::<(), _, _>(pending, stream, &self.executor).await; } - fn subscribe_storage(&self, mut sink: SubscriptionSink, keys: Option>) { + async fn subscribe_storage( + &self, + pending: PendingSubscriptionSink, + keys: Option>, + ) { let stream = match self.client.storage_changes_notification_stream(keys.as_deref(), None) { Ok(stream) => stream, Err(blockchain_err) => { - let _ = sink.reject(JsonRpseeError::from(Error::Client(Box::new(blockchain_err)))); + pending.reject(Error::Client(Box::new(blockchain_err))).await; return }, }; - // initial values let initial = stream::iter(keys.map(|keys| { let block = self.client.info().best_hash; let changes = keys @@ -442,7 +436,6 @@ where StorageChangeSet { block, changes } })); - // let storage_stream = stream.map(|(block, changes)| StorageChangeSet { let storage_stream = stream.map(|storage_notif| StorageChangeSet { block: storage_notif.block, changes: storage_notif @@ -456,11 +449,7 @@ where .chain(storage_stream) .filter(|storage| future::ready(!storage.changes.is_empty())); - let fut = async move { - sink.pipe_from_stream(stream).await; - }; - - self.executor.spawn("substrate-rpc-subscription", Some("rpc"), fut.boxed()); + accept_and_pipe_from_stream::<(), _, _>(pending, stream, &self.executor).await; } fn trace_block( diff --git a/client/rpc/src/state/tests.rs b/client/rpc/src/state/tests.rs index 9e00a04abe386..fd59a28939f3e 100644 --- a/client/rpc/src/state/tests.rs +++ b/client/rpc/src/state/tests.rs @@ -21,10 +21,7 @@ use super::*; use crate::testing::{test_executor, timeout_secs}; use assert_matches::assert_matches; use futures::executor; -use jsonrpsee::{ - core::Error as RpcError, - types::{error::CallError as RpcCallError, EmptyServerParams as EmptyParams, ErrorObject}, -}; +use jsonrpsee::core::{EmptyServerParams as EmptyParams, Error as RpcError}; use sc_block_builder::BlockBuilderProvider; use sc_rpc_api::DenyUnsafe; use sp_consensus::BlockOrigin; @@ -42,6 +39,14 @@ fn prefixed_storage_key() -> PrefixedStorageKey { child_info.prefixed_storage_key() } +fn init_logger() { + use tracing_subscriber::{EnvFilter, FmtSubscriber}; + + let _ = FmtSubscriber::builder() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); +} + #[tokio::test] async fn should_return_storage() { const KEY: &[u8] = b":mock"; @@ -200,22 +205,25 @@ async fn should_call_contract() { let genesis_hash = client.genesis_hash(); let (client, _child) = new_full(client, test_executor(), DenyUnsafe::No); - use jsonrpsee::{core::Error, types::error::CallError}; - assert_matches!( client.call("balanceOf".into(), Bytes(vec![1, 2, 3]), Some(genesis_hash).into()), - Err(Error::Call(CallError::Failed(_))) + Err(Error::Client(_)) ) } #[tokio::test] async fn should_notify_about_storage_changes() { + init_logger(); + let mut sub = { let mut client = Arc::new(substrate_test_runtime_client::new()); let (api, _child) = new_full(client.clone(), test_executor(), DenyUnsafe::No); let api_rpc = api.into_rpc(); - let sub = api_rpc.subscribe("state_subscribeStorage", EmptyParams::new()).await.unwrap(); + let sub = api_rpc + .subscribe_unbounded("state_subscribeStorage", EmptyParams::new()) + .await + .unwrap(); // Cause a change: let mut builder = client.new_block(Default::default()).unwrap(); @@ -237,11 +245,12 @@ async fn should_notify_about_storage_changes() { // NOTE: previous versions of the subscription code used to return an empty value for the // "initial" storage change here assert_matches!(timeout_secs(1, sub.next::>()).await, Ok(Some(_))); - assert_matches!(timeout_secs(1, sub.next::>()).await, Ok(None)); } #[tokio::test] async fn should_send_initial_storage_changes_and_notifications() { + init_logger(); + let mut sub = { let mut client = Arc::new(substrate_test_runtime_client::new()); let (api, _child) = new_full(client.clone(), test_executor(), DenyUnsafe::No); @@ -259,7 +268,10 @@ async fn should_send_initial_storage_changes_and_notifications() { let api_rpc = api.into_rpc(); let sub = api_rpc - .subscribe("state_subscribeStorage", [[StorageKey(alice_balance_key)]]) + .subscribe_unbounded( + "state_subscribeStorage", + [[StorageKey(alice_balance_key.to_vec())]], + ) .await .unwrap(); @@ -280,9 +292,6 @@ async fn should_send_initial_storage_changes_and_notifications() { assert_matches!(timeout_secs(1, sub.next::>()).await, Ok(Some(_))); assert_matches!(timeout_secs(1, sub.next::>()).await, Ok(Some(_))); - - // No more messages to follow - assert_matches!(timeout_secs(1, sub.next::>()).await, Ok(None)); } #[tokio::test] @@ -381,108 +390,48 @@ async fn should_query_storage() { assert_eq!(result.unwrap(), expected); // Inverted range. - let result = api.query_storage(keys.clone(), block1_hash, Some(genesis_hash)); - - assert_eq!( - result.map_err(|e| e.to_string()), - Err(RpcError::Call(RpcCallError::Custom(ErrorObject::owned( - 4001, - Error::InvalidBlockRange { - from: format!("1 ({:?})", block1_hash), - to: format!("0 ({:?})", genesis_hash), - details: "from number > to number".to_owned(), - } - .to_string(), - None::<()>, - )))) - .map_err(|e| e.to_string()) + assert_matches!( + api.query_storage(keys.clone(), block1_hash, Some(genesis_hash)), + Err(Error::InvalidBlockRange { from, to, details }) if from == format!("1 ({:?})", block1_hash) && to == format!("0 ({:?})", genesis_hash) && details == "from number > to number".to_owned() ); let random_hash1 = H256::random(); let random_hash2 = H256::random(); // Invalid second hash. - let result = api.query_storage(keys.clone(), genesis_hash, Some(random_hash1)); - - assert_eq!( - result.map_err(|e| e.to_string()), - Err(RpcError::Call(RpcCallError::Custom(ErrorObject::owned( - 4001, - Error::InvalidBlockRange { - from: format!("{:?}", genesis_hash), - to: format!("{:?}", Some(random_hash1)), - details: format!( - "UnknownBlock: Header was not found in the database: {:?}", - random_hash1 - ), - } - .to_string(), - None::<()>, - )))) - .map_err(|e| e.to_string()) + assert_matches!( + api.query_storage(keys.clone(), genesis_hash, Some(random_hash1)), + Err(Error::InvalidBlockRange { from, to, details }) if from == format!("{:?}", genesis_hash) && to == format!("{:?}", Some(random_hash1)) && details == format!( + "UnknownBlock: Header was not found in the database: {:?}", + random_hash1 + ) ); // Invalid first hash with Some other hash. - let result = api.query_storage(keys.clone(), random_hash1, Some(genesis_hash)); - - assert_eq!( - result.map_err(|e| e.to_string()), - Err(RpcError::Call(RpcCallError::Custom(ErrorObject::owned( - 4001, - Error::InvalidBlockRange { - from: format!("{:?}", random_hash1), - to: format!("{:?}", Some(genesis_hash)), - details: format!( - "UnknownBlock: Header was not found in the database: {:?}", - random_hash1 - ), - } - .to_string(), - None::<()>, - )))) - .map_err(|e| e.to_string()), + assert_matches!( + api.query_storage(keys.clone(), random_hash1, Some(genesis_hash)), + Err(Error::InvalidBlockRange { from, to, details }) if from == format!("{:?}", random_hash1) && to == format!("{:?}", Some(genesis_hash)) && details == format!( + "UnknownBlock: Header was not found in the database: {:?}", + random_hash1 + ) ); // Invalid first hash with None. - let result = api.query_storage(keys.clone(), random_hash1, None); - - assert_eq!( - result.map_err(|e| e.to_string()), - Err(RpcError::Call(RpcCallError::Custom(ErrorObject::owned( - 4001, - Error::InvalidBlockRange { - from: format!("{:?}", random_hash1), - to: format!("{:?}", Some(block2_hash)), // Best block hash. - details: format!( - "UnknownBlock: Header was not found in the database: {:?}", - random_hash1 - ), - } - .to_string(), - None::<()>, - )))) - .map_err(|e| e.to_string()), + assert_matches!( + api.query_storage(keys.clone(), random_hash1, None), + Err(Error::InvalidBlockRange { from, to, details }) if from == format!("{:?}", random_hash1) && to == format!("{:?}", Some(block2_hash)) && details == format!( + "UnknownBlock: Header was not found in the database: {:?}", + random_hash1 + ) ); // Both hashes invalid. - let result = api.query_storage(keys.clone(), random_hash1, Some(random_hash2)); - - assert_eq!( - result.map_err(|e| e.to_string()), - Err(RpcError::Call(RpcCallError::Custom(ErrorObject::owned( - 4001, - Error::InvalidBlockRange { - from: format!("{:?}", random_hash1), // First hash not found. - to: format!("{:?}", Some(random_hash2)), - details: format!( - "UnknownBlock: Header was not found in the database: {:?}", - random_hash1 - ), - } - .to_string(), - None::<()> - )))) - .map_err(|e| e.to_string()), + assert_matches!( + api.query_storage(keys.clone(), random_hash1, Some(random_hash2)), + Err(Error::InvalidBlockRange { from, to, details }) if from == format!("{:?}", random_hash1) && to == format!("{:?}", Some(random_hash2)) && details == format!( + "UnknownBlock: Header was not found in the database: {:?}", + random_hash1 + ) ); // single block range @@ -536,7 +485,7 @@ async fn should_notify_on_runtime_version_initially() { let api_rpc = api.into_rpc(); let sub = api_rpc - .subscribe("state_subscribeRuntimeVersion", EmptyParams::new()) + .subscribe_unbounded("state_subscribeRuntimeVersion", EmptyParams::new()) .await .unwrap(); @@ -545,9 +494,6 @@ async fn should_notify_on_runtime_version_initially() { // assert initial version sent. assert_matches!(timeout_secs(10, sub.next::()).await, Ok(Some(_))); - - sub.close(); - assert_matches!(timeout_secs(10, sub.next::()).await, Ok(None)); } #[test] @@ -560,12 +506,14 @@ fn should_deserialize_storage_key() { #[tokio::test] async fn wildcard_storage_subscriptions_are_rpc_unsafe() { + init_logger(); + let client = Arc::new(substrate_test_runtime_client::new()); let (api, _child) = new_full(client, test_executor(), DenyUnsafe::Yes); let api_rpc = api.into_rpc(); - let err = api_rpc.subscribe("state_subscribeStorage", EmptyParams::new()).await; - assert_matches!(err, Err(RpcError::Call(RpcCallError::Custom(e))) if e.message() == "RPC call is unsafe to be called externally"); + let err = api_rpc.subscribe_unbounded("state_subscribeStorage", EmptyParams::new()).await; + assert_matches!(err, Err(RpcError::Call(e)) if e.message() == "RPC call is unsafe to be called externally"); } #[tokio::test] @@ -575,7 +523,7 @@ async fn concrete_storage_subscriptions_are_rpc_safe() { let api_rpc = api.into_rpc(); let key = StorageKey(STORAGE_KEY.to_vec()); - let sub = api_rpc.subscribe("state_subscribeStorage", [[key]]).await; + let sub = api_rpc.subscribe_unbounded("state_subscribeStorage", [[key]]).await; assert!(sub.is_ok()); } diff --git a/client/rpc/src/system/mod.rs b/client/rpc/src/system/mod.rs index 0da4f8d0e211c..8c7510c64cb51 100644 --- a/client/rpc/src/system/mod.rs +++ b/client/rpc/src/system/mod.rs @@ -22,17 +22,12 @@ mod tests; use futures::channel::oneshot; -use jsonrpsee::{ - core::{async_trait, error::Error as JsonRpseeError, JsonValue, RpcResult}, - types::error::{CallError, ErrorCode, ErrorObject}, -}; +use jsonrpsee::core::{async_trait, JsonValue}; use sc_rpc_api::DenyUnsafe; use sc_tracing::logging; use sc_utils::mpsc::TracingUnboundedSender; use sp_runtime::traits::{self, Header as HeaderT}; -use self::error::Result; - pub use self::helpers::{Health, NodeRole, PeerInfo, SyncState, SystemInfo}; pub use sc_rpc_api::system::*; @@ -57,9 +52,9 @@ pub enum Request { /// Must return the state of the network. NetworkState(oneshot::Sender), /// Must return any potential parse error. - NetworkAddReservedPeer(String, oneshot::Sender>), + NetworkAddReservedPeer(String, oneshot::Sender>), /// Must return any potential parse error. - NetworkRemoveReservedPeer(String, oneshot::Sender>), + NetworkRemoveReservedPeer(String, oneshot::Sender>), /// Must return the list of reserved peers NetworkReservedPeers(oneshot::Sender>), /// Must return the node role. @@ -84,121 +79,109 @@ impl System { #[async_trait] impl SystemApiServer::Number> for System { - fn system_name(&self) -> RpcResult { + fn system_name(&self) -> Result { Ok(self.info.impl_name.clone()) } - fn system_version(&self) -> RpcResult { + fn system_version(&self) -> Result { Ok(self.info.impl_version.clone()) } - fn system_chain(&self) -> RpcResult { + fn system_chain(&self) -> Result { Ok(self.info.chain_name.clone()) } - fn system_type(&self) -> RpcResult { + fn system_type(&self) -> Result { Ok(self.info.chain_type.clone()) } - fn system_properties(&self) -> RpcResult { + fn system_properties(&self) -> Result { Ok(self.info.properties.clone()) } - async fn system_health(&self) -> RpcResult { + async fn system_health(&self) -> Result { let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::Health(tx)); - rx.await.map_err(|e| JsonRpseeError::to_call_error(e)) + rx.await.map_err(|e| Error::Internal(e.to_string())) } - async fn system_local_peer_id(&self) -> RpcResult { + async fn system_local_peer_id(&self) -> Result { let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::LocalPeerId(tx)); - rx.await.map_err(|e| JsonRpseeError::to_call_error(e)) + rx.await.map_err(|e| Error::Internal(e.to_string())) } - async fn system_local_listen_addresses(&self) -> RpcResult> { + async fn system_local_listen_addresses(&self) -> Result, Error> { let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::LocalListenAddresses(tx)); - rx.await.map_err(|e| JsonRpseeError::to_call_error(e)) + rx.await.map_err(|e| Error::Internal(e.to_string())) } async fn system_peers( &self, - ) -> RpcResult::Number>>> { + ) -> Result::Number>>, Error> { self.deny_unsafe.check_if_safe()?; let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::Peers(tx)); - rx.await.map_err(|e| JsonRpseeError::to_call_error(e)) + rx.await.map_err(|e| Error::Internal(e.to_string())) } - async fn system_network_state(&self) -> RpcResult { + async fn system_network_state(&self) -> Result { self.deny_unsafe.check_if_safe()?; let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::NetworkState(tx)); - rx.await.map_err(|e| JsonRpseeError::to_call_error(e)) + rx.await.map_err(|e| Error::Internal(e.to_string())) } - async fn system_add_reserved_peer(&self, peer: String) -> RpcResult<()> { + async fn system_add_reserved_peer(&self, peer: String) -> Result<(), Error> { self.deny_unsafe.check_if_safe()?; let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::NetworkAddReservedPeer(peer, tx)); match rx.await { Ok(Ok(())) => Ok(()), - Ok(Err(e)) => Err(JsonRpseeError::from(e)), - Err(e) => Err(JsonRpseeError::to_call_error(e)), + Ok(Err(e)) => Err(e), + Err(e) => Err(Error::Internal(e.to_string())), } } - async fn system_remove_reserved_peer(&self, peer: String) -> RpcResult<()> { + async fn system_remove_reserved_peer(&self, peer: String) -> Result<(), Error> { self.deny_unsafe.check_if_safe()?; let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::NetworkRemoveReservedPeer(peer, tx)); match rx.await { Ok(Ok(())) => Ok(()), - Ok(Err(e)) => Err(JsonRpseeError::from(e)), - Err(e) => Err(JsonRpseeError::to_call_error(e)), + Ok(Err(e)) => Err(e), + Err(e) => Err(Error::Internal(e.to_string())), } } - async fn system_reserved_peers(&self) -> RpcResult> { + async fn system_reserved_peers(&self) -> Result, Error> { let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::NetworkReservedPeers(tx)); - rx.await.map_err(|e| JsonRpseeError::to_call_error(e)) + rx.await.map_err(|e| Error::Internal(e.to_string())) } - async fn system_node_roles(&self) -> RpcResult> { + async fn system_node_roles(&self) -> Result, Error> { let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::NodeRoles(tx)); - rx.await.map_err(|e| JsonRpseeError::to_call_error(e)) + rx.await.map_err(|e| Error::Internal(e.to_string())) } - async fn system_sync_state(&self) -> RpcResult::Number>> { + async fn system_sync_state(&self) -> Result::Number>, Error> { let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::SyncState(tx)); - rx.await.map_err(|e| JsonRpseeError::to_call_error(e)) + rx.await.map_err(|e| Error::Internal(e.to_string())) } - fn system_add_log_filter(&self, directives: String) -> RpcResult<()> { + fn system_add_log_filter(&self, directives: String) -> Result<(), Error> { self.deny_unsafe.check_if_safe()?; logging::add_directives(&directives); - logging::reload_filter().map_err(|e| { - JsonRpseeError::Call(CallError::Custom(ErrorObject::owned( - ErrorCode::InternalError.code(), - e, - None::<()>, - ))) - }) + logging::reload_filter().map_err(|e| Error::Internal(e)) } - fn system_reset_log_filter(&self) -> RpcResult<()> { + fn system_reset_log_filter(&self) -> Result<(), Error> { self.deny_unsafe.check_if_safe()?; - logging::reset_log_filter().map_err(|e| { - JsonRpseeError::Call(CallError::Custom(ErrorObject::owned( - ErrorCode::InternalError.code(), - e, - None::<()>, - ))) - }) + logging::reset_log_filter().map_err(|e| Error::Internal(e)) } } diff --git a/client/rpc/src/system/tests.rs b/client/rpc/src/system/tests.rs index b6bfec7736b08..21d13ccfafaa7 100644 --- a/client/rpc/src/system/tests.rs +++ b/client/rpc/src/system/tests.rs @@ -20,8 +20,7 @@ use super::{helpers::SyncState, *}; use assert_matches::assert_matches; use futures::prelude::*; use jsonrpsee::{ - core::Error as RpcError, - types::{error::CallError, EmptyServerParams as EmptyParams}, + core::{EmptyServerParams as EmptyParams, Error as RpcError}, RpcModule, }; use sc_network::{self, config::Role, PeerId}; @@ -312,7 +311,7 @@ async fn system_network_add_reserved() { let bad_peer_id = ["/ip4/198.51.100.19/tcp/30333"]; assert_matches!( api(None).call::<_, ()>("system_addReservedPeer", bad_peer_id).await, - Err(RpcError::Call(CallError::Custom(err))) if err.message().contains("Peer id is missing from the address") + Err(RpcError::Call(err)) if err.message().contains("Peer id is missing from the address") ); } @@ -328,7 +327,7 @@ async fn system_network_remove_reserved() { assert_matches!( api(None).call::<_, String>("system_removeReservedPeer", bad_peer_id).await, - Err(RpcError::Call(CallError::Custom(err))) if err.message().contains("base-58 decode error: provided string contained invalid character '/' at byte 0") + Err(RpcError::Call(err)) if err.message().contains("base-58 decode error: provided string contained invalid character '/' at byte 0") ); } #[tokio::test] diff --git a/client/rpc/src/testing.rs b/client/rpc/src/testing.rs index 6b6e1906d44d1..e04f80a7b9e61 100644 --- a/client/rpc/src/testing.rs +++ b/client/rpc/src/testing.rs @@ -20,11 +20,50 @@ use std::{future::Future, sync::Arc}; -use sp_core::testing::TaskExecutor; +/// A task executor that can be used for running RPC tests. +/// +/// Warning: the tokio runtime must be initialized before calling this. +#[derive(Clone)] +pub struct TokioTestExecutor(tokio::runtime::Handle); + +impl TokioTestExecutor { + /// Create a new instance of `Self`. + pub fn new() -> Self { + Self(tokio::runtime::Handle::current()) + } +} + +impl Default for TokioTestExecutor { + fn default() -> Self { + Self::new() + } +} + +impl sp_core::traits::SpawnNamed for TokioTestExecutor { + fn spawn_blocking( + &self, + _name: &'static str, + _group: Option<&'static str>, + future: futures::future::BoxFuture<'static, ()>, + ) { + let handle = self.0.clone(); + self.0.spawn_blocking(move || { + handle.block_on(future); + }); + } + fn spawn( + &self, + _name: &'static str, + _group: Option<&'static str>, + future: futures::future::BoxFuture<'static, ()>, + ) { + self.0.spawn(future); + } +} /// Executor for testing. -pub fn test_executor() -> Arc { - Arc::new(TaskExecutor::default()) +pub fn test_executor() -> Arc { + Arc::new(TokioTestExecutor::default()) } /// Wrap a future in a timeout a little more concisely diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 5ffceb3eb05ad..832367035cc81 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -22,7 +22,7 @@ test-helpers = [] runtime-benchmarks = ["sc-client-db/runtime-benchmarks"] [dependencies] -jsonrpsee = { version = "0.16.2", features = ["server"] } +jsonrpsee = { version = "0.19.0", features = ["server"] } thiserror = "1.0.30" futures = "0.3.21" rand = "0.8.5" diff --git a/client/service/src/config.rs b/client/service/src/config.rs index c0fb2dc9c4c70..2bc3801c528b0 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -103,6 +103,8 @@ pub struct Configuration { pub rpc_max_subs_per_conn: u32, /// JSON-RPC server default port. pub rpc_port: u16, + /// The number of messages the JSON-RPC server is allowed to keep in memory. + pub rpc_message_buffer_capacity: u32, /// Prometheus endpoint configuration. `None` if disabled. pub prometheus_config: Option, /// Telemetry service URL. `None` if disabled. diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 4a896ecc87263..0ade1a93abe60 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -37,7 +37,7 @@ mod task_manager; use std::{collections::HashMap, net::SocketAddr}; use codec::{Decode, Encode}; -use futures::{channel::mpsc, pin_mut, FutureExt, StreamExt}; +use futures::{pin_mut, FutureExt, StreamExt}; use jsonrpsee::{core::Error as JsonRpseeError, RpcModule}; use log::{debug, error, warn}; use sc_client_api::{blockchain::HeaderBackend, BlockBackend, BlockchainEvents, ProofProvider}; @@ -111,9 +111,9 @@ impl RpcHandlers { pub async fn rpc_query( &self, json_query: &str, - ) -> Result<(String, mpsc::UnboundedReceiver), JsonRpseeError> { + ) -> Result<(String, tokio::sync::mpsc::Receiver), JsonRpseeError> { self.0 - .raw_json_request(json_query) + .raw_json_request(json_query, usize::MAX) .await .map(|(method_res, recv)| (method_res.result, recv)) } @@ -396,6 +396,7 @@ where max_payload_in_mb: config.rpc_max_request_size, max_payload_out_mb: config.rpc_max_response_size, max_subs_per_conn: config.rpc_max_subs_per_conn, + message_buffer_capacity: config.rpc_message_buffer_capacity, rpc_api: gen_rpc_module(deny_unsafe(addr, &config.rpc_methods))?, metrics, id_provider: rpc_id_provider, diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index 11c672db8cb90..6b14cb99acb56 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -255,6 +255,7 @@ fn node_config< rpc_id_provider: Default::default(), rpc_max_subs_per_conn: Default::default(), rpc_port: 9944, + rpc_message_buffer_capacity: Default::default(), prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index 79013cbd5b33a..587e0427f0898 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1" } -jsonrpsee = { version = "0.16.2", features = ["client-core", "server", "macros"] } +jsonrpsee = { version = "0.19.0", features = ["client-core", "server", "macros"] } serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.85" thiserror = "1.0.30" diff --git a/client/sync-state-rpc/src/lib.rs b/client/sync-state-rpc/src/lib.rs index dda8a7edfa9bb..cb737cc6c52b3 100644 --- a/client/sync-state-rpc/src/lib.rs +++ b/client/sync-state-rpc/src/lib.rs @@ -44,9 +44,9 @@ use std::sync::Arc; use jsonrpsee::{ - core::{async_trait, Error as JsonRpseeError, RpcResult}, + core::async_trait, proc_macros::rpc, - types::{error::CallError, ErrorObject}, + types::{ErrorObject, ErrorObjectOwned}, }; use sc_client_api::StorageData; @@ -80,13 +80,13 @@ pub enum Error { LightSyncStateExtensionNotFound, } -impl From> for JsonRpseeError { +impl From> for ErrorObjectOwned { fn from(error: Error) -> Self { let message = match error { Error::JsonRpc(s) => s, _ => error.to_string(), }; - CallError::Custom(ErrorObject::owned(1, message, None::<()>)).into() + ErrorObject::owned(1, message, None::<()>) } } @@ -126,10 +126,10 @@ pub struct LightSyncState { /// An api for sync state RPC calls. #[rpc(client, server)] -pub trait SyncStateApi { +pub trait SyncStateApi { /// Returns the JSON serialized chainspec running the node, with a sync state. #[method(name = "sync_state_genSyncSpec")] - async fn system_gen_sync_spec(&self, raw: bool) -> RpcResult; + async fn system_gen_sync_spec(&self, raw: bool) -> Result>; } /// An api for sync state RPC calls. @@ -188,12 +188,12 @@ where } #[async_trait] -impl SyncStateApiServer for SyncState +impl SyncStateApiServer for SyncState where Block: BlockT, Backend: HeaderBackend + sc_client_api::AuxStore + 'static, { - async fn system_gen_sync_spec(&self, raw: bool) -> RpcResult { + async fn system_gen_sync_spec(&self, raw: bool) -> Result> { let current_sync_state = self.build_sync_state().await?; let mut chain_spec = self.chain_spec.cloned_box(); @@ -202,10 +202,11 @@ where ) .ok_or(Error::::LightSyncStateExtensionNotFound)?; - let val = serde_json::to_value(¤t_sync_state)?; + let val = serde_json::to_value(¤t_sync_state) + .map_err(|e| Error::::JsonRpc(e.to_string()))?; *extension = Some(val); let json_str = chain_spec.as_json(raw).map_err(|e| Error::::JsonRpc(e))?; - serde_json::from_str(&json_str).map_err(Into::into) + serde_json::from_str(&json_str).map_err(|e| Error::::JsonRpc(e.to_string())) } } diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs index b11e164fe8e44..e5ec61d622e95 100644 --- a/frame/benchmarking/src/lib.rs +++ b/frame/benchmarking/src/lib.rs @@ -246,22 +246,21 @@ pub use v1::*; /// of impls and structs required by the benchmarking engine. Additionally, a benchmark /// function is also generated that resembles the function definition you provide, with a few /// modifications: -/// 1. The function name is transformed from i.e. `original_name` to `_original_name` so as not -/// to collide with the struct `original_name` that is created for some of the benchmarking -/// engine impls. -/// 2. Appropriate `T: Config` and `I` (if this is an instance benchmark) generics are added to -/// the function automatically during expansion, so you should not add these manually on -/// your function definition (but you may make use of `T` and `I` anywhere within your -/// benchmark function, in any of the three sections (setup, call, verification). +/// 1. The function name is transformed from i.e. `original_name` to `_original_name` so as not to +/// collide with the struct `original_name` that is created for some of the benchmarking engine +/// impls. +/// 2. Appropriate `T: Config` and `I` (if this is an instance benchmark) generics are added to the +/// function automatically during expansion, so you should not add these manually on your +/// function definition (but you may make use of `T` and `I` anywhere within your benchmark +/// function, in any of the three sections (setup, call, verification). /// 3. Arguments such as `u: Linear<10, 100>` are converted to `u: u32` to make the function /// directly callable. -/// 4. A `verify: bool` param is added as the last argument. Specifying `true` will result in -/// the verification section of your function executing, while a value of `false` will skip +/// 4. A `verify: bool` param is added as the last argument. Specifying `true` will result in the +/// verification section of your function executing, while a value of `false` will skip /// verification. /// 5. If you specify a return type on the function definition, it must conform to the [rules -/// below](#support-for-result-benchmarkerror-and-the--operator), and the last statement of -/// the function definition must resolve to something compatible with `Result<(), -/// BenchmarkError>`. +/// below](#support-for-result-benchmarkerror-and-the--operator), and the last statement of the +/// function definition must resolve to something compatible with `Result<(), BenchmarkError>`. /// /// The reason we generate an actual function as part of the expansion is to allow the compiler /// to enforce several constraints that would otherwise be difficult to enforce and to reduce diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index c6eedb155d6a4..94307811b8689 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -145,21 +145,20 @@ impl Limits { /// There there is one field for each wasm instruction that describes the weight to /// execute one instruction of that name. There are a few exceptions: /// -/// 1. If there is a i64 and a i32 variant of an instruction we use the weight -/// of the former for both. -/// 2. The following instructions are free of charge because they merely structure the -/// wasm module and cannot be spammed without making the module invalid (and rejected): -/// End, Unreachable, Return, Else -/// 3. The following instructions cannot be benchmarked because they are removed by any -/// real world execution engine as a preprocessing step and therefore don't yield a -/// meaningful benchmark result. However, in contrast to the instructions mentioned -/// in 2. they can be spammed. We price them with the same weight as the "default" -/// instruction (i64.const): Block, Loop, Nop -/// 4. We price both i64.const and drop as InstructionWeights.i64const / 2. The reason -/// for that is that we cannot benchmark either of them on its own but we need their -/// individual values to derive (by subtraction) the weight of all other instructions -/// that use them as supporting instructions. Supporting means mainly pushing arguments -/// and dropping return values in order to maintain a valid module. +/// 1. If there is a i64 and a i32 variant of an instruction we use the weight of the former for +/// both. +/// 2. The following instructions are free of charge because they merely structure the wasm module +/// and cannot be spammed without making the module invalid (and rejected): End, Unreachable, +/// Return, Else +/// 3. The following instructions cannot be benchmarked because they are removed by any real world +/// execution engine as a preprocessing step and therefore don't yield a meaningful benchmark +/// result. However, in contrast to the instructions mentioned in 2. they can be spammed. We +/// price them with the same weight as the "default" instruction (i64.const): Block, Loop, Nop +/// 4. We price both i64.const and drop as InstructionWeights.i64const / 2. The reason for that is +/// that we cannot benchmark either of them on its own but we need their individual values to +/// derive (by subtraction) the weight of all other instructions that use them as supporting +/// instructions. Supporting means mainly pushing arguments and dropping return values in order +/// to maintain a valid module. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[derive(Clone, Encode, Decode, PartialEq, Eq, ScheduleDebug, TypeInfo)] #[scale_info(skip_type_params(T))] diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index 1f9557a427293..e1adbc062424f 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -656,7 +656,7 @@ impl Pallet { // // At index `idx`: // 1. A (ImOnline) public key to be used by a validator at index `idx` to send im-online - // heartbeats. + // heartbeats. let authorities = Keys::::get(); // local keystore diff --git a/frame/recovery/src/lib.rs b/frame/recovery/src/lib.rs index d66b5725fd4f7..8f70ebfe5ec67 100644 --- a/frame/recovery/src/lib.rs +++ b/frame/recovery/src/lib.rs @@ -48,34 +48,30 @@ //! ### Recovery Life Cycle //! //! The intended life cycle of a successful recovery takes the following steps: -//! 1. The account owner calls `create_recovery` to set up a recovery configuration -//! for their account. -//! 2. At some later time, the account owner loses access to their account and wants -//! to recover it. Likely, they will need to create a new account and fund it with -//! enough balance to support the transaction fees and the deposit for the -//! recovery process. -//! 3. Using this new account, they call `initiate_recovery`. -//! 4. Then the account owner would contact their configured friends to vouch for -//! the recovery attempt. The account owner would provide their old account id -//! and the new account id, and friends would call `vouch_recovery` with those -//! parameters. -//! 5. Once a threshold number of friends have vouched for the recovery attempt, -//! the account owner needs to wait until the delay period has passed, starting -//! when they initiated the recovery process. -//! 6. Now the account owner is able to call `claim_recovery`, which subsequently -//! allows them to call `as_recovered` and directly make calls on-behalf-of the lost +//! 1. The account owner calls `create_recovery` to set up a recovery configuration for their //! account. -//! 7. Using the now recovered account, the account owner can call `close_recovery` -//! on the recovery process they opened, reclaiming the recovery deposit they -//! placed. +//! 2. At some later time, the account owner loses access to their account and wants to recover it. +//! Likely, they will need to create a new account and fund it with enough balance to support the +//! transaction fees and the deposit for the recovery process. +//! 3. Using this new account, they call `initiate_recovery`. +//! 4. Then the account owner would contact their configured friends to vouch for the recovery +//! attempt. The account owner would provide their old account id and the new account id, and +//! friends would call `vouch_recovery` with those parameters. +//! 5. Once a threshold number of friends have vouched for the recovery attempt, the account owner +//! needs to wait until the delay period has passed, starting when they initiated the recovery +//! process. +//! 6. Now the account owner is able to call `claim_recovery`, which subsequently allows them to +//! call `as_recovered` and directly make calls on-behalf-of the lost account. +//! 7. Using the now recovered account, the account owner can call `close_recovery` on the recovery +//! process they opened, reclaiming the recovery deposit they placed. //! 8. Then the account owner should then call `remove_recovery` to remove the recovery -//! configuration on the recovered account and reclaim the recovery configuration -//! deposit they placed. -//! 9. Using `as_recovered`, the account owner is able to call any other pallets -//! to clean up their state and reclaim any reserved or locked funds. They -//! can then transfer all funds from the recovered account to the new account. -//! 10. When the recovered account becomes reaped (i.e. its free and reserved -//! balance drops to zero), the final recovery link is removed. +//! configuration on the recovered account and reclaim the recovery configuration deposit they +//! placed. +//! 9. Using `as_recovered`, the account owner is able to call any other pallets to clean up their +//! state and reclaim any reserved or locked funds. They can then transfer all funds from the +//! recovered account to the new account. +//! 10. When the recovered account becomes reaped (i.e. its free and reserved balance drops to +//! zero), the final recovery link is removed. //! //! ### Malicious Recovery Attempts //! diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 8d021045ed675..92cf544995255 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -2708,13 +2708,13 @@ pub mod pallet_prelude { /// - query the metadata using the `state_getMetadata` RPC and curl, or use `subsee -p /// > meta.json` /// 2. Generate the template upgrade for the pallet provided by `decl_storage` with the -/// environment variable `PRINT_PALLET_UPGRADE`: `PRINT_PALLET_UPGRADE=1 cargo check -p -/// my_pallet`. This template can be used as it contains all information for storages, -/// genesis config and genesis build. +/// environment variable `PRINT_PALLET_UPGRADE`: `PRINT_PALLET_UPGRADE=1 cargo check -p +/// my_pallet`. This template can be used as it contains all information for storages, +/// genesis config and genesis build. /// 3. Reorganize the pallet to have the trait `Config`, `decl_*` macros, -/// [`ValidateUnsigned`](`pallet_prelude::ValidateUnsigned`), -/// [`ProvideInherent`](`pallet_prelude::ProvideInherent`), and Origin` all together in one -/// file. Suggested order: +/// [`ValidateUnsigned`](`pallet_prelude::ValidateUnsigned`), +/// [`ProvideInherent`](`pallet_prelude::ProvideInherent`), and Origin` all together in one +/// file. Suggested order: /// * `Config`, /// * `decl_module`, /// * `decl_event`, @@ -2774,8 +2774,8 @@ pub mod pallet_prelude { /// 8. **migrate error**: rewrite it with attribute /// [`#[pallet::error]`](#error-palleterror-optional). /// 9. **migrate storage**: `decl_storage` provide an upgrade template (see 3.). All storages, -/// genesis config, genesis build and default implementation of genesis config can be -/// taken from it directly. +/// genesis config, genesis build and default implementation of genesis config can be taken +/// from it directly. /// /// Otherwise here is the manual process: /// diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index 28eb562e97d0c..1f930b4df0b5d 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1" } -jsonrpsee = { version = "0.16.2", features = ["client-core", "server", "macros"] } +jsonrpsee = { version = "0.19.0", features = ["client-core", "server", "macros"] } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", path = "./runtime-api" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/frame/transaction-payment/rpc/src/lib.rs b/frame/transaction-payment/rpc/src/lib.rs index 7f8ed4b802675..5b141a6bdad88 100644 --- a/frame/transaction-payment/rpc/src/lib.rs +++ b/frame/transaction-payment/rpc/src/lib.rs @@ -21,9 +21,8 @@ use std::{convert::TryInto, sync::Arc}; use codec::{Codec, Decode}; use jsonrpsee::{ - core::{Error as JsonRpseeError, RpcResult}, proc_macros::rpc, - types::error::{CallError, ErrorCode, ErrorObject}, + types::error::{ErrorObject, ErrorObjectOwned}, }; use pallet_transaction_payment_rpc_runtime_api::{FeeDetails, InclusionFee, RuntimeDispatchInfo}; use sp_api::ProvideRuntimeApi; @@ -37,14 +36,14 @@ pub use pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi as Tra #[rpc(client, server)] pub trait TransactionPaymentApi { #[method(name = "payment_queryInfo")] - fn query_info(&self, encoded_xt: Bytes, at: Option) -> RpcResult; + fn query_info(&self, encoded_xt: Bytes, at: Option) -> Result; #[method(name = "payment_queryFeeDetails")] fn query_fee_details( &self, encoded_xt: Bytes, at: Option, - ) -> RpcResult>; + ) -> Result, Error>; } /// Provides RPC methods to query a dispatchable's class, weight and fee. @@ -64,16 +63,21 @@ impl TransactionPayment { /// Error type of this RPC api. pub enum Error { /// The transaction was not decodable. - DecodeError, + DecodeError { msg: String, err: codec::Error }, /// The call to runtime failed. - RuntimeError, + RuntimeError { msg: String, err: sp_api::ApiError }, + /// Balance too large + BalanceTooLarge(String), } -impl From for i32 { - fn from(e: Error) -> i32 { - match e { - Error::RuntimeError => 1, - Error::DecodeError => 2, +impl From for ErrorObjectOwned { + fn from(err: Error) -> Self { + match err { + Error::RuntimeError { msg, err } => + ErrorObject::owned(1, msg, Some(format!("{:?}", err))), + Error::DecodeError { msg, err } => + ErrorObject::owned(2, msg, Some(format!("{:?}", err))), + Error::BalanceTooLarge(msg) => ErrorObject::owned(3, msg, None::<()>), } } } @@ -93,31 +97,20 @@ where &self, encoded_xt: Bytes, at: Option, - ) -> RpcResult> { + ) -> Result, Error> { let api = self.client.runtime_api(); let at_hash = at.unwrap_or_else(|| self.client.info().best_hash); let encoded_len = encoded_xt.len() as u32; let uxt: Block::Extrinsic = Decode::decode(&mut &*encoded_xt).map_err(|e| { - CallError::Custom(ErrorObject::owned( - Error::DecodeError.into(), - "Unable to query dispatch info.", - Some(format!("{:?}", e)), - )) + Error::DecodeError { msg: "Unable to query dispatch info.".to_string(), err: e } })?; - fn map_err(error: impl ToString, desc: &'static str) -> CallError { - CallError::Custom(ErrorObject::owned( - Error::RuntimeError.into(), - desc, - Some(error.to_string()), - )) - } - - let res = api - .query_info(at_hash, uxt, encoded_len) - .map_err(|e| map_err(e, "Unable to query dispatch info."))?; + let res = api.query_info(at_hash, uxt, encoded_len).map_err(|e| Error::RuntimeError { + msg: "Unable to query dispatch info.".to_string(), + err: e, + })?; Ok(RuntimeDispatchInfo { weight: res.weight, @@ -130,34 +123,28 @@ where &self, encoded_xt: Bytes, at: Option, - ) -> RpcResult> { + ) -> Result, Error> { let api = self.client.runtime_api(); let at_hash = at.unwrap_or_else(|| self.client.info().best_hash); let encoded_len = encoded_xt.len() as u32; let uxt: Block::Extrinsic = Decode::decode(&mut &*encoded_xt).map_err(|e| { - CallError::Custom(ErrorObject::owned( - Error::DecodeError.into(), - "Unable to query fee details.", - Some(format!("{:?}", e)), - )) - })?; - let fee_details = api.query_fee_details(at_hash, uxt, encoded_len).map_err(|e| { - CallError::Custom(ErrorObject::owned( - Error::RuntimeError.into(), - "Unable to query fee details.", - Some(e.to_string()), - )) + Error::DecodeError { msg: "Unable to query fee details.".to_string(), err: e } })?; + let fee_details = + api.query_fee_details(at_hash, uxt, encoded_len) + .map_err(|e| Error::RuntimeError { + msg: "Unable to query fee details.".to_string(), + err: e, + })?; let try_into_rpc_balance = |value: Balance| { value.try_into().map_err(|_| { - JsonRpseeError::Call(CallError::Custom(ErrorObject::owned( - ErrorCode::InvalidParams.code(), - format!("{} doesn't fit in NumberOrHex representation", value), - None::<()>, - ))) + Error::BalanceTooLarge(format!( + "{} doesn't fit in NumberOrHex representation", + value + )) }) }; diff --git a/frame/transaction-payment/src/types.rs b/frame/transaction-payment/src/types.rs index cbe85309b856a..04ae5a1eb4f1a 100644 --- a/frame/transaction-payment/src/types.rs +++ b/frame/transaction-payment/src/types.rs @@ -94,7 +94,7 @@ impl FeeDetails { /// Information related to a dispatchable's class, weight, and fee that can be queried from the /// runtime. #[derive(Eq, PartialEq, Encode, Decode, Default, TypeInfo)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[cfg_attr(feature = "std", derive(Clone, Debug, Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr( feature = "std", diff --git a/primitives/npos-elections/src/balancing.rs b/primitives/npos-elections/src/balancing.rs index 234326ee94dd2..90dbe7eb71478 100644 --- a/primitives/npos-elections/src/balancing.rs +++ b/primitives/npos-elections/src/balancing.rs @@ -19,7 +19,7 @@ //! //! Given a committee `A` and an edge weight vector `w`, a balanced solution is one that //! -//! 1. it maximizes the sum of member supports, i.e `Argmax { sum(support(c)) }`. for all `c` in +//! 1. it maximizes the sum of member supports, i.e `Argmax { sum(support(c)) }`. for all `c` in //! `A`. //! 2. it minimizes the sum of supports squared, i.e `Argmin { sum(support(c).pow(2)) }` for all `c` //! in `A`. diff --git a/primitives/rpc/src/list.rs b/primitives/rpc/src/list.rs index 860e5161b97c1..5c63d963d68b8 100644 --- a/primitives/rpc/src/list.rs +++ b/primitives/rpc/src/list.rs @@ -29,7 +29,7 @@ use serde::{Deserialize, Serialize}; /// /// Also it's nice to be able to maintain backward compatibility for methods that /// were initially taking a value and now we want to expand them to take a list. -#[derive(Serialize, Deserialize, Debug, PartialEq)] +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] #[serde(untagged)] pub enum ListOrValue { /// A list of values of given type. diff --git a/primitives/runtime/src/offchain/http.rs b/primitives/runtime/src/offchain/http.rs index 25e5c1007d5da..bacc0073825bb 100644 --- a/primitives/runtime/src/offchain/http.rs +++ b/primitives/runtime/src/offchain/http.rs @@ -343,10 +343,10 @@ impl Response { /// A buffered byte iterator over response body. /// /// Note that reading the body may return `None` in following cases: -/// 1. Either the deadline you've set is reached (check via `#error`; -/// In such case you can resume the reader by setting a new deadline) -/// 2. Or because of IOError. In such case the reader is not resumable and will keep -/// returning `None`. +/// 1. Either the deadline you've set is reached (check via `#error`; In such case you can resume +/// the reader by setting a new deadline) +/// 2. Or because of IOError. In such case the reader is not resumable and will keep returning +/// `None`. /// 3. The body has been returned. The reader will keep returning `None`. #[derive(Clone)] pub struct ResponseBody { diff --git a/primitives/staking/src/offence.rs b/primitives/staking/src/offence.rs index 6694c9055d4ff..8013166374e06 100644 --- a/primitives/staking/src/offence.rs +++ b/primitives/staking/src/offence.rs @@ -220,16 +220,16 @@ pub struct OffenceDetails { /// for a typical usage scenario: /// /// 1. An offence is detected and an evidence is submitted on-chain via the -/// [`OffenceReportSystem::publish_evidence`] method. This will construct -/// and submit an extrinsic transaction containing the offence evidence. +/// [`OffenceReportSystem::publish_evidence`] method. This will construct and submit an extrinsic +/// transaction containing the offence evidence. /// -/// 2. If the extrinsic is unsigned then the transaction receiver may want to -/// perform some preliminary checks before further processing. This is a good -/// place to call the [`OffenceReportSystem::check_evidence`] method. +/// 2. If the extrinsic is unsigned then the transaction receiver may want to perform some +/// preliminary checks before further processing. This is a good place to call the +/// [`OffenceReportSystem::check_evidence`] method. /// -/// 3. Finally the report extrinsic is executed on-chain. This is where the user -/// calls the [`OffenceReportSystem::process_evidence`] to consume the offence -/// report and enact any required action. +/// 3. Finally the report extrinsic is executed on-chain. This is where the user calls the +/// [`OffenceReportSystem::process_evidence`] to consume the offence report and enact any +/// required action. pub trait OffenceReportSystem { /// Longevity, in blocks, for the evidence report validity. /// diff --git a/primitives/storage/src/lib.rs b/primitives/storage/src/lib.rs index aa1bc8e305c9b..d1c40b7d64e02 100644 --- a/primitives/storage/src/lib.rs +++ b/primitives/storage/src/lib.rs @@ -178,8 +178,8 @@ pub struct Storage { /// Storage change set #[derive(RuntimeDebug)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, PartialEq, Eq))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", derive(Clone, Serialize, Deserialize, PartialEq, Eq))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] pub struct StorageChangeSet { /// Block hash pub block: Hash, diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index d813f8e465469..49022f8ffaeac 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -36,3 +36,4 @@ sp-keyring = { version = "24.0.0", path = "../../primitives/keyring" } sp-keystore = { version = "0.27.0", path = "../../primitives/keystore" } sp-runtime = { version = "24.0.0", path = "../../primitives/runtime" } sp-state-machine = { version = "0.28.0", path = "../../primitives/state-machine" } +tokio = { version = "1", features = ["sync"] } diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index 94006fd9acb8e..01b97749bf523 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -314,7 +314,7 @@ pub struct RpcTransactionOutput { /// The output string of the transaction if any. pub result: String, /// An async receiver if data will be returned via a callback. - pub receiver: futures::channel::mpsc::UnboundedReceiver, + pub receiver: tokio::sync::mpsc::Receiver, } impl std::fmt::Debug for RpcTransactionOutput { @@ -374,7 +374,7 @@ impl RpcHandlersExt for RpcHandlers { pub(crate) fn parse_rpc_result( result: String, - receiver: futures::channel::mpsc::UnboundedReceiver, + receiver: tokio::sync::mpsc::Receiver, ) -> Result { let json: serde_json::Value = serde_json::from_str(&result).expect("the result can only be a JSONRPC string; qed"); @@ -428,7 +428,7 @@ where mod tests { #[test] fn parses_error_properly() { - let (_, rx) = futures::channel::mpsc::unbounded(); + let (_, rx) = tokio::sync::mpsc::channel(16); assert!(super::parse_rpc_result( r#"{ "jsonrpc": "2.0", @@ -440,7 +440,7 @@ mod tests { ) .is_ok()); - let (_, rx) = futures::channel::mpsc::unbounded(); + let (_, rx) = tokio::sync::mpsc::channel(16); let error = super::parse_rpc_result( r#"{ "jsonrpc": "2.0", @@ -458,7 +458,7 @@ mod tests { assert_eq!(error.message, "Method not found"); assert!(error.data.is_none()); - let (_, rx) = futures::channel::mpsc::unbounded(); + let (_, rx) = tokio::sync::mpsc::channel(16); let error = super::parse_rpc_result( r#"{ "jsonrpc": "2.0", diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index 82a258e0ec39b..1bdbb08b25a93 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -12,7 +12,7 @@ description = "An externalities provided environment that can load itself from r targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee = { version = "0.16.2", features = ["http-client"] } +jsonrpsee = { version = "0.19.0", features = ["http-client"] } codec = { package = "parity-scale-codec", version = "3.6.1" } log = "0.4.17" serde = "1.0.163" diff --git a/utils/frame/remote-externalities/src/lib.rs b/utils/frame/remote-externalities/src/lib.rs index 42df99137b2de..77488893b1874 100644 --- a/utils/frame/remote-externalities/src/lib.rs +++ b/utils/frame/remote-externalities/src/lib.rs @@ -152,7 +152,8 @@ impl Transport { uri.clone() }; let http_client = HttpClientBuilder::default() - .max_request_body_size(u32::MAX) + .max_request_size(u32::MAX) + .max_response_size(u32::MAX) .request_timeout(std::time::Duration::from_secs(60 * 5)) .build(uri) .map_err(|e| { diff --git a/utils/frame/rpc/client/Cargo.toml b/utils/frame/rpc/client/Cargo.toml index d39fbbdf48603..73021c7d5122b 100644 --- a/utils/frame/rpc/client/Cargo.toml +++ b/utils/frame/rpc/client/Cargo.toml @@ -12,7 +12,7 @@ description = "Shared JSON-RPC client" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee = { version = "0.16.2", features = ["ws-client"] } +jsonrpsee = { version = "0.19.0", features = ["ws-client"] } sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } async-trait = "0.1.57" serde = "1" diff --git a/utils/frame/rpc/client/src/lib.rs b/utils/frame/rpc/client/src/lib.rs index a6a667bef5681..9349ee2d357b2 100644 --- a/utils/frame/rpc/client/src/lib.rs +++ b/utils/frame/rpc/client/src/lib.rs @@ -61,10 +61,11 @@ pub use sc_rpc_api::{ /// Create a new `WebSocket` connection with shared settings. pub async fn ws_client(uri: impl AsRef) -> Result { WsClientBuilder::default() - .max_request_body_size(u32::MAX) + .max_request_size(u32::MAX) + .max_response_size(u32::MAX) .request_timeout(std::time::Duration::from_secs(60 * 10)) .connection_timeout(std::time::Duration::from_secs(60)) - .max_notifs_per_subscription(1024) + .max_buffer_capacity_per_subscription(1024) .build(uri) .await .map_err(|e| format!("`WsClientBuilder` failed to build: {:?}", e)) diff --git a/utils/frame/rpc/state-trie-migration-rpc/Cargo.toml b/utils/frame/rpc/state-trie-migration-rpc/Cargo.toml index 34546f43a4fea..db09f235ac6a3 100644 --- a/utils/frame/rpc/state-trie-migration-rpc/Cargo.toml +++ b/utils/frame/rpc/state-trie-migration-rpc/Cargo.toml @@ -13,6 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] +thiserror = "1.0.40" scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } serde = { version = "1", features = ["derive"] } @@ -23,7 +24,7 @@ sp-state-machine = { path = "../../../../primitives/state-machine" } sp-trie = { path = "../../../../primitives/trie" } trie-db = "0.27.0" -jsonrpsee = { version = "0.16.2", features = ["client-core", "server", "macros"] } +jsonrpsee = { version = "0.19.0", features = ["client-core", "server", "macros"] } # Substrate Dependencies sc-client-api = { version = "4.0.0-dev", path = "../../../../client/api" } diff --git a/utils/frame/rpc/state-trie-migration-rpc/src/lib.rs b/utils/frame/rpc/state-trie-migration-rpc/src/lib.rs index d1175fdea907a..fa58e6310b81e 100644 --- a/utils/frame/rpc/state-trie-migration-rpc/src/lib.rs +++ b/utils/frame/rpc/state-trie-migration-rpc/src/lib.rs @@ -18,11 +18,13 @@ //! Rpc for state migration. use jsonrpsee::{ - core::{Error as JsonRpseeError, RpcResult}, proc_macros::rpc, - types::error::{CallError, ErrorCode, ErrorObject}, + types::{ + error::{ErrorCode, ErrorObject}, + ErrorObjectOwned, + }, }; -use sc_rpc_api::DenyUnsafe; +use sc_rpc_api::{DenyUnsafe, UnsafeRpcError}; use serde::{Deserialize, Serialize}; use sp_runtime::traits::Block as BlockT; use std::sync::Arc; @@ -112,7 +114,7 @@ where } /// Current state migration status. -#[derive(Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] pub struct MigrationStatusResult { @@ -135,7 +137,7 @@ pub trait StateMigrationApi { /// won't change any state. Nonetheless it is a VERY costy call that should be /// only exposed to trusted peers. #[method(name = "state_trieMigrationStatus")] - fn call(&self, at: Option) -> RpcResult; + fn call(&self, at: Option) -> Result; } /// An implementation of state migration specific RPC methods. @@ -159,19 +161,35 @@ where C: Send + Sync + 'static + sc_client_api::HeaderBackend, BA: 'static + sc_client_api::backend::Backend, { - fn call(&self, at: Option<::Hash>) -> RpcResult { + fn call(&self, at: Option<::Hash>) -> Result { self.deny_unsafe.check_if_safe()?; let hash = at.unwrap_or_else(|| self.client.info().best_hash); - let state = self.backend.state_at(hash).map_err(error_into_rpc_err)?; - migration_status(&state).map_err(error_into_rpc_err) + let state = self.backend.state_at(hash).map_err(|e| Error::Client(e.to_string()))?; + migration_status(&state).map_err(|e| Error::Client(e.to_string())) } } -fn error_into_rpc_err(err: impl std::fmt::Display) -> JsonRpseeError { - JsonRpseeError::Call(CallError::Custom(ErrorObject::owned( - ErrorCode::InternalError.code(), - "Error while checking migration state", - Some(err.to_string()), - ))) +/// Error. +#[derive(Debug, thiserror::Error)] +pub enum Error { + /// Client error. + #[error("Client error: {}", .0)] + Client(String), + /// Call to an unsafe RPC was denied. + #[error(transparent)] + UnsafeRpcCalled(#[from] UnsafeRpcError), +} + +impl From for ErrorObjectOwned { + fn from(e: Error) -> Self { + match e { + Error::Client(err) => ErrorObject::owned( + ErrorCode::InternalError.code(), + "Error while checking migration state", + Some(err.to_string()), + ), + Error::UnsafeRpcCalled(e) => e.into(), + } + } } diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index 032840d457c35..063dc3c57beb0 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1" } -jsonrpsee = { version = "0.16.2", features = ["jsonrpsee-types"] } +jsonrpsee = { version = "0.19.0", features = ["jsonrpsee-types"] } serde = "1" frame-support = { version = "4.0.0-dev", path = "../../../../frame/support" } sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } @@ -24,7 +24,7 @@ sp-storage = { version = "13.0.0", path = "../../../../primitives/storage" } [dev-dependencies] scale-info = "2.1.1" -jsonrpsee = { version = "0.16.2", features = ["ws-client", "jsonrpsee-types"] } +jsonrpsee = { version = "0.19.0", features = ["ws-client", "jsonrpsee-types"] } tokio = "1.22.0" sp-core = { version = "21.0.0", path = "../../../../primitives/core" } sp-runtime = { version = "24.0.0", path = "../../../../primitives/runtime" } diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index f93f32ad64f2e..f24232e33323c 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1" } -jsonrpsee = { version = "0.16.2", features = ["client-core", "server", "macros"] } +jsonrpsee = { version = "0.19.0", features = ["client-core", "server", "macros"] } futures = "0.3.21" log = "0.4.17" frame-system-rpc-runtime-api = { version = "4.0.0-dev", path = "../../../../frame/system/rpc/runtime-api" } @@ -25,6 +25,7 @@ sp-block-builder = { version = "4.0.0-dev", path = "../../../../primitives/block sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } sp-core = { version = "21.0.0", path = "../../../../primitives/core" } sp-runtime = { version = "24.0.0", path = "../../../../primitives/runtime" } +thiserror = "1.0.40" [dev-dependencies] sc-transaction-pool = { version = "4.0.0-dev", path = "../../../../client/transaction-pool" } diff --git a/utils/frame/rpc/system/src/lib.rs b/utils/frame/rpc/system/src/lib.rs index 26efa02970efe..63b42a9af80c8 100644 --- a/utils/frame/rpc/system/src/lib.rs +++ b/utils/frame/rpc/system/src/lib.rs @@ -20,13 +20,9 @@ use std::{fmt::Display, sync::Arc}; use codec::{self, Codec, Decode, Encode}; -use jsonrpsee::{ - core::{async_trait, RpcResult}, - proc_macros::rpc, - types::error::{CallError, ErrorObject}, -}; +use jsonrpsee::{core::async_trait, proc_macros::rpc, types::error::ErrorObjectOwned}; -use sc_rpc_api::DenyUnsafe; +use sc_rpc_api::{DenyUnsafe, UnsafeRpcError}; use sc_transaction_pool_api::{InPoolTransaction, TransactionPool}; use sp_api::ApiExt; use sp_block_builder::BlockBuilder; @@ -45,26 +41,35 @@ pub trait SystemApi { /// currently in the pool and if no transactions are found in the pool /// it fallbacks to query the index from the runtime (aka. state nonce). #[method(name = "system_accountNextIndex", aliases = ["account_nextIndex"])] - async fn nonce(&self, account: AccountId) -> RpcResult; + async fn nonce(&self, account: AccountId) -> Result; /// Dry run an extrinsic at a given block. Return SCALE encoded ApplyExtrinsicResult. #[method(name = "system_dryRun", aliases = ["system_dryRunAt"])] - async fn dry_run(&self, extrinsic: Bytes, at: Option) -> RpcResult; + async fn dry_run(&self, extrinsic: Bytes, at: Option) -> Result; } /// Error type of this RPC api. +#[derive(Debug, thiserror::Error)] pub enum Error { /// The transaction was not decodable. - DecodeError, + #[error("{0}")] + DecodeError(String), /// The call to runtime failed. - RuntimeError, + #[error("{0}")] + RuntimeError(String), + /// Call to an unsafe RPC was denied. + #[error(transparent)] + UnsafeRpcCalled(#[from] UnsafeRpcError), } -impl From for i32 { - fn from(e: Error) -> i32 { +impl From for ErrorObjectOwned { + fn from(e: Error) -> ErrorObjectOwned { match e { - Error::RuntimeError => 1, - Error::DecodeError => 2, + Error::RuntimeError(e) => + ErrorObjectOwned::owned(1, "Unable to dry run extrinsic", Some(e)), + Error::DecodeError(e) => + ErrorObjectOwned::owned(2, "Unable to dry run extrinsic", Some(e)), + Error::UnsafeRpcCalled(e) => e.into(), } } } @@ -98,17 +103,13 @@ where AccountId: Clone + Display + Codec + Send + 'static, Index: Clone + Display + Codec + Send + traits::AtLeast32Bit + 'static, { - async fn nonce(&self, account: AccountId) -> RpcResult { + async fn nonce(&self, account: AccountId) -> Result { let api = self.client.runtime_api(); let best = self.client.info().best_hash; - let nonce = api.account_nonce(best, account.clone()).map_err(|e| { - CallError::Custom(ErrorObject::owned( - Error::RuntimeError.into(), - "Unable to query nonce.", - Some(e.to_string()), - )) - })?; + let nonce = api + .account_nonce(best, account.clone()) + .map_err(|e| Error::RuntimeError(e.to_string()))?; Ok(adjust_nonce(&*self.pool, account, nonce)) } @@ -116,7 +117,7 @@ where &self, extrinsic: Bytes, at: Option<::Hash>, - ) -> RpcResult { + ) -> Result { self.deny_unsafe.check_if_safe()?; let api = self.client.runtime_api(); let best_hash = at.unwrap_or_else(|| @@ -124,28 +125,15 @@ where self.client.info().best_hash); let uxt: ::Extrinsic = - Decode::decode(&mut &*extrinsic).map_err(|e| { - CallError::Custom(ErrorObject::owned( - Error::DecodeError.into(), - "Unable to dry run extrinsic", - Some(e.to_string()), - )) - })?; + Decode::decode(&mut &*extrinsic).map_err(|e| Error::DecodeError(e.to_string()))?; let api_version = api .api_version::>(best_hash) - .map_err(|e| { - CallError::Custom(ErrorObject::owned( - Error::RuntimeError.into(), - "Unable to dry run extrinsic.", - Some(e.to_string()), - )) - })? + .map_err(|e| Error::RuntimeError(e.to_string()))? .ok_or_else(|| { - CallError::Custom(ErrorObject::owned( - Error::RuntimeError.into(), - "Unable to dry run extrinsic.", - Some(format!("Could not find `BlockBuilder` api for block `{:?}`.", best_hash)), + Error::RuntimeError(format!( + "Could not find `BlockBuilder` api for block `{:?}`.", + best_hash )) })?; @@ -153,21 +141,10 @@ where #[allow(deprecated)] api.apply_extrinsic_before_version_6(best_hash, uxt) .map(legacy::byte_sized_error::convert_to_latest) - .map_err(|e| { - CallError::Custom(ErrorObject::owned( - Error::RuntimeError.into(), - "Unable to dry run extrinsic.", - Some(e.to_string()), - )) - })? + .map_err(|e| Error::RuntimeError(e.to_string()))? } else { - api.apply_extrinsic(best_hash, uxt).map_err(|e| { - CallError::Custom(ErrorObject::owned( - Error::RuntimeError.into(), - "Unable to dry run extrinsic.", - Some(e.to_string()), - )) - })? + api.apply_extrinsic(best_hash, uxt) + .map_err(|e| Error::RuntimeError(e.to_string()))? }; Ok(Encode::encode(&result).into()) @@ -216,7 +193,6 @@ mod tests { use assert_matches::assert_matches; use futures::executor::block_on; - use jsonrpsee::{core::Error as JsonRpseeError, types::error::CallError}; use sc_transaction_pool::BasicPool; use sp_runtime::{ generic::BlockId, @@ -274,8 +250,8 @@ mod tests { // when let res = accounts.dry_run(vec![].into(), None).await; - assert_matches!(res, Err(JsonRpseeError::Call(CallError::Custom(e))) => { - assert!(e.message().contains("RPC call is unsafe to be called externally")); + assert_matches!(res, Err(Error::UnsafeRpcCalled(e)) => { + assert_eq!(e.to_string(), "RPC call is unsafe to be called externally"); }); } diff --git a/utils/wasm-builder/src/builder.rs b/utils/wasm-builder/src/builder.rs index d0bed8d22a036..208b56077669e 100644 --- a/utils/wasm-builder/src/builder.rs +++ b/utils/wasm-builder/src/builder.rs @@ -80,8 +80,8 @@ impl WasmBuilderSelectProject { /// /// 1. Call [`WasmBuilder::new`] to create a new builder. /// 2. Select the project to build using the methods of [`WasmBuilderSelectProject`]. -/// 3. Set additional `RUST_FLAGS` or a different name for the file containing the WASM code -/// using methods of [`WasmBuilder`]. +/// 3. Set additional `RUST_FLAGS` or a different name for the file containing the WASM code using +/// methods of [`WasmBuilder`]. /// 4. Build the WASM binary using [`Self::build`]. pub struct WasmBuilder { /// Flags that should be appended to `RUST_FLAGS` env variable.