diff --git a/Cargo.lock b/Cargo.lock index b8a51717713..72c30e00cb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "adler32" version = "1.2.0" @@ -101,9 +107,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", @@ -116,33 +122,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.3" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -306,9 +312,9 @@ checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "assertables" @@ -335,7 +341,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -346,7 +352,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -394,7 +400,7 @@ dependencies = [ "futures-util", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.30", "itoa", "matchit", "memchr", @@ -421,9 +427,9 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-util", "itoa", "matchit", @@ -473,7 +479,7 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", @@ -493,7 +499,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object 0.32.2", "rustc-demangle", ] @@ -530,9 +536,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -566,9 +572,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe5b10e214954177fb1dc9fbd20a1a2608fe99e6c832033bdc7cea287a20d77" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ "borsh-derive", "cfg_aliases", @@ -576,38 +582,29 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a8646f94ab393e43e8b35a2558b1624bed28b97ee09c5d15456e3c9463f46d" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "syn_derive", ] [[package]] name = "bstr" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", - "regex-automata 0.4.6", + "regex-automata 0.4.7", "serde", ] -[[package]] -name = "btoi" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd6407f73a9b8b6162d8a2ef999fe6afd7cc15902ebf42c5cd296addf17e0ad" -dependencies = [ - "num-traits", -] - [[package]] name = "bumpalo" version = "3.16.0" @@ -661,15 +658,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "camino" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] @@ -705,13 +702,13 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.97" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" dependencies = [ "jobserver", "libc", - "once_cell", + "shlex", ] [[package]] @@ -722,9 +719,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chacha20" @@ -762,7 +759,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -805,9 +802,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.11" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -815,9 +812,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.11" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", @@ -827,21 +824,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.11" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clru" @@ -894,9 +891,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "colored" @@ -988,9 +985,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core2" @@ -1012,9 +1009,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -1131,9 +1128,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -1176,9 +1173,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -1213,9 +1210,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crossterm" @@ -1294,14 +1291,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "cxx" -version = "1.0.122" +version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb497fad022245b29c2a0351df572e2d67c1046bcef2260ebc022aec81efea82" +checksum = "3c4eae4b7fc8dcb0032eb3b1beee46b38d371cdeaf2d0c64b9944f6f69ad7755" dependencies = [ "cc", "cxxbridge-flags", @@ -1311,9 +1308,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.122" +version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9327c7f9fbd6329a200a5d4aa6f674c60ab256525ff0084b52a889d4e4c60cee" +checksum = "6c822bf7fb755d97328d6c337120b6f843678178751cba33c9da25cf522272e0" dependencies = [ "cc", "codespan-reporting", @@ -1321,24 +1318,24 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "cxxbridge-flags" -version = "1.0.122" +version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c799a4a846f1c0acb9f36bb9c6272d9b3d9457f3633c7753c6057270df13c" +checksum = "719d6197dc016c88744aff3c0d0340a01ecce12e8939fc282e7c8f583ee64bc6" [[package]] name = "cxxbridge-macro" -version = "1.0.122" +version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928bc249a7e3cd554fd2e8e08a426e9670c50bbfc9a621653cfa9accc9641783" +checksum = "35de3b547387863c8f82013c4f79f1c2162edee956383e4089e1d04c18c4f16c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1362,7 +1359,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1373,7 +1370,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1449,7 +1446,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1460,7 +1457,7 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1504,7 +1501,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1521,9 +1518,9 @@ checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" [[package]] name = "dunce" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "dyn-clone" @@ -1572,9 +1569,9 @@ dependencies = [ [[package]] name = "either" -version = "1.11.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -1601,6 +1598,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "encoding_rs" version = "0.8.34" @@ -1714,14 +1717,14 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox", + "windows-sys 0.59.0", ] [[package]] @@ -1744,12 +1747,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1844,7 +1847,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1892,7 +1895,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "debugid", "fxhash", "serde", @@ -1940,15 +1943,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" dependencies = [ "fallible-iterator", - "indexmap 2.2.6", + "indexmap 2.4.0", "stable_deref_trait", ] [[package]] name = "gix" -version = "0.57.1" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd025382892c7b500a9ce1582cd803f9c2ebfe44aff52e9c7f86feee7ced75e" +checksum = "984c5018adfa7a4536ade67990b3ebc6e11ab57b3d6cd9968de0947ca99b4b06" dependencies = [ "gix-actor", "gix-commitgraph", @@ -1984,21 +1987,20 @@ dependencies = [ "signal-hook", "smallvec", "thiserror", - "unicode-normalization", ] [[package]] name = "gix-actor" -version = "0.29.1" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da27b5ab4ab5c75ff891dccd48409f8cc53c28a79480f1efdd33184b2dc1d958" +checksum = "a0e454357e34b833cc3a00b6efbbd3dd4d18b24b9fb0c023876ec2645e8aa3f2" dependencies = [ "bstr", - "btoi", "gix-date", + "gix-utils", "itoa", "thiserror", - "winnow 0.5.40", + "winnow 0.6.18", ] [[package]] @@ -2021,9 +2023,9 @@ dependencies = [ [[package]] name = "gix-commitgraph" -version = "0.23.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8dcbf434951fa477063e05fea59722615af70dc2567377e58c2f7853b010fc" +checksum = "133b06f67f565836ec0c473e2116a60fb74f80b6435e21d88013ac0e3c60fc78" dependencies = [ "bstr", "gix-chunk", @@ -2035,9 +2037,9 @@ dependencies = [ [[package]] name = "gix-config" -version = "0.33.1" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "367304855b369cadcac4ee5fb5a3a20da9378dd7905106141070b79f85241079" +checksum = "53fafe42957e11d98e354a66b6bd70aeea00faf2f62dd11164188224a507c840" dependencies = [ "bstr", "gix-config-value", @@ -2051,16 +2053,16 @@ dependencies = [ "smallvec", "thiserror", "unicode-bom", - "winnow 0.5.40", + "winnow 0.6.18", ] [[package]] name = "gix-config-value" -version = "0.14.6" +version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd06203b1a9b33a78c88252a625031b094d9e1b647260070c25b09910c0a804" +checksum = "03f76169faa0dec598eac60f83d7fcdd739ec16596eca8fb144c88973dbe6f8c" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bstr", "gix-path", "libc", @@ -2069,9 +2071,9 @@ dependencies = [ [[package]] name = "gix-date" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "367ee9093b0c2b04fd04c5c7c8b6a1082713534eab537597ae343663a518fa99" +checksum = "9eed6931f21491ee0aeb922751bd7ec97b4b2fe8fbfedcb678e2a2dce5f3b8c0" dependencies = [ "bstr", "itoa", @@ -2081,9 +2083,9 @@ dependencies = [ [[package]] name = "gix-diff" -version = "0.39.1" +version = "0.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6a0454f8c42d686f17e7f084057c717c082b7dbb8209729e4e8f26749eb93a" +checksum = "1996d5c8a305b59709467d80617c9fde48d9d75fd1f4179ea970912630886c9d" dependencies = [ "bstr", "gix-hash", @@ -2093,12 +2095,13 @@ dependencies = [ [[package]] name = "gix-discover" -version = "0.28.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d7b2896edc3d899d28a646ccc6df729827a6600e546570b2783466404a42d6" +checksum = "fc27c699b63da66b50d50c00668bc0b7e90c3a382ef302865e891559935f3dbf" dependencies = [ "bstr", "dunce", + "gix-fs", "gix-hash", "gix-path", "gix-ref", @@ -2108,14 +2111,15 @@ dependencies = [ [[package]] name = "gix-features" -version = "0.37.2" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50270e8dcc665f30ba0735b17984b9535bdf1e646c76e638e007846164d57af" +checksum = "ac7045ac9fe5f9c727f38799d002a7ed3583cd777e3322a7c4b43e3cf437dc69" dependencies = [ "crc32fast", "flate2", "gix-hash", "gix-trace", + "gix-utils", "libc", "once_cell", "prodash", @@ -2126,20 +2130,22 @@ dependencies = [ [[package]] name = "gix-fs" -version = "0.9.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7555c23a005537434bbfcb8939694e18cad42602961d0de617f8477cc2adecdd" +checksum = "f2bfe6249cfea6d0c0e0990d5226a4cb36f030444ba9e35e0639275db8f98575" dependencies = [ + "fastrand", "gix-features", + "gix-utils", ] [[package]] name = "gix-glob" -version = "0.15.1" +version = "0.16.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6232f18b262770e343dcdd461c0011c9b9ae27f0c805e115012aa2b902c1b8" +checksum = "74908b4bbc0a0a40852737e5d7889f676f081e340d5451a16e5b4c50d592f111" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bstr", "gix-features", "gix-path", @@ -2168,14 +2174,14 @@ dependencies = [ [[package]] name = "gix-index" -version = "0.28.2" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e50e63df6c8d4137f7fb882f27643b3a9756c468a1a2cdbe1ce443010ca8778" +checksum = "9a9a44eb55bd84bb48f8a44980e951968ced21e171b22d115d1cdcef82a7d73f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bstr", - "btoi", "filetime", + "fnv", "gix-bitmap", "gix-features", "gix-fs", @@ -2183,6 +2189,9 @@ dependencies = [ "gix-lock", "gix-object", "gix-traverse", + "gix-utils", + "gix-validate", + "hashbrown 0.14.5", "itoa", "libc", "memmap2", @@ -2193,9 +2202,9 @@ dependencies = [ [[package]] name = "gix-lock" -version = "12.0.1" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40a439397f1e230b54cf85d52af87e5ea44cc1e7748379785d3f6d03d802b00" +checksum = "e3bc7fe297f1f4614774989c00ec8b1add59571dc9b024b4c00acb7dedd4e19d" dependencies = [ "gix-tempfile", "gix-utils", @@ -2204,43 +2213,44 @@ dependencies = [ [[package]] name = "gix-macros" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dff438f14e67e7713ab9332f5fd18c8f20eb7eb249494f6c2bf170522224032" +checksum = "999ce923619f88194171a67fb3e6d613653b8d4d6078b529b15a765da0edcc17" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "gix-object" -version = "0.40.1" +version = "0.42.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c89402e8faa41b49fde348665a8f38589e461036475af43b6b70615a6a313a2" +checksum = "25da2f46b4e7c2fa7b413ce4dffb87f69eaf89c2057e386491f4c55cadbfe386" dependencies = [ "bstr", - "btoi", "gix-actor", "gix-date", "gix-features", "gix-hash", + "gix-utils", "gix-validate", "itoa", "smallvec", "thiserror", - "winnow 0.5.40", + "winnow 0.6.18", ] [[package]] name = "gix-odb" -version = "0.56.1" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46ae6da873de41c6c2b73570e82c571b69df5154dcd8f46dfafc6687767c33b1" +checksum = "20d384fe541d93d8a3bb7d5d5ef210780d6df4f50c4e684ccba32665a5e3bc9b" dependencies = [ "arc-swap", "gix-date", "gix-features", + "gix-fs", "gix-hash", "gix-object", "gix-pack", @@ -2253,9 +2263,9 @@ dependencies = [ [[package]] name = "gix-pack" -version = "0.46.1" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "782b4d42790a14072d5c400deda9851f5765f50fe72bca6dece0da1cd6f05a9a" +checksum = "3e0594491fffe55df94ba1c111a6566b7f56b3f8d2e1efc750e77d572f5f5229" dependencies = [ "clru", "gix-chunk", @@ -2264,18 +2274,16 @@ dependencies = [ "gix-hashtable", "gix-object", "gix-path", - "gix-tempfile", "memmap2", - "parking_lot", "smallvec", "thiserror", ] [[package]] name = "gix-path" -version = "0.10.7" +version = "0.10.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23623cf0f475691a6d943f898c4d0b89f5c1a2a64d0f92bce0e0322ee6528783" +checksum = "38d5b8722112fa2fa87135298780bc833b0e9f6c56cc82795d209804b3a03484" dependencies = [ "bstr", "gix-trace", @@ -2297,9 +2305,9 @@ dependencies = [ [[package]] name = "gix-ref" -version = "0.40.1" +version = "0.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d9bd1984638d8f3511a2fcbe84fcedb8a5b5d64df677353620572383f42649" +checksum = "3394a2997e5bc6b22ebc1e1a87b41eeefbcfcff3dbfa7c4bd73cb0ac8f1f3e2e" dependencies = [ "gix-actor", "gix-date", @@ -2310,17 +2318,18 @@ dependencies = [ "gix-object", "gix-path", "gix-tempfile", + "gix-utils", "gix-validate", "memmap2", "thiserror", - "winnow 0.5.40", + "winnow 0.6.18", ] [[package]] name = "gix-refspec" -version = "0.21.1" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be219df5092c1735abb2a53eccdf775e945eea6986ee1b6e7a5896dccc0be704" +checksum = "6868f8cd2e62555d1f7c78b784bece43ace40dd2a462daf3b588d5416e603f37" dependencies = [ "bstr", "gix-hash", @@ -2332,9 +2341,9 @@ dependencies = [ [[package]] name = "gix-revision" -version = "0.25.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa78e1df3633bc937d4db15f8dca2abdb1300ca971c0fabcf9fa97e38cf4cd9f" +checksum = "01b13e43c2118c4b0537ddac7d0821ae0dfa90b7b8dbf20c711e153fb749adce" dependencies = [ "bstr", "gix-date", @@ -2348,9 +2357,9 @@ dependencies = [ [[package]] name = "gix-revwalk" -version = "0.11.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702de5fe5c2bbdde80219f3a8b9723eb927466e7ecd187cfd1b45d986408e45f" +checksum = "1b030ccaab71af141f537e0225f19b9e74f25fefdba0372246b844491cab43e0" dependencies = [ "gix-commitgraph", "gix-date", @@ -2363,11 +2372,11 @@ dependencies = [ [[package]] name = "gix-sec" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fddc27984a643b20dd03e97790555804f98cf07404e0e552c0ad8133266a79a1" +checksum = "0fe4d52f30a737bbece5276fab5d3a8b276dc2650df963e293d0673be34e7a5f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "gix-path", "libc", "windows-sys 0.52.0", @@ -2375,9 +2384,9 @@ dependencies = [ [[package]] name = "gix-tempfile" -version = "12.0.1" +version = "14.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8ef376d718b1f5f119b458e21b00fbf576bc9d4e26f8f383d29f5ffe3ba3eaa" +checksum = "046b4927969fa816a150a0cda2e62c80016fe11fb3c3184e4dddf4e542f108aa" dependencies = [ "gix-fs", "libc", @@ -2396,10 +2405,11 @@ checksum = "f924267408915fddcd558e3f37295cc7d6a3e50f8bd8b606cee0808c3915157e" [[package]] name = "gix-traverse" -version = "0.36.2" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65109e445ba7a409b48f34f570a4d7db72eade1dc1bcff81990a490e86c07161" +checksum = "e499a18c511e71cf4a20413b743b9f5bcf64b3d9e81e9c3c6cd399eae55a8840" dependencies = [ + "bitflags 2.6.0", "gix-commitgraph", "gix-date", "gix-hash", @@ -2412,9 +2422,9 @@ dependencies = [ [[package]] name = "gix-url" -version = "0.26.1" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f0f17cceb7552a231d1fec690bc2740c346554e3be6f5d2c41dfa809594dc44" +checksum = "fd280c5e84fb22e128ed2a053a0daeacb6379469be6a85e3d518a0636e160c89" dependencies = [ "bstr", "gix-features", @@ -2436,9 +2446,9 @@ dependencies = [ [[package]] name = "gix-validate" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e39fc6e06044985eac19dd34d474909e517307582e462b2eb4c8fa51b6241545" +checksum = "82c27dd34a49b1addf193c92070bcbf3beaf6e10f16a78544de6372e146a0acf" dependencies = [ "bstr", "thiserror", @@ -2473,7 +2483,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.2.6", + "indexmap 2.4.0", "slab", "tokio", "tokio-util", @@ -2559,6 +2569,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "hex" version = "0.4.3" @@ -2636,9 +2652,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http 1.1.0", @@ -2653,15 +2669,15 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -2677,9 +2693,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", @@ -2701,15 +2717,15 @@ dependencies = [ [[package]] name = "hyper" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -2724,7 +2740,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper 0.14.28", + "hyper 0.14.30", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -2732,15 +2748,15 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", - "hyper 1.3.1", + "http-body 1.0.1", + "hyper 1.4.1", "pin-project-lite", "tokio", ] @@ -2826,9 +2842,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", "hashbrown 0.14.5", @@ -2993,7 +3009,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.72", + "syn 2.0.75", "trybuild", ] @@ -3011,7 +3027,7 @@ dependencies = [ "eyre", "futures", "hex", - "indexmap 2.2.6", + "indexmap 2.4.0", "iroha_config", "iroha_crypto", "iroha_data_model", @@ -3050,7 +3066,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -3137,7 +3153,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.72", + "syn 2.0.75", "trybuild", ] @@ -3151,7 +3167,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "trybuild", ] @@ -3188,7 +3204,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -3200,7 +3216,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -3226,7 +3242,7 @@ dependencies = [ "quote", "rustc-hash", "strum 0.25.0", - "syn 2.0.72", + "syn 2.0.75", "trybuild", ] @@ -3234,14 +3250,17 @@ dependencies = [ name = "iroha_futures" version = "2.0.0-rc.1.0" dependencies = [ + "futures", "iroha_config", "iroha_futures_derive", "iroha_logger", "rand", "serde", "serde_json", + "thiserror", "tokio", "tokio-stream", + "tokio-util", ] [[package]] @@ -3252,7 +3271,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -3308,7 +3327,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -3340,6 +3359,7 @@ dependencies = [ "iroha_config_base", "iroha_crypto", "iroha_data_model", + "iroha_futures", "iroha_logger", "iroha_primitives", "parity-scale-codec", @@ -3380,7 +3400,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -3403,7 +3423,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "trybuild", ] @@ -3444,7 +3464,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -3515,7 +3535,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "trybuild", ] @@ -3578,7 +3598,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -3608,7 +3628,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.72", + "syn 2.0.75", "trybuild", ] @@ -3680,8 +3700,8 @@ dependencies = [ "supports-color 2.1.0", "tempfile", "thiserror", - "thread-local-panic-hook", "tokio", + "tokio-util", "toml", "tracing", "vergen", @@ -3689,11 +3709,11 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.4.0", "libc", "windows-sys 0.52.0", ] @@ -3706,9 +3726,9 @@ checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -3756,18 +3776,18 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -3837,9 +3857,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "leb128" @@ -3849,9 +3869,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libflate" @@ -3889,15 +3909,16 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", + "redox_syscall", ] [[package]] name = "libsodium-sys-stable" -version = "1.20.9" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad52c454200cd0178a04ef7642a240a7e81b4d8c59f0865eb98c477daf7d3b84" +checksum = "5fd1882b85f01cdd4021c0664fd897710a04c5d01b593a5a70e1b0baa999c1f8" dependencies = [ "cc", "libc", @@ -3921,9 +3942,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" @@ -3949,9 +3970,9 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ "hashbrown 0.14.5", ] @@ -3975,7 +3996,7 @@ dependencies = [ "manyhow-macros", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -4006,9 +4027,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memfd" @@ -4057,13 +4078,22 @@ checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" version = "0.8.11" @@ -4078,9 +4108,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi 0.3.9", "libc", @@ -4117,11 +4147,10 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -4181,9 +4210,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", @@ -4239,7 +4268,7 @@ checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "crc32fast", "hashbrown 0.14.5", - "indexmap 2.2.6", + "indexmap 2.4.0", "memchr", ] @@ -4251,9 +4280,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "opaque-debug" @@ -4267,7 +4296,7 @@ version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -4284,7 +4313,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -4295,9 +4324,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.2.3+3.2.1" +version = "300.3.1+3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cff92b6f71555b61bb9315f7c64da3ca43d87531622120fea0195fc761b4843" +checksum = "7259953d42a81bf137fbbd73bd30a8e1914d6dce43c2b90ed575783a22608b91" dependencies = [ "cc", ] @@ -4398,10 +4427,10 @@ dependencies = [ "cfg-if", "libc", "petgraph", - "redox_syscall 0.5.1", + "redox_syscall", "smallvec", "thread-id", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -4442,9 +4471,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -4453,9 +4482,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -4463,22 +4492,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "pest_meta" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", @@ -4492,7 +4521,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.2.6", + "indexmap 2.4.0", ] [[package]] @@ -4512,7 +4541,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -4545,9 +4574,9 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ "num-traits", "plotters-backend", @@ -4558,15 +4587,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" dependencies = [ "plotters-backend", ] @@ -4584,12 +4613,13 @@ dependencies = [ [[package]] name = "postcard" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" dependencies = [ "cobs", - "embedded-io", + "embedded-io 0.4.0", + "embedded-io 0.6.1", "serde", ] @@ -4622,9 +4652,12 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "pretty-error-debug" @@ -4642,7 +4675,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "788992637e9c73f809f7bdc647572785efb06cb7c860105a4e55e9c7d6935d39" dependencies = [ "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -4720,9 +4753,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", "prost-derive", @@ -4730,22 +4763,22 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9554e3ab233f0a932403704f1a1d08c30d5ccd931adfdfa1e8b5a19b52c1d55a" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "prost-types" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ "prost", ] @@ -4806,9 +4839,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -4871,27 +4904,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", @@ -4913,14 +4937,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -4934,13 +4958,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", ] [[package]] @@ -4951,9 +4975,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rend" @@ -4991,9 +5015,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.44" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" dependencies = [ "bitvec", "bytecheck", @@ -5009,9 +5033,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.44" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" dependencies = [ "proc-macro2", "quote", @@ -5026,9 +5050,9 @@ checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" [[package]] name = "rust_decimal" -version = "1.35.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a" +checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" dependencies = [ "arrayvec", "borsh", @@ -5067,7 +5091,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -5090,9 +5114,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +checksum = "04182dffc9091a404e0fc069ea5cd60e5b866c3adf881eff99a32d048242dffa" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -5103,9 +5127,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ "base64 0.22.1", "rustls-pki-types", @@ -5113,15 +5137,15 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" -version = "0.102.3" +version = "0.102.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" dependencies = [ "ring", "rustls-pki-types", @@ -5151,9 +5175,9 @@ dependencies = [ [[package]] name = "scc" -version = "2.1.1" +version = "2.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ad2bbb0ae5100a07b7a6f2ed7ab5fd0045551a4c507989b7a620046ea3efdc" +checksum = "aeb7ac86243095b70a7920639507b71d51a63390d1ba26c4f60a552fbb914a37" dependencies = [ "sdd", ] @@ -5181,9 +5205,9 @@ checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" [[package]] name = "sdd" -version = "0.2.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84345e4c9bd703274a082fb80caaa99b7612be48dfaa1dd9266577ec412309d" +checksum = "0495e4577c672de8254beb68d01a9b62d0e8a13c099edecdbedccce3223cd29f" [[package]] name = "seahash" @@ -5227,11 +5251,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -5240,9 +5264,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" dependencies = [ "core-foundation-sys", "libc", @@ -5259,29 +5283,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.204" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "serde_json" -version = "1.0.121" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" dependencies = [ "itoa", "memchr", @@ -5330,7 +5354,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.6", + "indexmap 2.4.0", "serde", "serde_derive", "serde_json", @@ -5347,7 +5371,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -5356,7 +5380,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.4.0", "itoa", "ryu", "serde", @@ -5385,7 +5409,7 @@ checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -5401,9 +5425,9 @@ dependencies = [ [[package]] name = "sha1_smol" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" @@ -5448,6 +5472,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook" version = "0.3.17" @@ -5460,9 +5490,9 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", "mio 0.8.11", @@ -5649,14 +5679,14 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "supports-color" @@ -5680,9 +5710,9 @@ dependencies = [ [[package]] name = "symbolic-common" -version = "12.8.0" +version = "12.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cccfffbc6bb3bb2d3a26cd2077f4d055f6808d266f9d4d158797a4c60510dfe" +checksum = "16629323a4ec5268ad23a575110a724ad4544aae623451de600c747bf87b36cf" dependencies = [ "debugid", "memmap2", @@ -5692,9 +5722,9 @@ dependencies = [ [[package]] name = "symbolic-demangle" -version = "12.8.0" +version = "12.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a99812da4020a67e76c4eb41f08c87364c14170495ff780f30dd519c221a68" +checksum = "48c043a45f08f41187414592b3ceb53fb0687da57209cc77401767fb69d5b596" dependencies = [ "cpp_demangle", "rustc-demangle", @@ -5714,9 +5744,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" dependencies = [ "proc-macro2", "quote", @@ -5732,7 +5762,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -5755,9 +5785,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" dependencies = [ "filetime", "libc", @@ -5766,20 +5796,21 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5803,6 +5834,7 @@ dependencies = [ "iroha_crypto", "iroha_data_model", "iroha_executor_data_model", + "iroha_futures", "iroha_genesis", "iroha_logger", "iroha_primitives", @@ -5845,25 +5877,19 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "thread-id" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0ec81c46e9eb50deaa257be2f148adf052d1fb7701cfd55ccfab2525280b70b" +checksum = "cfe8f25bbdd100db7e1d34acf7fd2dc59c4bf8f7483f505eaa7d4f12f76cc0ea" dependencies = [ "libc", "winapi", ] -[[package]] -name = "thread-local-panic-hook" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70399498abd3ec85f99a2f2d765c8638588e20361678af93a9f47de96719743" - [[package]] name = "thread_local" version = "1.1.8" @@ -5919,9 +5945,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -5934,14 +5960,14 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.2" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", "libc", - "mio 1.0.1", + "mio 1.0.2", "pin-project-lite", "signal-hook-registry", "socket2", @@ -5968,7 +5994,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -6032,27 +6058,29 @@ dependencies = [ "bytes", "futures-core", "futures-sink", + "futures-util", + "hashbrown 0.14.5", "pin-project-lite", "tokio", ] [[package]] name = "toml" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.17", + "toml_edit 0.22.20", ] [[package]] name = "toml_datetime" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] @@ -6063,22 +6091,22 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.4.0", "toml_datetime", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.22.17" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.4.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.8", + "winnow 0.6.18", ] [[package]] @@ -6095,7 +6123,7 @@ dependencies = [ "h2", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.30", "hyper-timeout", "percent-encoding", "pin-project", @@ -6134,10 +6162,10 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bytes", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "pin-project-lite", "tokio", @@ -6148,15 +6176,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -6178,7 +6206,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -6260,9 +6288,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "trybuild" -version = "1.0.97" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1e5645f2ee8025c2f1d75e1138f2dd034d74e6ba54620f3c569ba2a2a1ea06" +checksum = "207aa50d36c4be8d8c6ea829478be44a372c6a77669937bb39c698e52f1491e8" dependencies = [ "glob", "serde", @@ -6298,9 +6326,9 @@ dependencies = [ [[package]] name = "typeid" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "059d83cc991e7a42fc37bd50941885db0888e34209f8cfd9aab07ddec03bc9cf" +checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" [[package]] name = "typenum" @@ -6349,15 +6377,15 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" [[package]] name = "unique_port" @@ -6392,9 +6420,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.9.7" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d11a831e3c0b56e438a28308e7c810799e3c118417f342d30ecec080105395cd" +checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" dependencies = [ "base64 0.22.1", "log", @@ -6428,9 +6456,9 @@ checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" @@ -6455,9 +6483,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vergen" -version = "8.3.1" +version = "8.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525" +checksum = "2990d9ea5967266ea0ccf413a4aa5c42a93dbcfda9cb49a97de6931726b12566" dependencies = [ "anyhow", "cargo_metadata", @@ -6470,9 +6498,9 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "w3f-bls" @@ -6525,34 +6553,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6560,22 +6589,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasm-encoder" @@ -6588,9 +6617,9 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.215.0" +version = "0.216.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb56df3e06b8e6b77e37d2969a50ba51281029a9aeb3855e76b7f49b6418847" +checksum = "04c23aebea22c8a75833ae08ed31ccc020835b12a41999e58c31464271b94a88" dependencies = [ "leb128", ] @@ -6642,9 +6671,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07035cc9a9b41e62d3bb3a3815a66ab87c993c06fe1cf6b2a3f2a18499d937db" dependencies = [ "ahash 0.8.11", - "bitflags 2.5.0", + "bitflags 2.6.0", "hashbrown 0.14.5", - "indexmap 2.2.6", + "indexmap 2.4.0", "semver", "serde", ] @@ -6675,7 +6704,7 @@ dependencies = [ "fxprof-processed-profile", "gimli", "hashbrown 0.14.5", - "indexmap 2.2.6", + "indexmap 2.4.0", "ittapi", "libc", "libm", @@ -6753,7 +6782,7 @@ dependencies = [ "anyhow", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "wasmtime-component-util", "wasmtime-wit-bindgen", "wit-parser", @@ -6799,7 +6828,7 @@ dependencies = [ "cpp_demangle", "cranelift-entity", "gimli", - "indexmap 2.2.6", + "indexmap 2.4.0", "log", "object 0.36.3", "postcard", @@ -6880,7 +6909,7 @@ checksum = "de5a9bc4f44ceeb168e9e8e3be4e0b4beb9095b468479663a9e24c667e36826f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -6908,37 +6937,37 @@ checksum = "70dc077306b38288262e5ba01d4b21532a6987416cdc0aedf04bb06c22a68fdc" dependencies = [ "anyhow", "heck 0.4.1", - "indexmap 2.2.6", + "indexmap 2.4.0", "wit-parser", ] [[package]] name = "wast" -version = "215.0.0" +version = "216.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff1d00d893593249e60720be04a7c1f42f1c4dc3806a2869f4e66ab61eb54cb" +checksum = "f7eb1f2eecd913fdde0dc6c3439d0f24530a98ac6db6cb3d14d92a5328554a08" dependencies = [ "bumpalo", "leb128", "memchr", "unicode-width", - "wasm-encoder 0.215.0", + "wasm-encoder 0.216.0", ] [[package]] name = "wat" -version = "1.215.0" +version = "1.216.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670bf4d9c8cf76ae242d70ded47c546525b6dafaa6871f9bcb065344bf2b4e3d" +checksum = "ac0409090fb5154f95fb5ba3235675fd9e579e731524d63b6a2f653e1280c82a" dependencies = [ "wast", ] [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -6956,9 +6985,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.1" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" dependencies = [ "rustls-pki-types", ] @@ -6981,11 +7010,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -7017,7 +7046,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -7035,7 +7064,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -7055,18 +7093,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -7077,9 +7115,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -7089,9 +7127,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -7101,15 +7139,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -7119,9 +7157,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -7131,9 +7169,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -7143,9 +7181,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -7155,9 +7193,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -7170,9 +7208,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.8" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] @@ -7185,7 +7223,7 @@ checksum = "3e79b9e3c0b6bb589dec46317e645851e0db2734c44e2be5e251b03ff4a51269" dependencies = [ "anyhow", "id-arena", - "indexmap 2.2.6", + "indexmap 2.4.0", "log", "semver", "serde", @@ -7227,22 +7265,23 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -7262,21 +7301,21 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "zip" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2568cd0f20e86cd9a7349fe05178f7bd22f22724678448ae5a9bac266df2689" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" dependencies = [ "arbitrary", "crc32fast", "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.2.6", + "indexmap 2.4.0", "memchr", "thiserror", "zopfli", @@ -7316,9 +7355,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index fa6ed17714e..ada3e6a396b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,7 @@ futures = { version = "0.3.30", default-features = false } tokio = "1.39.2" tokio-stream = "0.1.15" tokio-tungstenite = "0.21.0" +tokio-util = "0.7.11" tungstenite = "0.21.0" crossbeam-queue = "0.3.11" parking_lot = { version = "0.12.3" } diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 116342c22f8..1be905073f4 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -30,9 +30,6 @@ dev-telemetry = ["telemetry", "iroha_telemetry/dev-telemetry", "iroha_logger/tok # Support schema generation from the `schema` endpoint in the local binary. # Useful for debugging issues with decoding in SDKs. schema-endpoint = ["iroha_torii/schema"] -# Support internal testing infrastructure for integration tests. -# Disable in production. -test-network = ["thread-local-panic-hook"] [badges] is-it-maintained-issue-resolution = { repository = "https://github.com/hyperledger/iroha" } @@ -58,13 +55,12 @@ error-stack = { workspace = true, features = ["eyre"] } thiserror = { workspace = true } tracing = { workspace = true } tokio = { workspace = true, features = ["macros", "signal"] } +tokio-util = { workspace = true, features = ["rt"] } once_cell = { workspace = true } owo-colors = { workspace = true, features = ["supports-colors"] } supports-color = { workspace = true } toml = { workspace = true } -thread-local-panic-hook = { version = "0.1.0", optional = true } - [dev-dependencies] serial_test = "3.1.1" tempfile = { workspace = true } @@ -82,6 +78,5 @@ vergen = { workspace = true, features = ["cargo"] } denylist = [ "schema-endpoint", "telemetry", - "test-network", ] skip_optional_dependencies = true diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 23c43a1ccc9..46888b39369 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -7,6 +7,7 @@ #[cfg(debug_assertions)] use core::sync::atomic::{AtomicBool, Ordering}; use std::{ + future::Future, path::{Path, PathBuf}, sync::Arc, }; @@ -22,20 +23,18 @@ use iroha_core::metrics::MetricsReporter; use iroha_core::{ block_sync::{BlockSynchronizer, BlockSynchronizerHandle}, gossiper::{TransactionGossiper, TransactionGossiperHandle}, - handler::ThreadHandler, kiso::KisoHandle, kura::Kura, query::store::LiveQueryStore, queue::Queue, smartcontracts::isi::Registrable as _, - snapshot::{ - try_read_snapshot, SnapshotMaker, SnapshotMakerHandle, TryReadError as TryReadSnapshotError, - }, + snapshot::{try_read_snapshot, SnapshotMaker, TryReadError as TryReadSnapshotError}, state::{State, StateReadOnly, World}, sumeragi::{GenesisWithPubKey, SumeragiHandle, SumeragiMetrics, SumeragiStartArgs}, IrohaNetwork, }; use iroha_data_model::{block::SignedBlock, prelude::*}; +use iroha_futures::supervisor::{ShutdownSignal, Supervisor}; use iroha_genesis::GenesisBlock; use iroha_logger::{actor::LoggerHandle, InitConfig as LoggerInitConfig}; use iroha_primitives::addr::SocketAddr; @@ -43,52 +42,30 @@ use iroha_torii::Torii; use iroha_version::scale::DecodeVersioned; use thiserror::Error; use tokio::{ - signal, - sync::{broadcast, mpsc, Notify}, + sync::{broadcast, mpsc}, task, }; // FIXME: move from CLI pub mod samples; +const EVENTS_BUFFER_CAPACITY: usize = 10_000; + /// Iroha is an /// [Orchestrator](https://en.wikipedia.org/wiki/Orchestration_%28computing%29) /// of the system. It configures, coordinates and manages transactions /// and queries processing, work of consensus and storage. pub struct Iroha { - /// Actor responsible for the configuration - _kiso: KisoHandle, - /// Queue of transactions - _queue: Arc, - /// Sumeragi consensus - _sumeragi: SumeragiHandle, /// Kura — block storage kura: Arc, - /// Snapshot service. Might be not started depending on the config. - _snapshot_maker: Option, /// State of blockchain state: Arc, - /// Shutdown signal - notify_shutdown: Arc, - /// Thread handlers - thread_handlers: Vec, /// A boolean value indicating whether or not the peers will receive data from the network. /// Used in sumeragi testing. #[cfg(debug_assertions)] pub freeze_status: FreezeStatus, } -impl Drop for Iroha { - fn drop(&mut self) { - iroha_logger::trace!("Iroha instance dropped"); - self.notify_shutdown.notify_waiters(); - let _thread_handles = core::mem::take(&mut self.thread_handlers); - iroha_logger::debug!( - "Thread handles dropped. Dependent processes going for a graceful shutdown" - ) - } -} - /// Error(s) that might occur while starting [`Iroha`] #[derive(thiserror::Error, Debug, Copy, Clone)] #[allow(missing_docs)] @@ -133,18 +110,13 @@ impl FreezeStatus { struct NetworkRelay { sumeragi: SumeragiHandle, block_sync: BlockSynchronizerHandle, - gossiper: TransactionGossiperHandle, + tx_gossiper: TransactionGossiperHandle, network: IrohaNetwork, - shutdown_notify: Arc, #[cfg(debug_assertions)] freeze_status: FreezeStatus, } impl NetworkRelay { - fn start(self) { - tokio::task::spawn(self.run()); - } - async fn run(mut self) { let (sender, mut receiver) = mpsc::channel(1); self.network.subscribe_to_peers_messages(sender); @@ -152,13 +124,12 @@ impl NetworkRelay { #[allow(clippy::redundant_pub_crate)] loop { tokio::select! { - // Receive message from network + // Receive a message from the network Some(msg) = receiver.recv() => self.handle_message(msg).await, - () = self.shutdown_notify.notified() => { - iroha_logger::info!("NetworkRelay is being shut down."); + else => { + iroha_logger::debug!("Exiting the network relay"); break; - } - else => break, + }, } tokio::task::yield_now().await; } @@ -180,101 +151,56 @@ impl NetworkRelay { self.sumeragi.incoming_control_flow_message(*data); } BlockSync(data) => self.block_sync.message(*data).await, - TransactionGossiper(data) => self.gossiper.gossip(*data).await, + TransactionGossiper(data) => self.tx_gossiper.gossip(*data).await, Health => {} } } } impl Iroha { - fn prepare_panic_hook(notify_shutdown: Arc) { - #[cfg(not(feature = "test-network"))] - use std::panic::set_hook; - - // This is a hot-fix for tests - // - // # Problem - // - // When running tests in parallel `std::panic::set_hook()` will be set - // the same for all threads. That means, that panic in one test can - // cause another test shutdown, which we don't want. - // - // # Downside - // - // A downside of this approach is that this panic hook will not work for - // threads created by Iroha itself (e.g. Sumeragi thread). - // - // # TODO - // - // Remove this when all Rust integrations tests will be converted to a - // separate Python tests. - #[cfg(feature = "test-network")] - use thread_local_panic_hook::set_hook; - - set_hook(Box::new(move |info| { - // What clippy suggests is much less readable in this case - #[allow(clippy::option_if_let_else)] - let panic_message = if let Some(message) = info.payload().downcast_ref::<&str>() { - message - } else if let Some(message) = info.payload().downcast_ref::() { - message - } else { - "unspecified" - }; - - let location = info.location().map_or_else( - || "unspecified".to_owned(), - |location| format!("{}:{}", location.file(), location.line()), - ); - - iroha_logger::error!(panic_message, location, "A panic occurred, shutting down"); - - // NOTE: shutdown all currently listening waiters - notify_shutdown.notify_waiters(); - })); - } - - /// Creates new Iroha instance and starts all internal services. + /// Starts Iroha with all its subsystems. /// - /// Returns iroha itself and future to await for iroha completion. + /// Returns iroha itself and a future of system shutdown. /// /// # Errors /// - Reading telemetry configs /// - Telemetry setup /// - Initialization of [`Sumeragi`] and [`Kura`] - /// - /// # Side Effects - /// - Sets global panic hook #[allow(clippy::too_many_lines)] - #[iroha_logger::log(name = "init", skip_all)] // This is actually easier to understand as a linear sequence of init statements. - pub async fn start_network( + #[iroha_logger::log(name = "start", skip_all)] // This is actually easier to understand as a linear sequence of init statements. + pub async fn start( config: Config, genesis: Option, logger: LoggerHandle, - ) -> Result<(impl core::future::Future, Self), StartError> { - let network = IrohaNetwork::start(config.common.key_pair.clone(), config.network.clone()) - .await - .change_context(StartError::StartP2p)?; + shutdown_signal: ShutdownSignal, + ) -> Result< + ( + Self, + impl Future>, + ), + StartError, + > { + let mut supervisor = Supervisor::new(); + + let (kura, block_count) = Kura::new(&config.kura).change_context(StartError::InitKura)?; + let child = Kura::start(kura.clone(), supervisor.shutdown_signal()); + supervisor.monitor(child); - let (events_sender, _) = broadcast::channel(10000); let world = World::with( [genesis_domain(config.genesis.public_key.clone())], [genesis_account(config.genesis.public_key.clone())], [], ); - let notify_shutdown = Arc::new(Notify::new()); - - let (kura, block_count) = Kura::new(&config.kura).change_context(StartError::InitKura)?; - let kura_thread_handler = Kura::start(Arc::clone(&kura)); - let live_query_store_handle = - LiveQueryStore::from_config(config.live_query_store, Arc::clone(¬ify_shutdown)) + let (live_query_store, child) = + LiveQueryStore::from_config(config.live_query_store, supervisor.shutdown_signal()) .start(); + supervisor.monitor(child); let state = match try_read_snapshot( config.snapshot.store_dir.resolve_relative_path(), &kura, - live_query_store_handle.clone(), + || live_query_store.clone(), block_count, ) { Ok(state) => { @@ -296,15 +222,22 @@ impl Iroha { State::new( world, Arc::clone(&kura), - live_query_store_handle.clone(), + live_query_store.clone(), ) }); let state = Arc::new(state); + let (events_sender, _) = broadcast::channel(EVENTS_BUFFER_CAPACITY); let queue = Arc::new(Queue::from_config(config.queue, events_sender.clone())); + let (network, child) = + IrohaNetwork::start(config.common.key_pair.clone(), config.network.clone()) + .await + .change_context(StartError::StartP2p)?; + supervisor.monitor(child); + #[cfg(feature = "telemetry")] - Self::start_telemetry(&logger, &config).await?; + start_telemetry(&logger, &config, &mut supervisor).await?; #[cfg(feature = "telemetry")] let metrics_reporter = MetricsReporter::new( @@ -314,13 +247,13 @@ impl Iroha { queue.clone(), ); - let start_args = SumeragiStartArgs { + let (sumeragi, child) = SumeragiStartArgs { sumeragi_config: config.sumeragi.clone(), common_config: config.common.clone(), events_sender: events_sender.clone(), - state: Arc::clone(&state), - queue: Arc::clone(&queue), - kura: Arc::clone(&kura), + state: state.clone(), + queue: queue.clone(), + kura: kura.clone(), network: network.clone(), genesis_network: GenesisWithPubKey { genesis, @@ -331,200 +264,88 @@ impl Iroha { dropped_messages: metrics_reporter.metrics().dropped_messages.clone(), view_changes: metrics_reporter.metrics().view_changes.clone(), }, - }; - // Starting Sumeragi requires no async context enabled - let sumeragi = task::spawn_blocking(move || SumeragiHandle::start(start_args)) - .await - .expect("Failed to join task with Sumeragi start"); + } + .start(supervisor.shutdown_signal()); + supervisor.monitor(child); - let block_sync = BlockSynchronizer::from_config( + let (block_sync, child) = BlockSynchronizer::from_config( &config.block_sync, sumeragi.clone(), - Arc::clone(&kura), + kura.clone(), config.common.peer.clone(), network.clone(), Arc::clone(&state), ) - .start(); + .start(supervisor.shutdown_signal()); + supervisor.monitor(child); - let gossiper = TransactionGossiper::from_config( + let (tx_gossiper, child) = TransactionGossiper::from_config( config.common.chain.clone(), config.transaction_gossiper, network.clone(), Arc::clone(&queue), Arc::clone(&state), ) - .start(); + .start(supervisor.shutdown_signal()); + supervisor.monitor(child); #[cfg(debug_assertions)] let freeze_status = FreezeStatus::new(config.common.peer.clone()); + supervisor.monitor(task::spawn( + NetworkRelay { + sumeragi, + block_sync, + tx_gossiper, + network, + #[cfg(debug_assertions)] + freeze_status: freeze_status.clone(), + } + .run(), + )); - NetworkRelay { - sumeragi: sumeragi.clone(), - block_sync, - gossiper, - network: network.clone(), - shutdown_notify: Arc::clone(¬ify_shutdown), - #[cfg(debug_assertions)] - freeze_status: freeze_status.clone(), + if let Some(snapshot_maker) = + SnapshotMaker::from_config(&config.snapshot, Arc::clone(&state)) + { + supervisor.monitor(snapshot_maker.start(supervisor.shutdown_signal())); } - .start(); - let snapshot_maker = SnapshotMaker::from_config(&config.snapshot, Arc::clone(&state)) - .map(SnapshotMaker::start); + let (kiso, child) = KisoHandle::start(config.clone()); + supervisor.monitor(child); - let kiso = KisoHandle::new(config.clone()); - - let torii = Torii::new( + let torii_run = Torii::new( config.common.chain.clone(), kiso.clone(), config.torii, - Arc::clone(&queue), + queue, events_sender, - Arc::clone(¬ify_shutdown), - live_query_store_handle, - Arc::clone(&kura), - Arc::clone(&state), + live_query_store, + kura.clone(), + state.clone(), #[cfg(feature = "telemetry")] metrics_reporter, - ); - - let run_torii = torii - .start() - .await - .map_err(|report| report.change_context(StartError::StartTorii))?; - - tokio::spawn(run_torii); - - Self::spawn_config_updates_broadcasting(kiso.clone(), logger.clone()); - - Self::start_listening_signal(Arc::clone(¬ify_shutdown))?; - - Self::prepare_panic_hook(Arc::clone(¬ify_shutdown)); - - // Future to wait for iroha completion - let wait = { - let notify_shutdown = Arc::clone(¬ify_shutdown); - async move { notify_shutdown.notified().await } - }; - - let irohad = Self { - _kiso: kiso, - _queue: queue, - _sumeragi: sumeragi, - kura, - _snapshot_maker: snapshot_maker, - state, - notify_shutdown, - thread_handlers: vec![kura_thread_handler], - #[cfg(debug_assertions)] - freeze_status, - }; - - Ok((wait, irohad)) - } - - #[cfg(feature = "telemetry")] - async fn start_telemetry(logger: &LoggerHandle, config: &Config) -> Result<(), StartError> { - const MSG_SUBSCRIBE: &str = "unable to subscribe to the channel"; - const MSG_START_TASK: &str = "unable to start the task"; - - #[cfg(feature = "dev-telemetry")] - { - if let Some(out_file) = &config.dev_telemetry.out_file { - let receiver = logger - .subscribe_on_telemetry(iroha_logger::telemetry::Channel::Future) - .await - .change_context(StartError::StartDevTelemetry) - .attach_printable(MSG_SUBSCRIBE)?; - let _handle = iroha_telemetry::dev::start_file_output( - out_file.resolve_relative_path(), - receiver, - ) - .await - .into_report() - .map_err(|report| report.change_context(StartError::StartDevTelemetry)) - .attach_printable(MSG_START_TASK)?; - } - } - - if let Some(config) = &config.telemetry { - let receiver = logger - .subscribe_on_telemetry(iroha_logger::telemetry::Channel::Regular) - .await - .change_context(StartError::StartTelemetry) - .attach_printable(MSG_SUBSCRIBE)?; - let _handle = iroha_telemetry::ws::start(config.clone(), receiver) - .await - .into_report() - .map_err(|report| report.change_context(StartError::StartTelemetry)) - .attach_printable(MSG_START_TASK)?; - iroha_logger::info!("Telemetry started"); - Ok(()) - } else { - iroha_logger::info!("Telemetry not started due to absent configuration"); - Ok(()) - } - } + ) + .start(&supervisor.shutdown_signal()) + .await + .map_err(|report| report.change_context(StartError::StartTorii))?; + supervisor.monitor(tokio::spawn(torii_run)); - fn start_listening_signal( - notify_shutdown: Arc, - ) -> Result, StartError> { - let (mut sigint, mut sigterm) = signal::unix::signal(signal::unix::SignalKind::interrupt()) - .and_then(|sigint| { - let sigterm = signal::unix::signal(signal::unix::SignalKind::terminate())?; + supervisor.monitor(tokio::task::spawn(config_updates_relay(kiso, logger))); - Ok((sigint, sigterm)) - }) + supervisor + .setup_shutdown_on_os_signals() .change_context(StartError::ListenOsSignal)?; - // NOTE: Triggered by tokio::select - #[allow(clippy::redundant_pub_crate)] - let handle = task::spawn(async move { - tokio::select! { - _ = sigint.recv() => { - iroha_logger::info!("SIGINT received, shutting down..."); - }, - _ = sigterm.recv() => { - iroha_logger::info!("SIGTERM received, shutting down..."); - }, - } - - // NOTE: shutdown all currently listening waiters - notify_shutdown.notify_waiters(); - }); - - Ok(handle) - } + supervisor.shutdown_on_external_signal(shutdown_signal); - /// Spawns a task which subscribes on updates from configuration actor - /// and broadcasts them further to interested actors. This way, neither config actor nor other ones know - /// about each other, achieving loose coupling of code and system. - fn spawn_config_updates_broadcasting( - kiso: KisoHandle, - logger: LoggerHandle, - ) -> task::JoinHandle<()> { - tokio::spawn(async move { - let mut log_level_update = kiso - .subscribe_on_log_level() - .await - // FIXME: don't like neither the message nor inability to throw Result to the outside - .expect("Cannot proceed without working subscriptions"); - - // See https://github.com/tokio-rs/tokio/issues/5616 and - // https://github.com/rust-lang/rust-clippy/issues/10636 - #[allow(clippy::redundant_pub_crate)] - loop { - tokio::select! { - Ok(()) = log_level_update.changed() => { - let value = log_level_update.borrow_and_update().clone(); - if let Err(error) = logger.reload_level(value).await { - iroha_logger::error!("Failed to reload log level: {error}"); - }; - } - }; - } - }) + Ok(( + Self { + kura, + state, + #[cfg(debug_assertions)] + freeze_status, + }, + supervisor.start(), + )) } #[allow(missing_docs)] @@ -544,6 +365,82 @@ impl Iroha { } } +#[cfg(feature = "telemetry")] +async fn start_telemetry( + logger: &LoggerHandle, + config: &Config, + supervisor: &mut Supervisor, +) -> Result<(), StartError> { + const MSG_SUBSCRIBE: &str = "unable to subscribe to the channel"; + const MSG_START_TASK: &str = "unable to start the task"; + + #[cfg(feature = "dev-telemetry")] + { + if let Some(out_file) = &config.dev_telemetry.out_file { + let receiver = logger + .subscribe_on_telemetry(iroha_logger::telemetry::Channel::Future) + .await + .change_context(StartError::StartDevTelemetry) + .attach_printable(MSG_SUBSCRIBE)?; + let handle = + iroha_telemetry::dev::start_file_output(out_file.resolve_relative_path(), receiver) + .await + .into_report() + .map_err(|report| report.change_context(StartError::StartDevTelemetry)) + .attach_printable(MSG_START_TASK)?; + supervisor.monitor(handle); + } + } + + if let Some(config) = &config.telemetry { + let receiver = logger + .subscribe_on_telemetry(iroha_logger::telemetry::Channel::Regular) + .await + .change_context(StartError::StartTelemetry) + .attach_printable(MSG_SUBSCRIBE)?; + let handle = iroha_telemetry::ws::start(config.clone(), receiver) + .await + .into_report() + .map_err(|report| report.change_context(StartError::StartTelemetry)) + .attach_printable(MSG_START_TASK)?; + supervisor.monitor(handle); + iroha_logger::info!("Telemetry started"); + Ok(()) + } else { + iroha_logger::info!("Telemetry not started due to absent configuration"); + Ok(()) + } +} + +/// Spawns a task which subscribes on updates from the configuration actor +/// and broadcasts them further to interested actors. This way, neither the config actor nor other ones know +/// about each other, achieving loose coupling of code and system. +async fn config_updates_relay(kiso: KisoHandle, logger: LoggerHandle) { + let mut log_level_update = kiso + .subscribe_on_log_level() + .await + // FIXME: don't like neither the message nor inability to throw Result to the outside + .expect("Cannot proceed without working subscriptions"); + + // See https://github.com/tokio-rs/tokio/issues/5616 and + // https://github.com/rust-lang/rust-clippy/issues/10636 + #[allow(clippy::redundant_pub_crate)] + loop { + tokio::select! { + Ok(()) = log_level_update.changed() => { + let value = log_level_update.borrow_and_update().clone(); + if let Err(error) = logger.reload_level(value).await { + iroha_logger::error!("Failed to reload log level: {error}"); + }; + } + else => { + iroha_logger::debug!("Exiting config updates relay"); + break; + } + }; + } +} + fn genesis_account(public_key: PublicKey) -> Account { let genesis_account_id = AccountId::new(iroha_genesis::GENESIS_DOMAIN_ID.clone(), public_key); Account::new(genesis_account_id.clone()).build(&genesis_account_id) @@ -774,31 +671,6 @@ mod tests { use super::*; - #[cfg(not(feature = "test-network"))] - mod no_test_network { - use std::{iter::repeat, panic, thread}; - - use futures::future::join_all; - use serial_test::serial; - - use super::*; - - #[tokio::test] - #[serial] - async fn iroha_should_notify_on_panic() { - let notify = Arc::new(Notify::new()); - let hook = panic::take_hook(); - crate::Iroha::prepare_panic_hook(Arc::clone(¬ify)); - let waiters: Vec<_> = repeat(()).take(10).map(|_| Arc::clone(¬ify)).collect(); - let handles: Vec<_> = waiters.iter().map(|waiter| waiter.notified()).collect(); - thread::spawn(move || { - panic!("Test panic"); - }); - join_all(handles).await; - panic::set_hook(hook); - } - } - mod config_integration { use assertables::{assert_contains, assert_contains_as_result}; use iroha_crypto::{ExposedPrivateKey, KeyPair}; diff --git a/cli/src/main.rs b/cli/src/main.rs index c34acb2f520..1f1bb177c5f 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -3,6 +3,7 @@ use std::env; use clap::Parser; use error_stack::{IntoReportCompat, ResultExt}; +use iroha_futures::supervisor::ShutdownSignal; use irohad::{Args, Iroha}; #[derive(thiserror::Error, Debug)] @@ -13,8 +14,10 @@ enum MainError { Config, #[error("Could not initialize logger")] Logger, - #[error("Could not start Iroha")] + #[error("Failed to start Iroha")] IrohaStart, + #[error("Error occured while running Iroha")] + IrohaRun, } #[tokio::main] @@ -54,13 +57,19 @@ async fn main() -> error_stack::Result<(), MainError> { iroha_logger::debug!("Submitting genesis."); } - Iroha::start_network(config, genesis, logger) - .await - .change_context(MainError::IrohaStart)? - .0 - .await; + let shutdown_on_panic = ShutdownSignal::new(); + let default_hook = std::panic::take_hook(); + let signal_clone = shutdown_on_panic.clone(); + std::panic::set_hook(Box::new(move |info| { + iroha_logger::error!("Panic occurred, shutting down Iroha gracefully..."); + signal_clone.send(); + default_hook(info); + })); - Ok(()) + let (_iroha, supervisor_fut) = Iroha::start(config, genesis, logger, shutdown_on_panic) + .await + .change_context(MainError::IrohaStart)?; + supervisor_fut.await.change_context(MainError::IrohaRun) } /// Configures globals of [`error_stack::Report`] diff --git a/client/tests/integration/extra_functional/restart_peer.rs b/client/tests/integration/extra_functional/restart_peer.rs index c183ccab2f1..b260150b588 100644 --- a/client/tests/integration/extra_functional/restart_peer.rs +++ b/client/tests/integration/extra_functional/restart_peer.rs @@ -61,7 +61,7 @@ fn restarted_peer_should_have_the_same_asset_amount() -> Result<()> { .collect(); let removed_peer_idx = rand::thread_rng().gen_range(0..all_peers.len()); let mut removed_peer = all_peers.swap_remove(removed_peer_idx); - removed_peer.stop(); + removed_peer.terminate(); removed_peer }; // All peers have been stopped here diff --git a/core/Cargo.toml b/core/Cargo.toml index 504a2ade04a..3a81883bc1f 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -110,6 +110,5 @@ path = "benches/blocks/validate_blocks_oneshot.rs" denylist = [ "schema-endpoint", "telemetry", - "test-network" ] skip_optional_dependencies = true diff --git a/core/benches/blocks/common.rs b/core/benches/blocks/common.rs index 9b4edabbc83..e88db6e9718 100644 --- a/core/benches/blocks/common.rs +++ b/core/benches/blocks/common.rs @@ -185,7 +185,7 @@ pub fn build_state(rt: &tokio::runtime::Handle, account_id: &AccountId) -> State let kura = iroha_core::kura::Kura::blank_kura_for_testing(); let query_handle = { let _guard = rt.enter(); - LiveQueryStore::test().start() + LiveQueryStore::start_test() }; let domain = Domain::new(account_id.domain().clone()).build(account_id); let state = State::new( diff --git a/core/benches/kura.rs b/core/benches/kura.rs index b01a5dcfd56..f602695d735 100644 --- a/core/benches/kura.rs +++ b/core/benches/kura.rs @@ -15,6 +15,7 @@ use iroha_core::{ }; use iroha_crypto::KeyPair; use iroha_data_model::prelude::*; +use iroha_futures::supervisor::ShutdownSignal; use test_samples::gen_account_in; use tokio::{fs, runtime::Runtime}; @@ -27,8 +28,8 @@ async fn measure_block_size_for_n_executors(n_executors: u32) { }; let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let (kura, _) = iroha_core::kura::Kura::new(&cfg).unwrap(); - let _thread_handle = iroha_core::kura::Kura::start(kura.clone()); - let query_handle = LiveQueryStore::test().start(); + let _thread_handle = iroha_core::kura::Kura::start(kura.clone(), ShutdownSignal::new()); + let query_handle = LiveQueryStore::start_test(); let state = State::new(World::new(), kura, query_handle); let (alice_id, alice_keypair) = gen_account_in("test"); diff --git a/core/benches/validation.rs b/core/benches/validation.rs index 40c999b8579..90aaeb63527 100644 --- a/core/benches/validation.rs +++ b/core/benches/validation.rs @@ -35,7 +35,7 @@ fn build_test_transaction(chain_id: ChainId) -> TransactionBuilder { fn build_test_and_transient_state() -> State { let kura = iroha_core::kura::Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new( { @@ -147,7 +147,7 @@ fn validate_transaction(criterion: &mut Criterion) { fn sign_blocks(criterion: &mut Criterion) { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let kura = iroha_core::kura::Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(World::new(), kura, query_handle); let (max_clock_drift, tx_limits) = { let state_view = state.world.view(); diff --git a/core/src/block.rs b/core/src/block.rs index 57cb6721f49..7d0c52be86d 100644 --- a/core/src/block.rs +++ b/core/src/block.rs @@ -1148,7 +1148,7 @@ mod tests { let domain = Domain::new(domain_id).build(&alice_id); let world = World::with([domain], [account], []); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world, kura, query_handle); let (max_clock_drift, tx_limits) = { let state_view = state.world.view(); @@ -1206,7 +1206,7 @@ mod tests { let domain = Domain::new(domain_id).build(&alice_id); let world = World::with([domain], [account], []); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world, kura, query_handle); let (max_clock_drift, tx_limits) = { let state_view = state.world.view(); @@ -1284,7 +1284,7 @@ mod tests { let domain = Domain::new(domain_id).build(&alice_id); let world = World::with([domain], [account], []); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world, kura, query_handle); let (max_clock_drift, tx_limits) = { let state_view = state.world.view(); @@ -1364,7 +1364,7 @@ mod tests { Account::new(genesis_wrong_account_id.clone()).build(&genesis_wrong_account_id); let world = World::with([genesis_domain], [genesis_wrong_account], []); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world, kura, query_handle); let mut state_block = state.block(); diff --git a/core/src/block_sync.rs b/core/src/block_sync.rs index c0c0d31e563..da415e3096b 100644 --- a/core/src/block_sync.rs +++ b/core/src/block_sync.rs @@ -13,6 +13,7 @@ use iroha_data_model::{ block::{BlockHeader, SignedBlock}, prelude::*, }; +use iroha_futures::supervisor::{Child, OnShutdown, ShutdownSignal}; use iroha_logger::prelude::*; use iroha_macro::*; use iroha_p2p::Post; @@ -59,25 +60,34 @@ pub struct BlockSynchronizer { impl BlockSynchronizer { /// Start [`Self`] actor. - pub fn start(self) -> BlockSynchronizerHandle { + pub fn start(self, shutdown_signal: ShutdownSignal) -> (BlockSynchronizerHandle, Child) { let (message_sender, message_receiver) = mpsc::channel(1); - tokio::task::spawn(self.run(message_receiver)); - BlockSynchronizerHandle { message_sender } + ( + BlockSynchronizerHandle { message_sender }, + Child::new( + tokio::spawn(self.run(message_receiver, shutdown_signal)), + OnShutdown::Abort, + ), + ) } /// [`Self`] task. - async fn run(mut self, mut message_receiver: mpsc::Receiver) { + async fn run( + mut self, + mut message_receiver: mpsc::Receiver, + shutdown_signal: ShutdownSignal, + ) { let mut gossip_period = tokio::time::interval(self.gossip_period); loop { tokio::select! { _ = gossip_period.tick() => self.request_block().await, - msg = message_receiver.recv() => { - let Some(msg) = msg else { - info!("All handler to BlockSynchronizer are dropped. Shutting down..."); - break; - }; + Some(msg) = message_receiver.recv() => { msg.handle_message(&mut self).await; } + () = shutdown_signal.receive() => { + debug!("Shutting down block sync"); + break; + }, } tokio::task::yield_now().await; } diff --git a/core/src/gossiper.rs b/core/src/gossiper.rs index 247d9b717d5..f883c56ba86 100644 --- a/core/src/gossiper.rs +++ b/core/src/gossiper.rs @@ -4,6 +4,7 @@ use std::{num::NonZeroU32, sync::Arc, time::Duration}; use iroha_config::parameters::actual::TransactionGossiper as Config; use iroha_data_model::{transaction::SignedTransaction, ChainId}; +use iroha_futures::supervisor::{Child, OnShutdown, ShutdownSignal}; use iroha_p2p::Broadcast; use parity_scale_codec::{Decode, Encode}; use tokio::sync::mpsc; @@ -46,10 +47,15 @@ pub struct TransactionGossiper { impl TransactionGossiper { /// Start [`Self`] actor. - pub fn start(self) -> TransactionGossiperHandle { + pub fn start(self, shutdown_signal: ShutdownSignal) -> (TransactionGossiperHandle, Child) { let (message_sender, message_receiver) = mpsc::channel(1); - tokio::task::spawn(self.run(message_receiver)); - TransactionGossiperHandle { message_sender } + ( + TransactionGossiperHandle { message_sender }, + Child::new( + tokio::task::spawn(self.run(message_receiver, shutdown_signal)), + OnShutdown::Abort, + ), + ) } /// Construct [`Self`] from configuration @@ -73,18 +79,22 @@ impl TransactionGossiper { } } - async fn run(self, mut message_receiver: mpsc::Receiver) { + async fn run( + self, + mut message_receiver: mpsc::Receiver, + shutdown_signal: ShutdownSignal, + ) { let mut gossip_period = tokio::time::interval(self.gossip_period); loop { tokio::select! { _ = gossip_period.tick() => self.gossip_transactions(), - transaction_gossip = message_receiver.recv() => { - let Some(transaction_gossip) = transaction_gossip else { - iroha_logger::info!("All handler to Gossiper are dropped. Shutting down..."); - break; - }; + Some(transaction_gossip) = message_receiver.recv() => { self.handle_transaction_gossip(transaction_gossip); } + () = shutdown_signal.receive() => { + iroha_logger::info!("Shutting down transactions gossiper"); + break; + }, } tokio::task::yield_now().await; } diff --git a/core/src/kiso.rs b/core/src/kiso.rs index 19982bc1949..50fd939e3d1 100644 --- a/core/src/kiso.rs +++ b/core/src/kiso.rs @@ -13,6 +13,7 @@ use iroha_config::{ logger::Directives, parameters::actual::Root as Config, }; +use iroha_futures::supervisor::{Child, OnShutdown}; use tokio::sync::{mpsc, oneshot, watch}; const DEFAULT_CHANNEL_SIZE: usize = 32; @@ -27,7 +28,7 @@ pub struct KisoHandle { impl KisoHandle { /// Spawn a new actor - pub fn new(state: Config) -> Self { + pub fn start(state: Config) -> (Self, Child) { let (actor_sender, actor_receiver) = mpsc::channel(DEFAULT_CHANNEL_SIZE); let (log_level_update, _) = watch::channel(state.logger.level.clone()); let mut actor = Actor { @@ -35,11 +36,15 @@ impl KisoHandle { state, log_level_update, }; - tokio::spawn(async move { actor.run().await }); - - Self { - actor: actor_sender, - } + ( + Self { + actor: actor_sender, + }, + Child::new( + tokio::spawn(async move { actor.run().await }), + OnShutdown::Abort, + ), + ) } /// Fetch the [`ConfigDTO`] from the actor's state. @@ -177,7 +182,7 @@ mod tests { let mut config = test_config(); config.logger.level = INIT_LOG_LEVEL.into(); - let kiso = KisoHandle::new(config); + let (kiso, _) = KisoHandle::start(config); let mut recv = kiso .subscribe_on_log_level() diff --git a/core/src/kura.rs b/core/src/kura.rs index 8366e7c69ad..5e28ebae57e 100644 --- a/core/src/kura.rs +++ b/core/src/kura.rs @@ -8,17 +8,19 @@ use std::{ num::NonZeroUsize, path::{Path, PathBuf}, sync::Arc, + time::Duration, }; use iroha_config::{kura::InitMode, parameters::actual::Kura as Config}; use iroha_crypto::{Hash, HashOf}; use iroha_data_model::block::{BlockHeader, SignedBlock}; +use iroha_futures::supervisor::{spawn_os_thread_as_future, Child, OnShutdown, ShutdownSignal}; use iroha_logger::prelude::*; use iroha_version::scale::{DecodeVersioned, EncodeVersioned}; use parity_scale_codec::DecodeAll; use parking_lot::Mutex; -use crate::{block::CommittedBlock, handler::ThreadHandler}; +use crate::block::CommittedBlock; const INDEX_FILE_NAME: &str = "blocks.index"; const DATA_FILE_NAME: &str = "blocks.data"; @@ -84,21 +86,16 @@ impl Kura { } /// Start the Kura thread - pub fn start(kura: Arc) -> ThreadHandler { - // Oneshot channel to allow forcefully stopping the thread. - let (shutdown_sender, shutdown_receiver) = tokio::sync::oneshot::channel(); - - let thread_handle = std::thread::spawn(move || { - Self::kura_receive_blocks_loop(&kura, shutdown_receiver); - }); - - let shutdown = move || { - if let Err(error) = shutdown_sender.send(()) { - iroha_logger::error!(?error); - } - }; - - ThreadHandler::new(Box::new(shutdown), thread_handle) + pub fn start(kura: Arc, shutdown_signal: ShutdownSignal) -> Child { + Child::new( + tokio::task::spawn(spawn_os_thread_as_future( + std::thread::Builder::new().name("kura".to_owned()), + move || { + Self::kura_receive_blocks_loop(&kura, &shutdown_signal); + }, + )), + OnShutdown::Wait(Duration::from_secs(5)), + ) } /// Initialize [`Kura`] after its construction to be able to work with it. @@ -187,10 +184,7 @@ impl Kura { } #[iroha_logger::log(skip_all)] - fn kura_receive_blocks_loop( - kura: &Kura, - mut shutdown_receiver: tokio::sync::oneshot::Receiver<()>, - ) { + fn kura_receive_blocks_loop(kura: &Kura, shutdown_signal: &ShutdownSignal) { let mut written_block_count = kura.init_block_count; let mut latest_written_block_hash = { let block_data = kura.block_data.lock(); @@ -202,7 +196,7 @@ impl Kura { let mut should_exit = false; loop { // If kura receive shutdown then close block channel and write remaining blocks to the storage - if shutdown_receiver.try_recv().is_ok() { + if shutdown_signal.is_sent() { info!("Kura block thread is being shut down. Writing remaining blocks to store."); should_exit = true; } @@ -1053,10 +1047,9 @@ mod tests { let domain = Domain::new(domain_id).build(&genesis_id); let account = Account::new(account_id.clone()).build(&genesis_id); - let live_query_store = LiveQueryStore::test(); let live_query_store = { let _rt_guard = rt.enter(); - live_query_store.start() + LiveQueryStore::start_test() }; let (kura, block_count) = Kura::new(&Config { @@ -1070,7 +1063,7 @@ mod tests { // Starting with empty block store assert_eq!(block_count.0, 0); - let _handle = Kura::start(kura.clone()); + let _handle = Kura::start(kura.clone(), ShutdownSignal::new()); let state = State::new( World::with([domain, genesis_domain], [account, genesis_account], []), diff --git a/core/src/lib.rs b/core/src/lib.rs index 94241f507c3..4cb040dcd9a 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -56,43 +56,6 @@ pub enum NetworkMessage { Health, } -pub mod handler { - //! General purpose thread handler. It is responsible for RAII for - //! threads started for Kura, Sumeragi and other core routines. - use std::thread::JoinHandle; - - /// Call shutdown function and join thread on drop - pub struct ThreadHandler { - /// Shutdown function: after calling it, the thread must terminate in finite amount of time - shutdown: Option>, - handle: Option>, - } - - impl ThreadHandler { - /// [`Self`] constructor - #[must_use] - #[inline] - pub fn new(shutdown: Box, handle: JoinHandle<()>) -> Self { - Self { - shutdown: Some(shutdown), - handle: Some(handle), - } - } - } - - impl Drop for ThreadHandler { - /// Join on drop to ensure that the thread is properly shut down. - fn drop(&mut self) { - (self.shutdown.take().expect("Always some after init"))(); - let handle = self.handle.take().expect("Always some after init"); - - if let Err(error) = handle.join() { - iroha_logger::error!(?error, "Fatal error: thread panicked"); - } - } - } -} - pub mod role { //! Module with extension for [`RoleId`] to be stored inside state. diff --git a/core/src/query/store.rs b/core/src/query/store.rs index ca07126ac7e..4b64fa28c9d 100644 --- a/core/src/query/store.rs +++ b/core/src/query/store.rs @@ -16,10 +16,11 @@ use iroha_data_model::{ QueryOutput, QueryOutputBatchBox, }, }; +use iroha_futures::supervisor::{Child, OnShutdown, ShutdownSignal}; use iroha_logger::{trace, warn}; use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; -use tokio::sync::Notify; +use tokio::task::JoinHandle; use super::cursor::{QueryBatchedErasedIterator, UnknownCursor}; @@ -74,7 +75,7 @@ pub struct LiveQueryStore { capacity_per_user: NonZeroUsize, // Queries older then this time will be automatically removed from the store idle_time: Duration, - notify_shutdown: Arc, + shutdown_signal: ShutdownSignal, } #[derive(Debug)] @@ -86,14 +87,14 @@ struct QueryInfo { impl LiveQueryStore { /// Construct [`LiveQueryStore`] from configuration. - pub fn from_config(cfg: Config, notify_shutdown: Arc) -> Self { + pub fn from_config(cfg: Config, shutdown_signal: ShutdownSignal) -> Self { Self { queries: DashMap::new(), queries_per_user: DashMap::new(), idle_time: cfg.idle_time, capacity: cfg.capacity, capacity_per_user: cfg.capacity_per_user, - notify_shutdown, + shutdown_signal, } } @@ -101,22 +102,30 @@ impl LiveQueryStore { /// Default configuration will be used. /// /// Not marked as `#[cfg(test)]` because it is used in benches as well. - pub fn test() -> Self { - let notify_shutdown = Arc::new(Notify::new()); - Self::from_config(Config::default(), notify_shutdown) + pub fn start_test() -> LiveQueryStoreHandle { + Self::from_config(Config::default(), ShutdownSignal::new()) + .start() + .0 } /// Start [`LiveQueryStore`]. Requires a [`tokio::runtime::Runtime`] being run /// as it will create new [`tokio::task`] and detach it. /// /// Returns a handle to interact with the service. - pub fn start(self) -> LiveQueryStoreHandle { + pub fn start(self) -> (LiveQueryStoreHandle, Child) { let store = Arc::new(self); - Arc::clone(&store).spawn_pruning_task(); - LiveQueryStoreHandle { store } + let handle = Arc::clone(&store).spawn_pruning_task(); + ( + LiveQueryStoreHandle { store }, + Child::new( + handle, + // should shutdown immediately anyway + OnShutdown::Wait(Duration::from_millis(5000)), + ), + ) } - fn spawn_pruning_task(self: Arc) { + fn spawn_pruning_task(self: Arc) -> JoinHandle<()> { let mut idle_interval = tokio::time::interval(self.idle_time); tokio::task::spawn(async move { loop { @@ -131,14 +140,14 @@ impl LiveQueryStore { } }); } - () = self.notify_shutdown.notified() => { + () = self.shutdown_signal.receive() => { iroha_logger::info!("LiveQueryStore is being shut down."); break; } else => break, } } - }); + }) } fn insert( @@ -321,9 +330,8 @@ mod tests { #[test] fn query_message_order_preserved() { - let query_store = LiveQueryStore::test(); let threaded_rt = tokio::runtime::Runtime::new().unwrap(); - let query_store_handle = threaded_rt.block_on(async { query_store.start() }); + let query_handle = threaded_rt.block_on(async { LiveQueryStore::start_test() }); for i in 0..10_000 { let pagination = Pagination::default(); @@ -347,7 +355,7 @@ mod tests { ) .unwrap(); - let (batch, _remaining_items, mut current_cursor) = query_store_handle + let (batch, _remaining_items, mut current_cursor) = query_handle .handle_iter_start(query_output, &ALICE_ID) .unwrap() .into_parts(); @@ -356,7 +364,7 @@ mod tests { counter += batch.len(); while let Some(cursor) = current_cursor { - let Ok(batched) = query_store_handle.handle_iter_continue(cursor) else { + let Ok(batched) = query_handle.handle_iter_continue(cursor) else { break; }; let (batch, _remaining_items, cursor) = batched.into_parts(); diff --git a/core/src/queue.rs b/core/src/queue.rs index 4b7b074c2da..a628e97c7c8 100644 --- a/core/src/queue.rs +++ b/core/src/queue.rs @@ -477,7 +477,7 @@ pub mod tests { #[test] async fn push_tx() { let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let (_time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -494,7 +494,7 @@ pub mod tests { let capacity = nonzero!(10_usize); let kura: Arc = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -528,7 +528,7 @@ pub mod tests { async fn get_available_txs() { let max_txs_in_block = nonzero!(2_usize); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -555,7 +555,7 @@ pub mod tests { #[test] async fn push_tx_already_in_blockchain() { let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world_with_test_domains(), kura, query_handle); let (_time_handle, time_source) = TimeSource::new_mock(Duration::default()); let tx = accepted_tx_by_someone(&time_source); @@ -579,7 +579,7 @@ pub mod tests { async fn get_tx_drop_if_in_blockchain() { let max_txs_in_block = nonzero!(2_usize); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world_with_test_domains(), kura, query_handle); let (_time_handle, time_source) = TimeSource::new_mock(Duration::default()); let tx = accepted_tx_by_someone(&time_source); @@ -604,7 +604,7 @@ pub mod tests { async fn get_available_txs_with_timeout() { let max_txs_in_block = nonzero!(6_usize); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -656,7 +656,7 @@ pub mod tests { let max_txs_in_block = nonzero!(2_usize); let (alice_id, alice_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let (max_clock_drift, tx_limits) = { let state_view = state.world.view(); @@ -715,7 +715,7 @@ pub mod tests { async fn concurrent_stress_test() { let max_txs_in_block = nonzero!(10_usize); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = Arc::new(State::new(world_with_test_domains(), kura, query_handle)); let (time_handle, time_source) = TimeSource::new_mock(Duration::default()); @@ -798,7 +798,7 @@ pub mod tests { let bob_account = Account::new(bob_id.clone()).build(&bob_id); World::with([domain], [alice_account, bob_account], []) }; - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world, kura, query_handle); let (_time_handle, time_source) = TimeSource::new_mock(Duration::default()); diff --git a/core/src/smartcontracts/isi/mod.rs b/core/src/smartcontracts/isi/mod.rs index c19ad67493d..343401697c3 100644 --- a/core/src/smartcontracts/isi/mod.rs +++ b/core/src/smartcontracts/isi/mod.rs @@ -244,7 +244,7 @@ mod tests { fn state_with_test_domains(kura: &Arc) -> Result { let world = World::with([], [], []); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world, kura.clone(), query_handle); let asset_definition_id = AssetDefinitionId::from_str("rose#wonderland")?; let mut state_block = state.block(); diff --git a/core/src/smartcontracts/isi/query.rs b/core/src/smartcontracts/isi/query.rs index 043d5cf8fba..26b3f4069ce 100644 --- a/core/src/smartcontracts/isi/query.rs +++ b/core/src/smartcontracts/isi/query.rs @@ -409,7 +409,7 @@ mod tests { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world_with_test_domains(), kura.clone(), query_handle); { let (max_clock_drift, tx_limits) = { @@ -471,7 +471,7 @@ mod tests { #[test] async fn asset_store() -> Result<()> { let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world_with_test_asset_with_metadata(), kura, query_handle); let asset_definition_id = AssetDefinitionId::from_str("rose#wonderland")?; @@ -485,7 +485,7 @@ mod tests { #[test] async fn account_metadata() -> Result<()> { let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world_with_test_account_with_metadata()?, kura, query_handle); let bytes = FindAccountMetadata::new(ALICE_ID.clone(), Name::from_str("Bytes")?) @@ -594,7 +594,7 @@ mod tests { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world_with_test_domains(), kura.clone(), query_handle); let (max_clock_drift, tx_limits) = { let state_view = state.world.view(); @@ -674,7 +674,7 @@ mod tests { let account = Account::new(ALICE_ID.clone()).build(&ALICE_ID); let asset_definition_id = AssetDefinitionId::from_str("rose#wonderland")?; let asset_definition = AssetDefinition::numeric(asset_definition_id).build(&ALICE_ID); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); State::new( World::with([domain], [account], [asset_definition]), kura, diff --git a/core/src/smartcontracts/wasm.rs b/core/src/smartcontracts/wasm.rs index 751ae3b19cf..fb1e58a78f6 100644 --- a/core/src/smartcontracts/wasm.rs +++ b/core/src/smartcontracts/wasm.rs @@ -1763,7 +1763,7 @@ mod tests { async fn execute_instruction_exported() -> Result<(), Error> { let (authority, _authority_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world_with_test_account(&authority), kura, query_handle); let isi_hex = { @@ -1805,7 +1805,7 @@ mod tests { async fn execute_query_exported() -> Result<(), Error> { let (authority, _authority_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world_with_test_account(&authority), kura, query_handle); let query_hex = encode_hex(QueryRequest::Singular( SingularQueryBox::FindExecutorDataModel(FindExecutorDataModel), @@ -1845,7 +1845,7 @@ mod tests { async fn instruction_limit_reached() -> Result<(), Error> { let (authority, _authority_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world_with_test_account(&authority), kura, query_handle); @@ -1900,7 +1900,7 @@ mod tests { async fn instructions_not_allowed() -> Result<(), Error> { let (authority, _authority_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world_with_test_account(&authority), kura, query_handle); let isi_hex = { @@ -1954,7 +1954,7 @@ mod tests { async fn queries_not_allowed() -> Result<(), Error> { let (authority, _authority_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world_with_test_account(&authority), kura, query_handle); let query_hex = encode_hex(QueryRequest::Singular( SingularQueryBox::FindExecutorDataModel(FindExecutorDataModel), @@ -2003,7 +2003,7 @@ mod tests { async fn trigger_related_func_is_not_linked_for_smart_contract() -> Result<(), Error> { let (authority, _authority_keypair) = gen_account_in("wonderland"); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world_with_test_account(&authority), kura, query_handle); let wat = format!( diff --git a/core/src/snapshot.rs b/core/src/snapshot.rs index e744f39f393..11d979cdb08 100644 --- a/core/src/snapshot.rs +++ b/core/src/snapshot.rs @@ -10,9 +10,9 @@ use std::{ use iroha_config::{parameters::actual::Snapshot as Config, snapshot::Mode}; use iroha_crypto::HashOf; use iroha_data_model::block::BlockHeader; +use iroha_futures::supervisor::{Child, OnShutdown, ShutdownSignal}; use iroha_logger::prelude::*; use serde::{de::DeserializeSeed, Serialize}; -use tokio::sync::mpsc; use crate::{ kura::{BlockCount, Kura}, @@ -28,13 +28,6 @@ const SNAPSHOT_TMP_FILE_NAME: &str = "snapshot.tmp"; // /// Errors produced by [`SnapshotMaker`] actor. // pub type Result = core::result::Result; -/// [`SnapshotMaker`] actor handle. -#[derive(Clone)] -pub struct SnapshotMakerHandle { - /// Not used to actually send messages but to signal that there is no more handles to [`SnapshotMaker`] - _message_sender: mpsc::Sender<()>, -} - /// Actor responsible for [`State`] snapshot reading and writing. pub struct SnapshotMaker { state: Arc, @@ -47,18 +40,15 @@ pub struct SnapshotMaker { } impl SnapshotMaker { - /// Start [`Self`] actor. - pub fn start(self) -> SnapshotMakerHandle { - let (message_sender, message_receiver) = mpsc::channel(1); - tokio::task::spawn(self.run(message_receiver)); - - SnapshotMakerHandle { - _message_sender: message_sender, - } + /// Start the actor. + pub fn start(self, shutdown_signal: ShutdownSignal) -> Child { + Child::new( + tokio::spawn(self.run(shutdown_signal)), + OnShutdown::Wait(Duration::from_secs(2)), + ) } - /// [`Self`] task. - async fn run(mut self, mut message_receiver: mpsc::Receiver<()>) { + async fn run(mut self, shutdown_signal: ShutdownSignal) { let mut snapshot_create_every = tokio::time::interval(self.create_every); // Don't try to create snapshot more frequently if previous take longer time snapshot_create_every.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay); @@ -69,8 +59,8 @@ impl SnapshotMaker { // Offload snapshot creation into blocking thread self.create_snapshot().await; }, - _ = message_receiver.recv() => { - info!("All handler to SnapshotMaker are dropped. Saving latest snapshot and shutting down..."); + () = shutdown_signal.receive() => { + info!("Saving latest snapshot and shutting down"); self.create_snapshot().await; break; } @@ -138,7 +128,7 @@ impl SnapshotMaker { pub fn try_read_snapshot( store_dir: impl AsRef, kura: &Arc, - query_handle: LiveQueryStoreHandle, + live_query_store_lazy: impl FnOnce() -> LiveQueryStoreHandle, BlockCount(block_count): BlockCount, ) -> Result { let mut bytes = Vec::new(); @@ -158,7 +148,7 @@ pub fn try_read_snapshot( let mut deserializer = serde_json::Deserializer::from_slice(&bytes); let seed = KuraSeed { kura: Arc::clone(kura), - query_handle, + query_handle: live_query_store_lazy(), }; let state = seed.deserialize(&mut deserializer)?; let state_view = state.view(); @@ -269,7 +259,7 @@ mod tests { fn state_factory() -> State { let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); State::new( crate::queue::tests::world_with_test_domains(), kura, @@ -298,7 +288,7 @@ mod tests { let _wsv = try_read_snapshot( &store_dir, &Kura::blank_kura_for_testing(), - LiveQueryStore::test().start(), + LiveQueryStore::start_test, BlockCount(state.view().height()), ) .unwrap(); @@ -312,7 +302,7 @@ mod tests { let Err(error) = try_read_snapshot( store_dir, &Kura::blank_kura_for_testing(), - LiveQueryStore::test().start(), + LiveQueryStore::start_test, BlockCount(15), ) else { panic!("should not be ok") @@ -334,7 +324,7 @@ mod tests { let Err(error) = try_read_snapshot( &store_dir, &Kura::blank_kura_for_testing(), - LiveQueryStore::test().start(), + LiveQueryStore::start_test, BlockCount(15), ) else { panic!("should not be ok") @@ -394,7 +384,7 @@ mod tests { let state = try_read_snapshot( &store_dir, &kura, - LiveQueryStore::test().start(), + LiveQueryStore::start_test, BlockCount(state.view().height()), ) .unwrap(); @@ -466,7 +456,7 @@ mod tests { let state = try_read_snapshot( &store_dir, &kura, - LiveQueryStore::test().start(), + LiveQueryStore::start_test, BlockCount(state.view().height()), ) .unwrap(); diff --git a/core/src/state.rs b/core/src/state.rs index a26346efec7..5f58b30bb59 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -2169,7 +2169,7 @@ mod tests { const BLOCK_CNT: usize = 10; let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(World::default(), kura, query_handle); let mut state_block = state.block(); @@ -2195,7 +2195,7 @@ mod tests { const BLOCK_CNT: usize = 10; let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(World::default(), kura.clone(), query_handle); let mut state_block = state.block(); diff --git a/core/src/sumeragi/main_loop.rs b/core/src/sumeragi/main_loop.rs index 1c37bd3fa34..c7c34368adc 100644 --- a/core/src/sumeragi/main_loop.rs +++ b/core/src/sumeragi/main_loop.rs @@ -3,6 +3,7 @@ use std::{collections::BTreeSet, ops::Deref, sync::mpsc}; use iroha_crypto::{HashOf, KeyPair}; use iroha_data_model::{block::*, events::pipeline::PipelineEventBox, peer::PeerId}; +use iroha_futures::supervisor::ShutdownSignal; use iroha_p2p::UpdateTopology; use tracing::{span, Level}; @@ -201,7 +202,7 @@ impl Sumeragi { &mut self, genesis_account: &AccountId, state: &State, - shutdown_receiver: &mut tokio::sync::oneshot::Receiver<()>, + shutdown_signal: &ShutdownSignal, ) -> Result<(), EarlyReturn> { info!( peer_id=%self.peer_id, @@ -211,10 +212,10 @@ impl Sumeragi { loop { std::thread::sleep(Duration::from_millis(50)); - early_return(shutdown_receiver).map_err(|e| { - debug!(?e, "Early return."); - e - })?; + if shutdown_signal.is_sent() { + info!("Shutdown signal received, shutting down Sumeragi..."); + return Err(EarlyReturn::ShutdownMessageReceived); + } match self.message_receiver.try_recv() { Ok(message) => { @@ -944,24 +945,12 @@ fn reset_state( } } -fn should_terminate(shutdown_receiver: &mut tokio::sync::oneshot::Receiver<()>) -> bool { - use tokio::sync::oneshot::error::TryRecvError; - - match shutdown_receiver.try_recv() { - Err(TryRecvError::Empty) => false, - reason => { - info!(?reason, "Sumeragi Thread is being shut down."); - true - } - } -} - #[iroha_logger::log(name = "consensus", skip_all)] /// Execute the main loop of [`Sumeragi`] pub(crate) fn run( genesis_network: GenesisWithPubKey, mut sumeragi: Sumeragi, - mut shutdown_receiver: tokio::sync::oneshot::Receiver<()>, + shutdown_signal: &ShutdownSignal, state: Arc, ) { // Connect peers with initial topology @@ -973,24 +962,23 @@ pub(crate) fn run( ); let span = span!(tracing::Level::TRACE, "genesis").entered(); - let is_genesis_peer = if state.view().height() == 0 - || state.view().latest_block_hash().is_none() - { - if let Some(genesis) = genesis_network.genesis { - sumeragi.init_commit_genesis(genesis, &genesis_account, &state); - true - } else { - if let Err(err) = - sumeragi.init_listen_for_genesis(&genesis_account, &state, &mut shutdown_receiver) - { - info!(?err, "Sumeragi Thread is being shut down."); - return; + let is_genesis_peer = + if state.view().height() == 0 || state.view().latest_block_hash().is_none() { + if let Some(genesis) = genesis_network.genesis { + sumeragi.init_commit_genesis(genesis, &genesis_account, &state); + true + } else { + if let Err(err) = + sumeragi.init_listen_for_genesis(&genesis_account, &state, shutdown_signal) + { + info!(?err, "Sumeragi Thread is being shut down."); + return; + } + false } + } else { false - } - } else { - false - }; + }; span.exit(); info!( @@ -1011,7 +999,7 @@ pub(crate) fn run( sumeragi.was_commit = false; sumeragi.round_start_time = Instant::now(); - while !should_terminate(&mut shutdown_receiver) { + while !shutdown_signal.is_sent() { if should_sleep { let span = span!(Level::TRACE, "main_thread_sleep"); let _enter = span.enter(); @@ -1196,20 +1184,6 @@ enum EarlyReturn { Disconnected, } -fn early_return( - shutdown_receiver: &mut tokio::sync::oneshot::Receiver<()>, -) -> Result<(), EarlyReturn> { - use tokio::sync::oneshot::error::TryRecvError; - - match shutdown_receiver.try_recv() { - Ok(()) | Err(TryRecvError::Closed) => { - info!("Sumeragi Thread is being shut down."); - Err(EarlyReturn::ShutdownMessageReceived) - } - Err(TryRecvError::Empty) => Ok(()), - } -} - /// Strategy to apply block to sumeragi. trait ApplyBlockStrategy { const LOG_MESSAGE: &'static str; @@ -1421,7 +1395,7 @@ mod tests { let domain = Domain::new(domain_id).build(&alice_id); let world = World::with([domain], [account], []); let kura = Kura::blank_kura_for_testing(); - let query_handle = LiveQueryStore::test().start(); + let query_handle = LiveQueryStore::start_test(); let state = State::new(world, Arc::clone(&kura), query_handle); // Create "genesis" block diff --git a/core/src/sumeragi/mod.rs b/core/src/sumeragi/mod.rs index 2ba02585d48..a94cf599f9f 100644 --- a/core/src/sumeragi/mod.rs +++ b/core/src/sumeragi/mod.rs @@ -11,13 +11,13 @@ use std::{ use eyre::Result; use iroha_config::parameters::actual::{Common as CommonConfig, Sumeragi as SumeragiConfig}; use iroha_data_model::{account::AccountId, block::SignedBlock, prelude::*}; +use iroha_futures::supervisor::{spawn_os_thread_as_future, Child, OnShutdown, ShutdownSignal}; use iroha_genesis::GenesisBlock; use iroha_logger::prelude::*; use network_topology::{Role, Topology}; use crate::{ block::ValidBlock, - handler::ThreadHandler, kura::BlockCount, state::{State, StateBlock}, }; @@ -36,7 +36,6 @@ pub struct SumeragiHandle { peer_id: PeerId, /// Counter for amount of dropped messages by sumeragi dropped_messages_metric: iroha_telemetry::metrics::DroppedMessagesCounter, - _thread_handle: Arc, // Should be dropped after `_thread_handle` to prevent sumeargi thread from panicking control_message_sender: mpsc::SyncSender, message_sender: mpsc::SyncSender, @@ -116,14 +115,16 @@ impl SumeragiHandle { let _ = events_sender.send(e); }); } +} +impl SumeragiStartArgs { /// Start [`Sumeragi`] actor and return handle to it. /// /// # Panics /// May panic if something is of during initialization which is bug. #[allow(clippy::too_many_lines)] - pub fn start( - SumeragiStartArgs { + pub fn start(self, shutdown_signal: ShutdownSignal) -> (SumeragiHandle, Child) { + let Self { sumeragi_config, common_config, events_sender, @@ -138,8 +139,8 @@ impl SumeragiHandle { view_changes, dropped_messages, }, - }: SumeragiStartArgs, - ) -> SumeragiHandle { + } = self; + let (control_message_sender, control_message_receiver) = mpsc::sync_channel(100); let (message_sender, message_receiver) = mpsc::sync_channel(100); @@ -175,7 +176,7 @@ impl SumeragiHandle { for block in blocks_iter { let mut state_block = state.block(); - Self::replay_block( + SumeragiHandle::replay_block( &common_config.chain, &genesis_account, &block, @@ -213,33 +214,25 @@ impl SumeragiHandle { round_start_time: Instant::now(), }; - // Oneshot channel to allow forcefully stopping the thread. - let (shutdown_sender, shutdown_receiver) = tokio::sync::oneshot::channel(); - - let thread_handle = { - let state = Arc::clone(&state); - std::thread::Builder::new() - .name("sumeragi thread".to_owned()) - .spawn(move || { - main_loop::run(genesis_network, sumeragi, shutdown_receiver, state); - }) - .expect("INTERNAL BUG: Sumeragi thread spawn failed") - }; - - let shutdown = move || { - if let Err(error) = shutdown_sender.send(()) { - iroha_logger::error!(?error); - } - }; + let child = Child::new( + tokio::task::spawn(spawn_os_thread_as_future( + std::thread::Builder::new().name("sumeragi".to_owned()), + move || { + main_loop::run(genesis_network, sumeragi, &shutdown_signal, state); + }, + )), + OnShutdown::Wait(Duration::from_secs(5)), + ); - let thread_handle = ThreadHandler::new(Box::new(shutdown), thread_handle); - SumeragiHandle { - peer_id, - dropped_messages_metric: dropped_messages, - control_message_sender, - message_sender, - _thread_handle: Arc::new(thread_handle), - } + ( + SumeragiHandle { + peer_id, + dropped_messages_metric: dropped_messages, + control_message_sender, + message_sender, + }, + child, + ) } } diff --git a/core/test_network/Cargo.toml b/core/test_network/Cargo.toml index 9998600b567..1d80086abfe 100644 --- a/core/test_network/Cargo.toml +++ b/core/test_network/Cargo.toml @@ -8,7 +8,7 @@ authors.workspace = true license.workspace = true [dependencies] -irohad = { workspace = true, features = ["test-network"] } +irohad.workspace = true iroha_core.workspace = true iroha.workspace = true @@ -19,6 +19,7 @@ iroha_data_model.workspace = true iroha_primitives.workspace = true iroha_logger.workspace = true iroha_genesis.workspace = true +iroha_futures.workspace = true iroha_wasm_builder.workspace = true test_samples.workspace = true diff --git a/core/test_network/src/lib.rs b/core/test_network/src/lib.rs index ea7b33d49e4..7bf8ccf6b45 100644 --- a/core/test_network/src/lib.rs +++ b/core/test_network/src/lib.rs @@ -20,6 +20,7 @@ use iroha_executor_data_model::permission::{ peer::CanUnregisterAnyPeer, role::CanUnregisterAnyRole, }; +use iroha_futures::supervisor::ShutdownSignal; use iroha_genesis::{GenesisBlock, RawGenesisTransaction}; use iroha_logger::{warn, InstrumentFutures}; use iroha_primitives::{ @@ -422,6 +423,8 @@ pub struct Peer { pub p2p_address: SocketAddr, /// The key-pair for the peer pub key_pair: KeyPair, + /// Shutdown handle + shutdown: ShutdownSignal, /// Iroha server pub irohad: Option, /// Temporary directory @@ -445,7 +448,8 @@ impl std::cmp::Eq for Peer {} impl Drop for Peer { fn drop(&mut self) { - self.stop(); + // TODO: wait for complete shutdown + self.terminate(); } } @@ -499,27 +503,35 @@ impl Peer { ); let logger = iroha_logger::test_logger(); - let (_, irohad) = Iroha::start_network(config, genesis, logger) - .instrument(info_span) + let (irohad, run_fut) = Iroha::start(config, genesis, logger, self.shutdown.clone()) .await - .expect("Failed to start Iroha"); + .expect("Iroha should start in test network"); + + let _handle = tokio::spawn( + async move { + if let Err(error) = run_fut.await { + iroha_logger::error!(?error, "Peer exited with an error"); + }; + } + .instrument(info_span), + ); self.irohad = Some(irohad); - time::sleep(Duration::from_millis(300)).await; // Prevent temporary directory deleting self.temp_dir = Some(temp_dir); } - /// Stop the peer if it's running - pub fn stop(&mut self) { - iroha_logger::info!( - p2p_addr = %self.p2p_address, - api_addr = %self.api_address, - "Stopping peer", - ); - - iroha_logger::info!("Shutting down peer..."); - self.irohad.take(); + /// Terminate the peer + // FIXME: support _complete_ forceful termination, with waiting for full abort + pub fn terminate(&mut self) { + if let Some(_irohad) = self.irohad.take() { + iroha_logger::info!( + p2p_addr = %self.p2p_address, + api_addr = %self.api_address, + "Terminating peer", + ); + self.shutdown.send(); + } } /// Creates peer @@ -534,11 +546,13 @@ impl Peer { let p2p_address = local_unique_port()?; let api_address = local_unique_port()?; let id = PeerId::new(p2p_address.clone(), key_pair.public_key().clone()); + let shutdown = ShutdownSignal::new(); Ok(Self { id, key_pair, p2p_address, api_address, + shutdown, irohad: None, temp_dir: None, }) diff --git a/futures/Cargo.toml b/futures/Cargo.toml index 5cd4feba46f..7b295c6c75c 100644 --- a/futures/Cargo.toml +++ b/futures/Cargo.toml @@ -24,7 +24,10 @@ iroha_logger = { workspace = true } rand = { workspace = true } serde_json = { workspace = true } serde = { workspace = true, features = ["derive"] } -tokio = { workspace = true, features = ["rt", "rt-multi-thread", "macros"] } +tokio = { workspace = true, features = ["rt", "rt-multi-thread", "macros", "signal"] } +tokio-util = { workspace = true } +thiserror = { workspace = true } +futures = { workspace = true, features = ["std", "alloc"] } [dev-dependencies] -tokio-stream = "0.1.15" +tokio-stream = { version = "0.1.15", features = ["sync"] } diff --git a/futures/src/lib.rs b/futures/src/lib.rs index 516182e08d9..98e76ff710d 100644 --- a/futures/src/lib.rs +++ b/futures/src/lib.rs @@ -1,4 +1,7 @@ //! Crate with various Iroha futures + +pub mod supervisor; + use std::{ future::Future, pin::Pin, diff --git a/futures/src/supervisor.rs b/futures/src/supervisor.rs new file mode 100644 index 00000000000..e3d0f2c6a7f --- /dev/null +++ b/futures/src/supervisor.rs @@ -0,0 +1,720 @@ +//! Lightweight supervisor for tokio tasks. +//! +//! What it does: +//! +//! - Monitors multiple children (as spawned [`JoinHandle`]) +//! - Provides a single shutdown signal for everything +//! - Supports graceful shutdown timeout before aborting a child (via [`OnShutdown`]) +//! - If a child panics, initiates shutdown and exits with an error +//! - If a child exits before shutdown signal, also initiates shutdown and exits with an error. +//! Note: this might not be always the desirable behaviour, but _currently_ there are no other +//! cases in Iroha. +//! This behaviour could be easily extended to support refined strategies. +//! - Logs children's lifecycle +//! +//! What it doesn't: +//! +//! - Doesn't support restarting child. +//! To implement that, we need a formal actor system, i.e. actors with a unified lifecycle, +//! messaging system, and, most importantly, address registry +//! (for reference, see [Registry - Elixir](https://hexdocs.pm/elixir/1.17.0-rc.1/Registry.html)). + +use std::time::Duration; + +use iroha_logger::{prelude::Span, InstrumentFutures}; +use tokio::{ + sync::{mpsc, oneshot}, + task::{JoinHandle, JoinSet}, + time::timeout, +}; +use tokio_util::sync::CancellationToken; + +/// Supervisor for tokio tasks. +#[derive(Debug, Default)] +pub struct Supervisor { + children: Vec, + shutdown_signal: ShutdownSignal, +} + +impl Supervisor { + /// Constructor + pub fn new() -> Self { + Self::default() + } + + /// Get a copy of the supervisor's shutdown signal + pub fn shutdown_signal(&self) -> ShutdownSignal { + self.shutdown_signal.clone() + } + + /// Monitor a given [`Child`] + #[track_caller] + pub fn monitor(&mut self, child: impl Into) { + self.children.push(child.into()); + } + + /// Spawns a task that will initiate supervisor shutdown on SIGINT/SIGTERM signals. + /// # Errors + /// See [`signal::unix::signal`] errors. + pub fn setup_shutdown_on_os_signals(&mut self) -> Result<(), Error> { + use tokio::signal; + + let mut sigint = signal::unix::signal(signal::unix::SignalKind::interrupt())?; + let mut sigterm = signal::unix::signal(signal::unix::SignalKind::terminate())?; + + let shutdown_signal = self.shutdown_signal(); + self.monitor(tokio::spawn(async move { + tokio::select! { + _ = sigint.recv() => { + iroha_logger::info!("SIGINT received, shutting down..."); + }, + _ = sigterm.recv() => { + iroha_logger::info!("SIGTERM received, shutting down..."); + }, + } + + shutdown_signal.send(); + })); + + Ok(()) + } + + /// Spawns a task that will shut down the supervisor once the external + /// [`ShutdownSignal`] is sent. + pub fn shutdown_on_external_signal(&mut self, external_signal: ShutdownSignal) { + let self_signal = self.shutdown_signal(); + + self.monitor(tokio::spawn(async move { + external_signal.receive().await; + self_signal.send(); + })) + } + + /// Start actual supervision and wait until all children terminate. + /// + /// Returns [`Ok`] if all children exited/aborted as expected after shutdown + /// signal being sent. + /// + /// # Errors + /// If any child panicked during execution or exited/aborted before shutdown signal being sent. + pub async fn start(self) -> Result<(), Error> { + // technically - should work without this check too + if self.children.is_empty() { + return Ok(()); + } + + LoopBuilder::new(self.shutdown_signal) + .monitor(self.children) + .into_loop() + .run() + .await + } +} + +struct LoopBuilder { + set: JoinSet<()>, + shutdown_signal: ShutdownSignal, + exit: ( + mpsc::Sender, + mpsc::Receiver, + ), +} + +impl LoopBuilder { + fn new(shutdown_signal: ShutdownSignal) -> Self { + Self { + set: JoinSet::new(), + shutdown_signal, + exit: mpsc::channel(256), + } + } + + fn monitor(mut self, children: impl IntoIterator) -> Self { + for child in children { + self.monitor_single(child); + } + self + } + + fn monitor_single( + &mut self, + Child { + task, + on_shutdown, + span, + }: Child, + ) { + let exit_tx = self.exit.0.clone(); + + // FIXME: tried to use `Notify` - couldn't make it to work for all cases + // CancellationToken just works, although semantically not a great fit + let exit_token = CancellationToken::new(); + + let exit_token2 = exit_token.clone(); + let abort_handle = self.set.spawn( + async move { + iroha_logger::debug!("Start monitoring a child"); + let result = match task.await { + Ok(()) => { + iroha_logger::debug!("Child exited normally"); + ChildExitResult::Ok + } + Err(err) if err.is_panic() => { + // we could call `err.into_panic()` and downcast `Any` to `String`, + // but the panic message was most probably already printed + iroha_logger::error!("Child panicked"); + ChildExitResult::Panic + } + Err(err) if err.is_cancelled() => { + iroha_logger::debug!("Child aborted"); // oh.. + ChildExitResult::Cancel + } + _ => unreachable!(), + }; + let _ = exit_tx.send(result).await; + exit_token2.cancel(); + } + .instrument(span.clone()), + ); + + // task to handle graceful shutdown + let shutdown_signal = self.shutdown_signal.clone(); + self.set.spawn(async move { + tokio::select! { + () = exit_token.cancelled() => { + // exit + } + () = shutdown_signal.receive() => { + match on_shutdown { + OnShutdown::Abort => { + iroha_logger::debug!("Shutdown signal received, aborting..."); + abort_handle.abort(); + } + OnShutdown::Wait(duration) => { + iroha_logger::debug!(?duration, "Shutdown signal received, waiting for child shutdown..."); + if timeout(duration, exit_token.cancelled()).await.is_err() { + iroha_logger::debug!(expected = ?duration, "Child shutdown took longer than expected, aborting..."); + abort_handle.abort(); + } + } + } + + } + } + }.instrument(span)); + } + + fn into_loop(self) -> SupervisorLoop { + let Self { + set, + shutdown_signal, + exit: (_tx, exit_rx), + } = self; + SupervisorLoop { + set, + shutdown_signal, + exit: exit_rx, + caught_panic: false, + caught_unexpected_exit: false, + } + } +} + +struct SupervisorLoop { + set: JoinSet<()>, + shutdown_signal: ShutdownSignal, + exit: mpsc::Receiver, + caught_panic: bool, + caught_unexpected_exit: bool, +} + +impl SupervisorLoop { + async fn run(mut self) -> Result<(), Error> { + loop { + tokio::select! { + // this should naturally finish when all supervisor-spawned tasks finish + Some(result) = self.set.join_next() => { + if let Err(err) = result { + if err.is_panic() { + iroha_logger::error!(?err, "Supervisor-spawned task panicked; it is probably a bug"); + } + } + } + + // this should finish when all task monitors finish + Some(result) = self.exit.recv() => { + iroha_logger::debug!(?result, "Child exited"); + self.handle_child_exit(result); + } + + else => break, + } + } + + // TODO: could report several reports. use error-stack? + if self.caught_panic { + Err(Error::ChildPanicked) + } else if self.caught_unexpected_exit { + Err(Error::UnexpectedExit) + } else { + Ok(()) + } + } + + fn handle_child_exit(&mut self, result: ChildExitResult) { + match result { + ChildExitResult::Ok | ChildExitResult::Cancel if !self.shutdown_signal.is_sent() => { + iroha_logger::error!("Some task exited unexpectedly, shutting down everything..."); + self.caught_unexpected_exit = true; + self.shutdown_signal.send(); + } + ChildExitResult::Panic if !self.caught_panic => { + iroha_logger::error!("Some task panicked, shutting down everything..."); + self.caught_panic = true; + self.shutdown_signal.send(); + } + _ => {} + } + } +} + +#[derive(Copy, Clone, Debug)] +enum ChildExitResult { + Ok, + Panic, + Cancel, +} + +/// Signal indicating system shutdown. Could be cloned around. +/// +/// It is effectively a wrap around [`CancellationToken`], but with different naming. +#[derive(Clone, Debug, Default)] +pub struct ShutdownSignal(CancellationToken); + +impl ShutdownSignal { + /// Constructor + pub fn new() -> Self { + Self::default() + } + + /// Send the shutdown signal, resolving all [`Self::receive`] futures. + pub fn send(&self) { + self.0.cancel(); + } + + /// Receive the shutdown signal. Resolves after [`Self::send`]. + pub async fn receive(&self) { + self.0.cancelled().await + } + + /// Sync check whether the shutdown signal was sent + pub fn is_sent(&self) -> bool { + self.0.is_cancelled() + } +} + +/// Spawn [`std::thread`] as a future that finishes when the thread finishes and panics +/// when the thread panics. +/// +/// Its intention is to link an OS thread to [`Supervisor`] in the following way: +/// +/// ``` +/// use std::time::Duration; +/// +/// use iroha_futures::supervisor::{ +/// spawn_os_thread_as_future, Child, OnShutdown, ShutdownSignal, Supervisor, +/// }; +/// +/// fn spawn_heavy_work(shutdown_signal: ShutdownSignal) -> Child { +/// Child::new( +/// tokio::spawn(spawn_os_thread_as_future( +/// std::thread::Builder::new().name("heavy_worker".to_owned()), +/// move || { +/// loop { +/// if shutdown_signal.is_sent() { +/// break; +/// } +/// // do heavy work... +/// std::thread::sleep(Duration::from_millis(100)); +/// } +/// }, +/// )), +/// OnShutdown::Wait(Duration::from_secs(1)), +/// ) +/// } +/// +/// #[tokio::main] +/// async fn main() { +/// let mut supervisor = Supervisor::new(); +/// supervisor.monitor(spawn_heavy_work(supervisor.shutdown_signal())); +/// +/// let signal = supervisor.shutdown_signal(); +/// tokio::spawn(async move { +/// tokio::time::sleep(Duration::from_millis(300)).await; +/// signal.send(); +/// }); +/// +/// supervisor.start().await.unwrap(); +/// } +/// ``` +/// +/// **Note:** this function doesn't provide a mechanism to shut down the thread. +/// You should handle it within the closure on your own, e.g. by passing [`ShutdownSignal`] inside. +pub async fn spawn_os_thread_as_future(builder: std::thread::Builder, f: F) +where + F: FnOnce(), + F: Send + 'static, +{ + let (complete_tx, complete_rx) = oneshot::channel(); + + // we are okay to drop the handle; thread will continue running in a detached way + let _handle: std::thread::JoinHandle<_> = builder + .spawn(move || { + f(); + + // the receiver might be dropped + let _ = complete_tx.send(()); + }) + .expect("should spawn thread normally"); + + complete_rx + .await + .expect("thread completion notifier was dropped; thread probably panicked"); +} + +/// Supervisor child. +#[derive(Debug)] +pub struct Child { + span: Span, + task: JoinHandle<()>, + on_shutdown: OnShutdown, +} + +impl Child { + /// Create a new supervisor child + #[track_caller] + pub fn new(task: JoinHandle<()>, on_shutdown: OnShutdown) -> Self { + let caller_location = std::panic::Location::caller().to_string(); + let span = iroha_logger::debug_span!("supervisor_child_monitor", %caller_location); + + Self { + span, + task, + on_shutdown, + } + } +} + +impl From> for Child { + #[track_caller] + fn from(value: JoinHandle<()>) -> Self { + Self::new(value, OnShutdown::Abort) + } +} + +/// Supervisor errors +#[derive(Debug, thiserror::Error)] +#[allow(missing_docs)] +pub enum Error { + #[error("Some of the supervisor children panicked")] + ChildPanicked, + #[error("Some of the supervisor children exited unexpectedly")] + UnexpectedExit, + #[error("IO error")] + IO(#[from] std::io::Error), +} + +/// Specifies supervisor action regarding a [`Child`] when shutdown happens. +#[derive(Default, Copy, Clone, Debug)] +pub enum OnShutdown { + /// Abort the child immediately + #[default] + Abort, + /// Wait until the child exits/aborts on its own; abort if it takes too long + Wait(Duration), +} + +#[cfg(test)] +mod tests { + use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }; + + use tokio::{ + sync::{mpsc, oneshot}, + time::sleep, + }; + + use super::*; + + const TICK_TIMEOUT: Duration = Duration::from_millis(10); + /// For some reason, when all tests are run simultaneously, tests with OS spawns take longer + /// than just [`TICK_TIMEOUT`] + const OS_THREAD_SPAWN_TICK: Duration = Duration::from_millis(500); + const SHUTDOWN_WITHIN_TICK: OnShutdown = OnShutdown::Wait(TICK_TIMEOUT); + + #[tokio::test] + async fn empty_supervisor_just_exits() { + timeout(TICK_TIMEOUT, Supervisor::new().start()) + .await + .expect("should exit immediately") + .expect("should not emit error"); + } + + #[tokio::test] + async fn happy_graceful_shutdown() { + #[derive(Debug)] + enum Message { + Ping { pong: oneshot::Sender<()> }, + Stopped, + } + + let mut sup = Supervisor::new(); + + let (tx_into, mut rx_into) = mpsc::channel(1); + let (tx_out, rx_out) = oneshot::channel(); + + { + let shutdown = sup.shutdown_signal(); + sup.monitor(Child::new( + tokio::spawn(async move { + loop { + tokio::select! { + Some(Message::Ping { pong }) = rx_into.recv() => { + pong.send(()).unwrap(); + }, + () = shutdown.receive() => { + tx_out.send(Message::Stopped).unwrap(); + break; + } + } + } + }), + SHUTDOWN_WITHIN_TICK, + )); + } + + // ensure task is spinning + timeout(TICK_TIMEOUT, async { + let (tx, rx) = oneshot::channel(); + tx_into.send(Message::Ping { pong: tx }).await.unwrap(); + rx.await.unwrap(); + }) + .await + .unwrap(); + + let shutdown = sup.shutdown_signal(); + let sup_handle = tokio::spawn(sup.start()); + + // send shutdown signal + shutdown.send(); + timeout(TICK_TIMEOUT, async { + let Message::Stopped = rx_out.await.unwrap() else { + panic!("expected stopped message"); + }; + }) + .await + .unwrap(); + + // we can now expect supervisor to stop without errors + timeout(TICK_TIMEOUT, sup_handle) + .await + .unwrap() + .expect("supervisor run should not panic") + .expect("supervisor should not find any nested panics"); + } + + #[tokio::test] + async fn supervisor_catches_panic_of_a_monitored_task() { + let mut sup = Supervisor::new(); + + sup.monitor(tokio::spawn(async { + panic!("my panic should not be unnoticed") + })); + + let Error::ChildPanicked = timeout(TICK_TIMEOUT, sup.start()) + .await + .expect("should finish almost immediately") + .expect_err("should catch the panic") + else { + panic!("other errors aren't expected") + }; + } + + #[tokio::test] + async fn supervisor_sends_shutdown_when_some_task_exits() { + let mut sup = Supervisor::new(); + + // exits immediately, not expected + sup.monitor(tokio::spawn(async {})); + + // some task that needs shutdown gracefully + let signal = sup.shutdown_signal(); + let (graceful_tx, graceful_rx) = oneshot::channel(); + sup.monitor(Child::new( + tokio::spawn(async move { + signal.receive().await; + graceful_tx.send(()).unwrap(); + }), + SHUTDOWN_WITHIN_TICK, + )); + + let sup_handle = tokio::spawn(sup.start()); + + timeout(TICK_TIMEOUT, graceful_rx) + .await + .expect("should shutdown everything immediately") + .expect("should receive message fine"); + + let Error::UnexpectedExit = timeout(TICK_TIMEOUT, sup_handle) + .await + .unwrap() + .expect("supervisor should not panic") + .expect_err("should handle unexpected exit") + else { + panic!("other errors aren't expected") + }; + } + + #[tokio::test] + async fn graceful_shutdown_when_some_task_panics() { + let mut sup = Supervisor::new(); + let signal = sup.shutdown_signal(); + sup.monitor(tokio::spawn(async { panic!() })); + + let Error::ChildPanicked = timeout(TICK_TIMEOUT, sup.start()) + .await + .expect("should finish immediately") + .expect_err("should catch the panic") + else { + panic!("other errors aren't expected") + }; + + assert!(signal.is_sent()); + } + + fn spawn_task_with_graceful_shutdown( + sup: &mut Supervisor, + shutdown_time: Duration, + timeout: Duration, + ) -> Arc { + let graceful = Arc::new(AtomicBool::new(false)); + + let signal = sup.shutdown_signal(); + let graceful_clone = graceful.clone(); + sup.monitor(Child::new( + tokio::spawn(async move { + signal.receive().await; + sleep(shutdown_time).await; + graceful_clone.fetch_or(true, Ordering::Relaxed); + }), + OnShutdown::Wait(timeout), + )); + + graceful + } + + #[tokio::test] + async fn actually_waits_for_shutdown() { + const ACTUAL_SHUTDOWN: Duration = Duration::from_millis(50); + const TIMEOUT: Duration = Duration::from_millis(100); + + let mut sup = Supervisor::new(); + let signal = sup.shutdown_signal(); + let graceful = spawn_task_with_graceful_shutdown(&mut sup, ACTUAL_SHUTDOWN, TIMEOUT); + let sup_fut = tokio::spawn(sup.start()); + + signal.send(); + timeout(ACTUAL_SHUTDOWN + TICK_TIMEOUT, sup_fut) + .await + .expect("should finish within this time") + .expect("supervisor should not panic") + .expect("supervisor should exit fine"); + assert!(graceful.load(Ordering::Relaxed)); + } + + #[tokio::test] + async fn aborts_task_if_shutdown_takes_long() { + const ACTUAL_SHUTDOWN: Duration = Duration::from_millis(100); + const TIMEOUT: Duration = Duration::from_millis(50); + + // Start system + let mut sup = Supervisor::new(); + let signal = sup.shutdown_signal(); + let graceful = spawn_task_with_graceful_shutdown(&mut sup, ACTUAL_SHUTDOWN, TIMEOUT); + let sup_fut = tokio::spawn(sup.start()); + + // Initiate shutdown + signal.send(); + timeout(TIMEOUT + TICK_TIMEOUT, sup_fut) + .await + .expect("should finish within this time") + .expect("supervisor should not panic") + .expect("shutdown took too long, but it is not an error"); + assert!(!graceful.load(Ordering::Relaxed)); + } + + #[tokio::test] + async fn can_monitor_os_thread_shutdown() { + const LOOP_SLEEP: Duration = Duration::from_millis(5); + const TIMEOUT: Duration = Duration::from_millis(50); + + let mut sup = Supervisor::new(); + let signal = sup.shutdown_signal(); + let signal2 = sup.shutdown_signal(); + let (ready_tx, ready_rx) = std::sync::mpsc::sync_channel(1); + let graceful = Arc::new(AtomicBool::new(false)); + let graceful2 = graceful.clone(); + sup.monitor(Child::new( + tokio::spawn(spawn_os_thread_as_future( + std::thread::Builder::new(), + move || { + // FIXME ready state + iroha_logger::info!("sending message"); + ready_tx.send(()).unwrap(); + iroha_logger::info!("done sending"); + loop { + if signal.is_sent() { + graceful.fetch_or(true, Ordering::Relaxed); + break; + } + std::thread::sleep(LOOP_SLEEP); + } + }, + )), + OnShutdown::Wait(TIMEOUT), + )); + // need to yield so that it can actually start the thread + tokio::task::yield_now().await; + let sup_fut = tokio::spawn(sup.start()); + + ready_rx + .recv_timeout(OS_THREAD_SPAWN_TICK) + .expect("thread should start by now"); + signal2.send(); + timeout(TICK_TIMEOUT, sup_fut) + .await + .expect("should shutdown within timeout") + .expect("should not panic") + .expect("should shutdown without errors"); + assert!(graceful2.load(Ordering::Relaxed)); + } + + #[tokio::test] + async fn can_catch_os_thread_panic() { + let mut sup = Supervisor::new(); + sup.monitor(tokio::spawn(spawn_os_thread_as_future( + std::thread::Builder::new(), + || panic!("oops"), + ))); + let Error::ChildPanicked = timeout(OS_THREAD_SPAWN_TICK, sup.start()) + .await + .expect("should terminate immediately") + .expect_err("should catch panic") + else { + panic!("no other error expected"); + }; + println!("hey"); + } +} diff --git a/logger/src/lib.rs b/logger/src/lib.rs index 1378ea9cc1f..65a4de4300a 100644 --- a/logger/src/lib.rs +++ b/logger/src/lib.rs @@ -5,6 +5,7 @@ pub mod telemetry; use std::{ fmt::Debug, + str::FromStr, sync::{ atomic::{AtomicBool, Ordering}, OnceLock, @@ -86,6 +87,8 @@ pub fn init_global(config: InitConfig) -> Result { /// Returns once lazily initialised global logger for testing purposes. /// +/// Log level may be modified via `TEST_LOG_LEVEL` environment variable +/// /// # Panics /// If [`init_global`] or [`disable_global`] were called first. pub fn test_logger() -> LoggerHandle { @@ -99,7 +102,11 @@ pub fn test_logger() -> LoggerHandle { // `test_logger` simple and also will emphasise isolation which is necessary anyway in // case of singleton mocking (where the logger is the singleton). let config = Config { - level: Level::DEBUG.into(), + level: std::env::var("TEST_LOG_LEVEL") + .ok() + .and_then(|raw| Level::from_str(&raw).ok()) + .unwrap_or(Level::DEBUG) + .into(), format: Format::Pretty, }; diff --git a/p2p/Cargo.toml b/p2p/Cargo.toml index 61ef83720ce..acd3b6c0b1c 100644 --- a/p2p/Cargo.toml +++ b/p2p/Cargo.toml @@ -14,12 +14,21 @@ workspace = true [dependencies] iroha_logger = { workspace = true } iroha_crypto = { workspace = true, default-features = true } -iroha_data_model = { workspace = true, default-features = true, features = ["transparent_api"] } +iroha_data_model = { workspace = true, default-features = true, features = [ + "transparent_api", +] } iroha_primitives = { workspace = true } iroha_config = { workspace = true } +iroha_futures = { workspace = true } rand = { workspace = true } -tokio = { workspace = true, features = ["rt-multi-thread", "macros", "io-util", "net", "time"] } +tokio = { workspace = true, features = [ + "rt-multi-thread", + "macros", + "io-util", + "net", + "time", +] } futures = { workspace = true, features = ["alloc"] } async-trait = { workspace = true } parity-scale-codec = { workspace = true, features = ["derive"] } diff --git a/p2p/src/network.rs b/p2p/src/network.rs index 85178ab95d8..fedded056b9 100644 --- a/p2p/src/network.rs +++ b/p2p/src/network.rs @@ -10,6 +10,7 @@ use futures::{stream::FuturesUnordered, StreamExt}; use iroha_config::parameters::actual::Network as Config; use iroha_crypto::{KeyPair, PublicKey}; use iroha_data_model::prelude::PeerId; +use iroha_futures::supervisor::{Child, OnShutdown}; use iroha_logger::prelude::*; use iroha_primitives::addr::SocketAddr; use parity_scale_codec::Encode as _; @@ -75,7 +76,7 @@ impl NetworkBaseHandle { address: listen_addr, idle_timeout, }: Config, - ) -> Result { + ) -> Result<(Self, Child), Error> { // TODO: enhance the error by reporting the origin of `listen_addr` let listener = TcpListener::bind(listen_addr.value().to_socket_addrs()?.as_slice()).await?; iroha_logger::info!("Network bound to listener"); @@ -108,15 +109,18 @@ impl NetworkBaseHandle { _key_exchange: core::marker::PhantomData::, _encryptor: core::marker::PhantomData::, }; - tokio::task::spawn(network.run()); - Ok(Self { - subscribe_to_peers_messages_sender, - online_peers_receiver, - update_topology_sender, - network_message_sender, - _key_exchange: core::marker::PhantomData, - _encryptor: core::marker::PhantomData, - }) + let child = Child::new(tokio::task::spawn(network.run()), OnShutdown::Abort); + Ok(( + Self { + subscribe_to_peers_messages_sender, + online_peers_receiver, + update_topology_sender, + network_message_sender, + _key_exchange: core::marker::PhantomData, + _encryptor: core::marker::PhantomData, + }, + child, + )) } /// Subscribe to messages received from other peers in the network diff --git a/p2p/tests/integration/p2p.rs b/p2p/tests/integration/p2p.rs index b73c06f0117..39ef5615506 100644 --- a/p2p/tests/integration/p2p.rs +++ b/p2p/tests/integration/p2p.rs @@ -45,7 +45,7 @@ async fn network_create() { address: WithOrigin::inline(address.clone()), idle_timeout, }; - let network = NetworkHandle::start(key_pair, config).await.unwrap(); + let (network, _) = NetworkHandle::start(key_pair, config).await.unwrap(); tokio::time::sleep(delay).await; info!("Connecting to peer..."); @@ -156,7 +156,7 @@ async fn two_networks() { address: WithOrigin::inline(address1.clone()), idle_timeout, }; - let mut network1 = NetworkHandle::start(key_pair1, config1).await.unwrap(); + let (mut network1, _) = NetworkHandle::start(key_pair1, config1).await.unwrap(); info!("Starting second network..."); let address2 = socket_addr!(127.0.0.1:12_010); @@ -164,7 +164,7 @@ async fn two_networks() { address: WithOrigin::inline(address2.clone()), idle_timeout, }; - let network2 = NetworkHandle::start(key_pair2, config2).await.unwrap(); + let (network2, _) = NetworkHandle::start(key_pair2, config2).await.unwrap(); let mut messages2 = WaitForN::new(1); let actor2 = TestActor::start(messages2.clone()); @@ -302,7 +302,7 @@ async fn start_network( address: WithOrigin::inline(address), idle_timeout, }; - let mut network = NetworkHandle::start(key_pair, config).await.unwrap(); + let (mut network, _) = NetworkHandle::start(key_pair, config).await.unwrap(); network.subscribe_to_peers_messages(actor); let _ = barrier.wait().await; diff --git a/telemetry/src/dev.rs b/telemetry/src/dev.rs index 1ca1511f3a0..881bbf1b811 100644 --- a/telemetry/src/dev.rs +++ b/telemetry/src/dev.rs @@ -47,8 +47,6 @@ pub async fn start_file_output( ) })?; - // Serde doesn't support async Read Write traits. - // So let synchronous code be here. let join_handle = task::spawn(async move { while let Some(item) = stream.next().await { if let Err(error) = write_telemetry(&mut file, &item).await { @@ -61,8 +59,11 @@ pub async fn start_file_output( } async fn write_telemetry(file: &mut File, item: &FuturePollTelemetry) -> Result<()> { + // Serde doesn't support async Read Write traits. + // So let synchronous code be here. let mut json = serde_json::to_string(&item).wrap_err("failed to serialize telemetry to JSON")?; + json.push('\n'); file.write_all(json.as_bytes()) .await diff --git a/torii/src/lib.rs b/torii/src/lib.rs index 35513feb9a3..d3d6c87527d 100644 --- a/torii/src/lib.rs +++ b/torii/src/lib.rs @@ -32,9 +32,10 @@ use iroha_core::{ EventsSender, }; use iroha_data_model::ChainId; +use iroha_futures::supervisor::ShutdownSignal; use iroha_primitives::addr::SocketAddr; use iroha_torii_const::uri; -use tokio::{net::TcpListener, sync::Notify, task}; +use tokio::{net::TcpListener, task}; use tower_http::{ timeout::TimeoutLayer, trace::{DefaultMakeSpan, TraceLayer}, @@ -58,7 +59,6 @@ pub struct Torii { kiso: KisoHandle, queue: Arc, events: EventsSender, - notify_shutdown: Arc, query_service: LiveQueryStoreHandle, kura: Arc, transaction_max_content_len: Bytes, @@ -77,7 +77,6 @@ impl Torii { config: Config, queue: Arc, events: EventsSender, - notify_shutdown: Arc, query_service: LiveQueryStoreHandle, kura: Arc, state: Arc, @@ -88,7 +87,6 @@ impl Torii { kiso, queue, events, - notify_shutdown, query_service, kura, state, @@ -245,7 +243,10 @@ impl Torii { /// /// # Errors /// Can fail due to listening to network or if http server fails - async fn start_api(self: Arc) -> eyre::Result>>> { + async fn start_api( + self: Arc, + shutdown_signal: &ShutdownSignal, + ) -> eyre::Result>>> { let torii_address = self.address.value(); let handles = torii_address @@ -256,11 +257,11 @@ impl Torii { .await? .into_iter() .map(|listener| { + let signal = shutdown_signal.clone(); + let signal = async move { signal.receive().await }; let torii = Arc::clone(&self); let api_router = torii.create_api_router(); - let signal = async move { torii.notify_shutdown.notified().await }; - let serve_fut = async move { axum::serve(listener, api_router) .with_graceful_shutdown(signal) @@ -281,13 +282,14 @@ impl Torii { #[iroha_futures::telemetry_future] pub async fn start( self, + shutdown_signal: &ShutdownSignal, ) -> error_stack::Result, eyre::Report> { let torii = Arc::new(self); let mut handles = vec![]; handles.extend( Arc::clone(&torii) - .start_api() + .start_api(shutdown_signal) .await .into_report() .map_err(|err| err.attach_printable(torii.address.clone().into_attachment()))?,