diff --git a/Cargo.lock b/Cargo.lock index b749998cd31b..7536eae33b2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,13 +12,19 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a49806b9dadc843c61e7c97e72490ad7f7220ae249012fbda9ad0609457c0543" +checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" dependencies = [ - "gimli 0.21.0", + "gimli 0.22.0", ] +[[package]] +name = "adler" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc9a9dd069569f212bc4330af9f17c4afb5e8ce185e83dbb14f1349dda18b10" + [[package]] name = "adler32" version = "1.1.0" @@ -27,57 +33,56 @@ checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d" [[package]] name = "aead" -version = "0.2.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cf01b9b56e767bb57b94ebf91a58b338002963785cdd7013e21c0d4679471e4" +checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" dependencies = [ - "generic-array", + "generic-array 0.14.2", ] [[package]] name = "aes" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" +checksum = "f7001367fde4c768a19d1029f0a8be5abd9308e1119846d5bd9ad26297b8faf5" dependencies = [ "aes-soft", "aesni", - "block-cipher-trait", + "block-cipher", ] [[package]] name = "aes-gcm" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "834a6bda386024dbb7c8fc51322856c10ffe69559f972261c868485f5759c638" +checksum = "86f5007801316299f922a6198d1d09a0bae95786815d066d5880d13f7c45ead1" dependencies = [ "aead", "aes", - "block-cipher-trait", + "block-cipher", "ghash", "subtle 2.2.3", - "zeroize", ] [[package]] name = "aes-soft" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" +checksum = "4925647ee64e5056cf231608957ce7c81e12d6d6e316b9ce1404778cc1d35fa7" dependencies = [ - "block-cipher-trait", + "block-cipher", "byteorder", - "opaque-debug", + "opaque-debug 0.2.3", ] [[package]] name = "aesni" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" +checksum = "d050d39b0b7688b3a3254394c3e30a9d66c41dcf9b05b0e2dbdc623f6505d264" dependencies = [ - "block-cipher-trait", - "opaque-debug", + "block-cipher", + "opaque-debug 0.2.3", ] [[package]] @@ -97,9 +102,9 @@ checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" [[package]] name = "aho-corasick" -version = "0.7.10" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" +checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" dependencies = [ "memchr", ] @@ -121,7 +126,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -130,7 +135,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -191,7 +196,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d0864d84b8e07b145449be9a8537db86bf9de5ce03b913214694643b4743502" dependencies = [ "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -246,12 +251,12 @@ checksum = "c17772156ef2829aadc587461c7753af20b7e8db1529bc66855add962a3b35d3" [[package]] name = "async-tls" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fd83426b89b034bf4e9ceb9c533c2f2386b813fd3dcae0a425ec6f1837d78a" +checksum = "df097e3f506bec0e1a24f06bb3c962c228f36671de841ff579cb99f371772634" dependencies = [ "futures 0.3.5", - "rustls", + "rustls 0.18.0", "webpki", "webpki-roots 0.19.0", ] @@ -264,7 +269,7 @@ checksum = "a265e3abeffdce30b2e26b7a11b222fe37c6067404001b434101457d0385eb92" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -275,7 +280,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -292,9 +297,9 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "backtrace" -version = "0.3.49" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05100821de9e028f12ae3d189176b41ee198341eb8f369956407fea2f5cc666c" +checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293" dependencies = [ "addr2line", "cfg-if", @@ -318,15 +323,15 @@ checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" [[package]] name = "base64" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e223af0dc48c96d4f8342ec01a4974f139df863896b316681efd36742f22cc67" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" [[package]] name = "bincode" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" +checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" dependencies = [ "byteorder", "serde", @@ -385,9 +390,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330" dependencies = [ "byte-tools", - "crypto-mac", - "digest", - "opaque-debug", + "crypto-mac 0.7.0", + "digest 0.8.1", + "opaque-debug 0.2.3", +] + +[[package]] +name = "blake2" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84ce5b6108f8e154604bd4eb76a2f726066c3464d5a552a4229262a18c9bb471" +dependencies = [ + "byte-tools", + "byteorder", + "crypto-mac 0.8.0", + "digest 0.9.0", + "opaque-debug 0.2.3", ] [[package]] @@ -431,16 +449,25 @@ dependencies = [ "block-padding", "byte-tools", "byteorder", - "generic-array", + "generic-array 0.12.3", ] [[package]] -name = "block-cipher-trait" -version = "0.6.2" +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array 0.14.2", +] + +[[package]] +name = "block-cipher" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" +checksum = "fa136449e765dc7faa244561ccae839c394048667929af599b5d931ebe7b7f10" dependencies = [ - "generic-array", + "generic-array 0.14.2", ] [[package]] @@ -517,9 +544,12 @@ dependencies = [ [[package]] name = "bytes" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" +checksum = "118cf036fbb97d0816e3c34b2d7a1e8cfc60f68fcf63d550ddbe9bd5f59c213b" +dependencies = [ + "loom", +] [[package]] name = "c_linked_list" @@ -535,9 +565,9 @@ checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" [[package]] name = "cc" -version = "1.0.54" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311" +checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518" dependencies = [ "jobserver", ] @@ -559,9 +589,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "chacha20" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6a7ae4c498f8447d86baef0fa0831909333f558866fabcb21600625ac5a31c7" +checksum = "086c0f07ac275808b7bf9a39f2fd013aae1498be83632814c8c4e0bd53f2dc58" dependencies = [ "stream-cipher", "zeroize", @@ -569,9 +599,9 @@ dependencies = [ [[package]] name = "chacha20poly1305" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48901293601228db2131606f741db33561f7576b5d19c99cd66222380a7dc863" +checksum = "18b0c90556d8e3fec7cf18d84a2f53d27b21288f2fe481b830fadcf809e48205" dependencies = [ "aead", "chacha20", @@ -582,9 +612,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" +checksum = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6" dependencies = [ "js-sys", "num-integer", @@ -708,6 +738,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" +[[package]] +name = "cpuid-bool" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d375c433320f6c5057ae04a04376eef4d04ce2801448cf8863a78da99107be4" + [[package]] name = "cranelift-bforest" version = "0.63.0" @@ -869,10 +905,20 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" dependencies = [ - "generic-array", + "generic-array 0.12.3", "subtle 1.0.0", ] +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array 0.14.2", + "subtle 2.2.3", +] + [[package]] name = "ct-logs" version = "0.6.0" @@ -889,7 +935,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5" dependencies = [ "byteorder", - "digest", + "digest 0.8.1", "rand_core 0.5.1", "subtle 2.2.3", "zeroize", @@ -929,13 +975,13 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.8" +version = "0.99.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc655351f820d774679da6cdc23355a93de496867d8203496675162e17b1d671" +checksum = "298998b1cf6b5b2c8a7b023dfd45821825ce3ba8a8af55c921a0e734e4653f76" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -950,7 +996,16 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ - "generic-array", + "generic-array 0.12.3", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.2", ] [[package]] @@ -971,7 +1026,7 @@ checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" dependencies = [ "libc", "redox_users", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1008,7 +1063,7 @@ dependencies = [ "clear_on_drop", "curve25519-dalek", "rand 0.7.3", - "sha2", + "sha2 0.8.2", ] [[package]] @@ -1054,7 +1109,7 @@ checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -1093,7 +1148,7 @@ checksum = "b480f641ccf0faf324e20c1d3e53d81b7484c698b42ea677f6907ae4db195371" dependencies = [ "errno-dragonfly", "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1160,7 +1215,7 @@ checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", "synstructure", ] @@ -1251,9 +1306,9 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "flate2" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" +checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e" dependencies = [ "cfg-if", "crc32fast", @@ -1385,7 +1440,7 @@ dependencies = [ "frame-support-procedural-tools", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -1397,7 +1452,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -1407,7 +1462,7 @@ source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c67 dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -1458,7 +1513,7 @@ dependencies = [ "lazy_static", "libc", "libloading", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1594,7 +1649,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -1667,7 +1722,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0a73299e4718f5452e45980fc1d6957a070abe308d3700b63b8673f47e1c2b3" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "futures 0.3.5", "memchr", "pin-project", @@ -1679,7 +1734,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce54d63f8b0c75023ed920d46fd71d0cbbb830b0ee012726b5b4f506fb6dea5b" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "futures 0.3.5", "memchr", "pin-project", @@ -1691,6 +1746,19 @@ version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +[[package]] +name = "generator" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add72f17bb81521258fcc8a7a3245b1e184e916bfbe34f0ea89558f440df5c68" +dependencies = [ + "cc", + "libc", + "log 0.4.8", + "rustc_version", + "winapi 0.3.9", +] + [[package]] name = "generic-array" version = "0.12.3" @@ -1700,6 +1768,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "generic-array" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac746a5f3bbfdadd6106868134545e684693d54d9d44f6e9588a7d54af0bf980" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "get_if_addrs" version = "0.5.3" @@ -1736,9 +1814,9 @@ dependencies = [ [[package]] name = "ghash" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f0930ed19a7184089ea46d2fedead2f6dc2b674c5db4276b7da336c7cd83252" +checksum = "d6e27f0689a6e15944bdce7e45425efb87eaa8ab0c6e87f11d0987a9133e2531" dependencies = [ "polyval", ] @@ -1759,9 +1837,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c" +checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" [[package]] name = "glob" @@ -1830,7 +1908,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79b7246d7e4b979c03fa093da39cfb3617a96bbeee6310af63991668d7e843ff" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "fnv", "futures-core", "futures-sink", @@ -1889,9 +1967,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909" +checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9" dependencies = [ "libc", ] @@ -1927,8 +2005,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" dependencies = [ - "crypto-mac", - "digest", + "crypto-mac 0.7.0", + "digest 0.8.1", ] [[package]] @@ -1937,8 +2015,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" dependencies = [ - "digest", - "generic-array", + "digest 0.8.1", + "generic-array 0.12.3", "hmac", ] @@ -1959,7 +2037,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "fnv", "itoa", ] @@ -1982,7 +2060,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "http 0.2.1", ] @@ -2037,7 +2115,7 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6e7655b9594024ad0ee439f3b5a7299369dc2a3f459b47c696f9ff676f9aa1f" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "futures-channel", "futures-core", "futures-util", @@ -2061,12 +2139,12 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac965ea399ec3a25ac7d13b8affd4b8f39325cca00858ddf5eb29b79e6b14b08" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "ct-logs", "futures-util", "hyper 0.13.6", "log 0.4.8", - "rustls", + "rustls 0.17.0", "rustls-native-certs", "tokio 0.2.21", "tokio-rustls", @@ -2130,7 +2208,7 @@ checksum = "7ef5550a42e3740a0e71f909d4c861056a284060af885ae7aa6242820f920d9d" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -2235,9 +2313,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.40" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce10c23ad2ea25ceca0093bd3192229da4c5b3c0f2de499c1ecac0d98d452177" +checksum = "c4b9172132a62451e56142bff9afc91c8e4a4500aa5b847da36815b63bfda916" dependencies = [ "wasm-bindgen", ] @@ -2289,7 +2367,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -2457,9 +2535,9 @@ dependencies = [ [[package]] name = "kv-log-macro" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ff57d6d215f7ca7eb35a9a64d656ba4d9d2bef114d741dc08048e75e2f5d418" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" dependencies = [ "log 0.4.8", ] @@ -2540,15 +2618,15 @@ checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" [[package]] name = "libc" -version = "0.2.71" +version = "0.2.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" +checksum = "a9f8082297d534141b30c8d39e9b1773713ab50fdbe4ff30f750d063b3bfd701" [[package]] name = "libflate" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784f4ec5908a9d7f4e53658906386667e8b02e9389a47cfebf45d324ba9e8d25" +checksum = "e9bac9023e1db29c084f9f8cd9d3852e5e8fddf98fb47c4964a0ea4663d95949" dependencies = [ "adler32", "crc32fast", @@ -2569,7 +2647,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" dependencies = [ "cc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2584,7 +2662,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d743d03fab397cde23925a17cb87b35b25994f44ab8c6a9e46a7e953ec739cd" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "futures 0.3.5", "lazy_static", "libp2p-core", @@ -2635,7 +2713,7 @@ dependencies = [ "rand 0.7.3", "ring", "rw-stream-sink", - "sha2", + "sha2 0.8.2", "smallvec 1.4.1", "thiserror", "unsigned-varint 0.4.0", @@ -2650,7 +2728,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "515c4a7cba5d321bb88ed3ed803997bdd5634ce35c9c5e8e9ace9c512e57eceb" dependencies = [ "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -2687,7 +2765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44ed3a4c8111c570ab2bffb30c6353178d7603ce3787e3c5f2493c8d3d16d1f0" dependencies = [ "arrayvec 0.5.1", - "bytes 0.5.4", + "bytes 0.5.5", "either", "fnv", "futures 0.3.5", @@ -2699,7 +2777,7 @@ dependencies = [ "prost", "prost-build", "rand 0.7.3", - "sha2", + "sha2 0.8.2", "smallvec 1.4.1", "uint", "unsigned-varint 0.4.0", @@ -2735,7 +2813,7 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14ae0ffacd30f073f96cd518b2c9cd2cb18ac27c3d136a4b23cf1af99f33e541" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "fnv", "futures 0.3.5", "futures_codec 0.4.1", @@ -2759,7 +2837,7 @@ dependencies = [ "prost", "prost-build", "rand 0.7.3", - "sha2", + "sha2 0.8.2", "snow", "static_assertions", "x25519-dalek", @@ -2828,9 +2906,9 @@ dependencies = [ [[package]] name = "libp2p-websocket" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd3a13025c0f621647ed2c5147615468e7b3cd1a5c7f26f2a6f6f8eafc9c1950" +checksum = "046a5201f6e471f22b22b394e4d084269ed1e28cf7300f7b49874385db84c7bd" dependencies = [ "async-tls", "either", @@ -2838,7 +2916,7 @@ dependencies = [ "libp2p-core", "log 0.4.8", "quicksink", - "rustls", + "rustls 0.18.0", "rw-stream-sink", "soketto", "url 2.1.1", @@ -2879,10 +2957,10 @@ checksum = "1fc1e2c808481a63dc6da2074752fdd4336a3c8fcc68b83db6f1fd5224ae7962" dependencies = [ "arrayref", "crunchy", - "digest", + "digest 0.8.1", "hmac-drbg", "rand 0.7.3", - "sha2", + "sha2 0.8.2", "subtle 2.2.3", "typenum", ] @@ -2952,6 +3030,17 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "loom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ecc775857611e1df29abba5c41355cdf540e7e9d4acfdf0f355eefee82330b7" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls 0.1.2", +] + [[package]] name = "lru" version = "0.4.3" @@ -3004,14 +3093,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" dependencies = [ "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "memoffset" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" +checksum = "c198b026e1bbf08a937e94c6c60f9ec4a2267f5b0d2eec9c1b21b061ce2be55f" dependencies = [ "autocfg 1.0.0", ] @@ -3056,11 +3145,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.3.7" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" +checksum = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f" dependencies = [ - "adler32", + "adler", ] [[package]] @@ -3096,14 +3185,14 @@ dependencies = [ [[package]] name = "mio-named-pipes" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" +checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656" dependencies = [ "log 0.4.8", "mio", "miow 0.3.5", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -3136,7 +3225,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e" dependencies = [ "socket2", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -3153,9 +3242,9 @@ checksum = "f75db05d738947aa5389863aadafbcf2e509d7ba099dc2ddcdf4fc66bf7a9e03" dependencies = [ "blake2b_simd", "blake2s_simd", - "digest", + "digest 0.8.1", "sha-1", - "sha2", + "sha2 0.8.2", "sha3", "unsigned-varint 0.3.3", ] @@ -3172,7 +3261,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9157e87afbc2ef0d84cc0345423d715f445edde00141c93721c162de35a05e5" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "futures 0.3.5", "log 0.4.8", "pin-project", @@ -3188,7 +3277,7 @@ checksum = "aaa9fddbc34c8c35dd2108515587b8ce0cab396f17977b8c738568e4edb521a2" dependencies = [ "alga", "approx", - "generic-array", + "generic-array 0.12.3", "matrixmultiply", "num-complex", "num-rational", @@ -3214,7 +3303,7 @@ checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" dependencies = [ "cfg-if", "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -3286,7 +3375,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a31937dea023539c72ddae0e3571deadc1414b300483fa7aaec176168cfa9d2" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -3391,6 +3480,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "openssl-probe" version = "0.1.2" @@ -3827,7 +3922,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -4010,11 +4105,11 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a1cd2ba02391b81367bec529fb209019d718684fdc8ad6a712c2b536e46f775" dependencies = [ - "blake2", - "bytes 0.5.4", + "blake2 0.8.1", + "bytes 0.5.5", "rand 0.7.3", "sha-1", - "sha2", + "sha2 0.8.2", "sha3", "unsigned-varint 0.3.3", ] @@ -4041,7 +4136,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -4066,7 +4161,7 @@ dependencies = [ "tokio 0.1.22", "tokio-named-pipes", "tokio-uds", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -4083,7 +4178,7 @@ dependencies = [ "parking_lot 0.10.2", "primitive-types", "smallvec 1.4.1", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -4093,7 +4188,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ "proc-macro2 1.0.18", - "syn 1.0.31", + "syn 1.0.33", "synstructure", ] @@ -4142,7 +4237,7 @@ dependencies = [ "redox_syscall", "rustc_version", "smallvec 0.6.13", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -4156,14 +4251,14 @@ dependencies = [ "libc", "redox_syscall", "smallvec 1.4.1", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "paste" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "026c63fe245362be0322bfec5a9656d458d13f9cfb1785d1b38458b9968e8080" +checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" dependencies = [ "paste-impl", "proc-macro-hack", @@ -4171,9 +4266,9 @@ dependencies = [ [[package]] name = "paste-impl" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b9281a268ec213237dcd2aa3c3d0f46681b04ced37c1616fd36567a9e6954b0" +checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" dependencies = [ "proc-macro-hack", ] @@ -4185,7 +4280,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" dependencies = [ "byteorder", - "crypto-mac", + "crypto-mac 0.7.0", ] [[package]] @@ -4239,7 +4334,7 @@ checksum = "6a0ffd45cf79d88737d7cc85bfd5d2894bee1139b356e616fe85dc389c61aaf7" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -4290,7 +4385,7 @@ dependencies = [ name = "polkadot-availability-store" version = "0.8.14" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "exit-future", "futures 0.3.5", "kvdb", @@ -4392,7 +4487,7 @@ name = "polkadot-network" version = "0.8.14" dependencies = [ "arrayvec 0.4.12", - "bytes 0.5.4", + "bytes 0.5.5", "derive_more 0.14.1", "exit-future", "futures 0.3.5", @@ -4456,6 +4551,31 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "polkadot-node-core-backing" +version = "0.1.0" +dependencies = [ + "assert_matches", + "bitvec", + "derive_more 0.99.9", + "futures 0.3.5", + "futures-timer 3.0.2", + "log 0.4.8", + "polkadot-erasure-coding", + "polkadot-node-primitives", + "polkadot-node-subsystem", + "polkadot-primitives", + "polkadot-statement-table", + "polkadot-subsystem-test-helpers", + "sc-client-api", + "sc-keystore", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-keyring", + "streamunordered", +] + [[package]] name = "polkadot-node-core-proposer" version = "0.1.0" @@ -4525,7 +4645,7 @@ dependencies = [ name = "polkadot-parachain" version = "0.8.14" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "log 0.4.8", "parity-scale-codec", "parking_lot 0.10.2", @@ -5103,18 +5223,18 @@ dependencies = [ [[package]] name = "poly1305" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5829f50f48e9ddb79f3f7c3097029d0caee30f8286accb241416df603b080b8" +checksum = "d9b42192ab143ed7619bf888a7f9c6733a9a2153b218e2cd557cfdb52fbf9bb1" dependencies = [ "universal-hash", ] [[package]] name = "polyval" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ec3341498978de3bfd12d1b22f1af1de22818f5473a11e8a6ef997989e3a212" +checksum = "d9a50142b55ab3ed0e9f68dfb3709f1d90d29da24e91033f28b96330643107dc" dependencies = [ "cfg-if", "universal-hash", @@ -5185,26 +5305,26 @@ dependencies = [ [[package]] name = "proc-macro-error" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" +checksum = "fc175e9777c3116627248584e8f8b3e2987405cabe1c0adf7d1dd28f09dc7880" dependencies = [ "proc-macro-error-attr", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", "version_check", ] [[package]] name = "proc-macro-error-attr" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" +checksum = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", "syn-mid", "version_check", ] @@ -5236,7 +5356,7 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" dependencies = [ - "unicode-xid 0.2.0", + "unicode-xid 0.2.1", ] [[package]] @@ -5274,7 +5394,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce49aefe0a6144a45de32927c77bd2859a5f7677b55f220ae5b744e87389c212" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "prost-derive", ] @@ -5284,7 +5404,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02b10678c913ecbd69350e8535c3aef91a8676c0773fc1d7b95cdd196d7f2f26" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "heck", "itertools 0.8.2", "log 0.4.8", @@ -5306,7 +5426,7 @@ dependencies = [ "itertools 0.8.2", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -5315,15 +5435,15 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1834f67c0697c001304b75be76f67add9c89742eda3a085ad8ee0bb38c3417aa" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "prost", ] [[package]] name = "protobuf" -version = "2.14.0" +version = "2.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e86d370532557ae7573551a1ec8235a0f8d6cb276c7c9e6aa490b511c447485" +checksum = "d883f78645c21b7281d21305181aa1f4dd9e9363e7cf2566c93121552cff003e" [[package]] name = "quick-error" @@ -5392,7 +5512,7 @@ dependencies = [ "libc", "rand_core 0.3.1", "rdrand", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -5405,7 +5525,7 @@ dependencies = [ "fuchsia-cprng", "libc", "rand_core 0.3.1", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -5424,7 +5544,7 @@ dependencies = [ "rand_os", "rand_pcg 0.1.2", "rand_xorshift", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -5520,7 +5640,7 @@ checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" dependencies = [ "libc", "rand_core 0.4.2", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -5535,7 +5655,7 @@ dependencies = [ "rand_core 0.4.2", "rdrand", "wasm-bindgen", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -5660,7 +5780,7 @@ checksum = "7d21b475ab879ef0e315ad99067fa25778c3b0377f57f1b00207448dac1a3144" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -5701,7 +5821,7 @@ dependencies = [ "bitflags", "libc", "mach", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -5710,7 +5830,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -5731,7 +5851,7 @@ checksum = "475e68978dc5b743f2f40d8e0a8fdc83f1c5e78cbf4b8fa5e74e73beebc340de" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -5746,7 +5866,7 @@ dependencies = [ "spin", "untrusted", "web-sys", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -5772,7 +5892,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99371657d3c8e4d816fb6221db98fa408242b0b53bac08f8676a41f8554fe99f" dependencies = [ "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -5833,6 +5953,19 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cac94b333ee2aac3284c5b8a1b7fb4dd11cba88c244e3fe33cdbd047af0eb693" +dependencies = [ + "base64 0.12.3", + "log 0.4.8", + "ring", + "sct", + "webpki", +] + [[package]] name = "rustls-native-certs" version = "0.3.0" @@ -5840,7 +5973,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75ffeb84a6bd9d014713119542ce415db3a3e4748f0bfce1e1416cd224a23a5" dependencies = [ "openssl-probe", - "rustls", + "rustls 0.17.0", "schannel", "security-framework", ] @@ -5876,8 +6009,8 @@ name = "sc-authority-discovery" version = "0.8.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "bytes 0.5.4", - "derive_more 0.99.8", + "bytes 0.5.5", + "derive_more 0.99.9", "futures 0.3.5", "futures-timer 3.0.2", "libp2p", @@ -5963,7 +6096,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -5974,7 +6107,7 @@ dependencies = [ "ansi_term 0.12.1", "atty", "chrono", - "derive_more 0.99.8", + "derive_more 0.99.9", "fdlimit", "flexi_logger", "futures 0.3.5", @@ -6012,7 +6145,7 @@ name = "sc-client-api" version = "2.0.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "fnv", "futures 0.3.5", "hash-db", @@ -6088,7 +6221,7 @@ name = "sc-consensus-babe" version = "0.8.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "fork-tree", "futures 0.3.5", "futures-timer 3.0.2", @@ -6130,7 +6263,7 @@ name = "sc-consensus-babe-rpc" version = "0.8.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "futures 0.3.5", "jsonrpc-core", "jsonrpc-core-client", @@ -6204,7 +6337,7 @@ name = "sc-executor" version = "0.8.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "lazy_static", "libsecp256k1", "log 0.4.8", @@ -6232,7 +6365,7 @@ name = "sc-executor-common" version = "0.8.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "log 0.4.8", "parity-scale-codec", "parity-wasm", @@ -6270,7 +6403,7 @@ dependencies = [ "parity-scale-codec", "parity-wasm", "sc-executor-common", - "scoped-tls", + "scoped-tls 1.0.0", "sp-allocator", "sp-core", "sp-runtime-interface", @@ -6286,7 +6419,7 @@ version = "0.8.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ "assert_matches", - "derive_more 0.99.8", + "derive_more 0.99.9", "finality-grandpa", "fork-tree", "futures 0.3.5", @@ -6323,7 +6456,7 @@ name = "sc-finality-grandpa-rpc" version = "0.8.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "finality-grandpa", "futures 0.3.5", "jsonrpc-core", @@ -6358,7 +6491,7 @@ name = "sc-keystore" version = "2.0.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "hex", "merlin", "parking_lot 0.10.2", @@ -6395,8 +6528,8 @@ source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c67 dependencies = [ "bitflags", "bs58", - "bytes 0.5.4", - "derive_more 0.99.8", + "bytes 0.5.5", + "derive_more 0.99.9", "either", "erased-serde", "fnv", @@ -6487,7 +6620,7 @@ name = "sc-offchain" version = "2.0.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "fnv", "futures 0.3.5", "futures-timer 3.0.2", @@ -6568,7 +6701,7 @@ name = "sc-rpc-api" version = "0.8.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "futures 0.3.5", "jsonrpc-core", "jsonrpc-core-client", @@ -6608,7 +6741,7 @@ name = "sc-service" version = "0.8.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "directories", "exit-future", "futures 0.1.29", @@ -6723,7 +6856,7 @@ name = "sc-transaction-graph" version = "2.0.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "futures 0.3.5", "linked-hash-map", "log 0.4.8", @@ -6743,7 +6876,7 @@ name = "sc-transaction-pool" version = "2.0.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "futures 0.3.5", "futures-diagnose", "intervalier", @@ -6771,7 +6904,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ "lazy_static", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -6787,11 +6920,17 @@ dependencies = [ "merlin", "rand 0.7.3", "rand_core 0.5.1", - "sha2", + "sha2 0.8.2", "subtle 2.2.3", "zeroize", ] +[[package]] +name = "scoped-tls" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" + [[package]] name = "scoped-tls" version = "1.0.0" @@ -6821,7 +6960,7 @@ checksum = "e367622f934864ffa1c704ba2b82280aab856e3d8213c84c5720257eb34b15b9" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -6901,29 +7040,29 @@ checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" [[package]] name = "serde" -version = "1.0.112" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736aac72d1eafe8e5962d1d1c3d99b0df526015ba40915cb3c49d042e92ec243" +checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.112" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf0343ce212ac0d3d6afd9391ac8e9c9efe06b533c8d33f660f6390cc4093f57" +checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] name = "serde_json" -version = "1.0.55" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2c5d7e739bc07a3e73381a39d61fdb5f671c60c1df26a130690665803d8226" +checksum = "3433e879a558dde8b5e8feb2a04899cf34fdde1fafb894687e52105fc1162ac3" dependencies = [ "itoa", "ryu", @@ -6936,10 +7075,10 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" dependencies = [ - "block-buffer", - "digest", + "block-buffer 0.7.3", + "digest 0.8.1", "fake-simd", - "opaque-debug", + "opaque-debug 0.2.3", ] [[package]] @@ -6948,10 +7087,23 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ - "block-buffer", - "digest", + "block-buffer 0.7.3", + "digest 0.8.1", "fake-simd", - "opaque-debug", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha2" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpuid-bool", + "digest 0.9.0", + "opaque-debug 0.3.0", ] [[package]] @@ -6960,11 +7112,11 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" dependencies = [ - "block-buffer", + "block-buffer 0.7.3", "byte-tools", - "digest", + "digest 0.8.1", "keccak", - "opaque-debug", + "opaque-debug 0.2.3", ] [[package]] @@ -6983,7 +7135,7 @@ dependencies = [ "rand 0.4.6", "shared_memory_derive", "theban_interval_tree", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -7060,7 +7212,7 @@ checksum = "a945ec7f7ce853e89ffa36be1e27dce9a43e82ff9093bf3461c30d5da74ed11b" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -7092,27 +7244,27 @@ dependencies = [ "futures-util", "libc", "once_cell", - "scoped-tls", + "scoped-tls 1.0.0", "slab", "socket2", "wepoll-sys-stjepang", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "snow" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce0f91be479494dd92e69d9971bd23ed27037dd1c94fcf558f6c6e74e6afa654" +checksum = "32bf8474159a95551661246cda4976e89356999e3cbfef36f493dacc3fae1e8e" dependencies = [ "aes-gcm", - "blake2", + "blake2 0.9.0", "chacha20poly1305", "rand 0.7.3", "rand_core 0.5.1", "ring", "rustc_version", - "sha2", + "sha2 0.9.1", "subtle 2.2.3", "x25519-dalek", ] @@ -7126,7 +7278,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -7135,8 +7287,8 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85457366ae0c6ce56bf05a958aef14cd38513c236568618edbcd9a8c52cb80b0" dependencies = [ - "base64 0.12.2", - "bytes 0.5.4", + "base64 0.12.3", + "bytes 0.5.5", "flate2", "futures 0.3.5", "httparse", @@ -7150,7 +7302,7 @@ name = "sp-allocator" version = "2.0.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "log 0.4.8", "sp-core", "sp-std", @@ -7181,7 +7333,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -7249,7 +7401,7 @@ name = "sp-blockchain" version = "2.0.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "log 0.4.8", "lru", "parity-scale-codec", @@ -7275,7 +7427,7 @@ name = "sp-consensus" version = "0.8.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "futures 0.3.5", "futures-timer 3.0.2", "libp2p", @@ -7357,7 +7509,7 @@ dependencies = [ "base58", "blake2-rfc", "byteorder", - "derive_more 0.99.8", + "derive_more 0.99.9", "ed25519-dalek", "futures 0.3.5", "hash-db", @@ -7378,7 +7530,7 @@ dependencies = [ "schnorrkel", "secrecy", "serde", - "sha2", + "sha2 0.8.2", "sp-debug-derive", "sp-externalities", "sp-runtime-interface", @@ -7408,7 +7560,7 @@ source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c67 dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -7453,7 +7605,7 @@ name = "sp-inherents" version = "2.0.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "parity-scale-codec", "parking_lot 0.10.2", "sp-core", @@ -7512,7 +7664,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -7589,7 +7741,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -7691,7 +7843,7 @@ name = "sp-transaction-pool" version = "2.0.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ - "derive_more 0.99.8", + "derive_more 0.99.9", "futures 0.3.5", "log 0.4.8", "parity-scale-codec", @@ -7780,11 +7932,11 @@ dependencies = [ [[package]] name = "stream-cipher" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c" +checksum = "09f8ed9974042b8c3672ff3030a69fcc03b74c47c3d1ecb7755e8a3626011e88" dependencies = [ - "generic-array", + "generic-array 0.14.2", ] [[package]] @@ -7844,7 +7996,7 @@ dependencies = [ "proc-macro-error", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -7865,7 +8017,7 @@ dependencies = [ "heck", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -7877,7 +8029,7 @@ dependencies = [ "hmac", "pbkdf2", "schnorrkel", - "sha2", + "sha2 0.8.2", ] [[package]] @@ -7944,7 +8096,7 @@ version = "0.8.0-rc4" source = "git+https://github.com/paritytech/substrate#06dedb0eb77abb7f64832b5c675ee4c00e40d730" dependencies = [ "async-std", - "derive_more 0.99.8", + "derive_more 0.99.9", "futures-util", "hyper 0.13.6", "log 0.4.8", @@ -8070,7 +8222,7 @@ dependencies = [ "wasmparser 0.52.2", "wasmtime-environ", "wat", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -8097,7 +8249,7 @@ dependencies = [ "wasmparser 0.52.2", "wasmtime-debug", "wasmtime-environ", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -8136,7 +8288,7 @@ dependencies = [ "region", "thiserror", "wasmtime-environ", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -8175,13 +8327,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6" +checksum = "e8d5d96e8cbb005d6959f119f773bfaebb5684296108fb32600c00cde305b2cd" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "unicode-xid 0.2.0", + "unicode-xid 0.2.1", ] [[package]] @@ -8192,7 +8344,7 @@ checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -8212,8 +8364,8 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", - "unicode-xid 0.2.0", + "syn 1.0.33", + "unicode-xid 0.2.1", ] [[package]] @@ -8228,7 +8380,7 @@ dependencies = [ "ntapi", "once_cell", "rayon", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -8254,7 +8406,7 @@ dependencies = [ "rand 0.7.3", "redox_syscall", "remove_dir_all", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -8363,7 +8515,7 @@ checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -8391,7 +8543,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -8406,7 +8558,7 @@ dependencies = [ "pbkdf2", "rand 0.7.3", "rustc-hash", - "sha2", + "sha2 0.8.2", "unicode-normalization", ] @@ -8464,7 +8616,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d099fa27b9702bed751524694adbe393e18b36b204da91eb1cbbbbb4a5ee2d58" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "fnv", "futures-core", "iovec", @@ -8478,7 +8630,7 @@ dependencies = [ "signal-hook-registry", "slab", "tokio-macros", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -8564,7 +8716,7 @@ checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] @@ -8606,7 +8758,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15cb62a0d2770787abc96e99c1cd98fcf17f94959f3af63ca85bdfb203f051b4" dependencies = [ "futures-core", - "rustls", + "rustls 0.17.0", "tokio 0.2.21", "webpki", ] @@ -8701,9 +8853,9 @@ dependencies = [ [[package]] name = "tokio-uds" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" +checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" dependencies = [ "bytes 0.4.12", "futures 0.1.29", @@ -8723,7 +8875,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "futures-core", "futures-sink", "log 0.4.8", @@ -8748,9 +8900,9 @@ checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" [[package]] name = "tracing" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41f40ed0e162c911ac6fcb53ecdc8134c46905fdbbae8c50add462a538b495f" +checksum = "c2e2a2de6b0d5cbb13fc21193a2296888eaab62b6044479aafb3c54c01c29fcd" dependencies = [ "cfg-if", "tracing-attributes", @@ -8759,20 +8911,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99bbad0de3fd923c9c3232ead88510b783e5a4d16a6154adffa3d53308de984c" +checksum = "f0693bf8d6f2bf22c690fc61a9d21ac69efdbb894a17ed596b9af0f01e64b84b" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", ] [[package]] name = "tracing-core" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa83a9a47081cd522c09c81b31aec2c9273424976f922ad61c053b58350b715" +checksum = "94ae75f0d28ae10786f3b1895c55fe72e79928fd5ccdebb5438c75e93fec178f" dependencies = [ "lazy_static", ] @@ -8873,9 +9025,9 @@ checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" [[package]] name = "unicode-width" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" [[package]] name = "unicode-xid" @@ -8891,17 +9043,17 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "universal-hash" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0c900f2f9b4116803415878ff48b63da9edb268668e08cf9292d7503114a01" +checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" dependencies = [ - "generic-array", + "generic-array 0.14.2", "subtle 2.2.3", ] @@ -8911,7 +9063,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f67332660eb59a6f1eb24ff1220c9e8d01738a8503c6002e30bcfe4bd9f2b4a9" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "futures-io", "futures-util", "futures_codec 0.3.4", @@ -8923,7 +9075,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "669d776983b692a906c881fcd0cfb34271a48e197e4d6cb8df32b05bfc3d3fa5" dependencies = [ - "bytes 0.5.4", + "bytes 0.5.5", "futures_codec 0.4.1", ] @@ -9023,9 +9175,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" -version = "0.2.63" +version = "0.2.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2dc4aa152834bc334f506c1a06b866416a8b6697d5c9f75b9a689c8486def0" +checksum = "6a634620115e4a229108b71bde263bb4220c483b3f07f5ba514ee8d15064c4c2" dependencies = [ "cfg-if", "serde", @@ -9035,24 +9187,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.63" +version = "0.2.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded84f06e0ed21499f6184df0e0cb3494727b0c5da89534e0fcc55c51d812101" +checksum = "3e53963b583d18a5aa3aaae4b4c1cb535218246131ba22a71f05b518098571df" dependencies = [ "bumpalo", "lazy_static", "log 0.4.8", "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64487204d863f109eb77e8462189d111f27cb5712cc9fdb3461297a76963a2f6" +checksum = "dba48d66049d2a6cc8488702e7259ab7afc9043ad0dc5448444f46f2a453b362" dependencies = [ "cfg-if", "js-sys", @@ -9062,9 +9214,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.63" +version = "0.2.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "838e423688dac18d73e31edce74ddfac468e37b1506ad163ffaf0a46f703ffe3" +checksum = "3fcfd5ef6eec85623b4c6e844293d4516470d8f19cd72d0d12246017eb9060b8" dependencies = [ "quote 1.0.7", "wasm-bindgen-macro-support", @@ -9072,22 +9224,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.63" +version = "0.2.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92" +checksum = "9adff9ee0e94b926ca81b57f57f86d5545cdcb1d259e21ec9bdd95b901754c75" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.63" +version = "0.2.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9ba19973a58daf4db6f352eda73dc0e289493cd29fb2632eb172085b6521acd" +checksum = "7f7b90ea6c632dd06fd765d44542e234d5e63d9bb917ecd64d79778a13bd79ae" [[package]] name = "wasm-timer" @@ -9163,7 +9315,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed54fd9d64dfeeee7c285fd126174a6b5e6d4efc7e5a1566fdb635e60ff6a74e" dependencies = [ "anyhow", - "base64 0.12.2", + "base64 0.12.3", "bincode", "cranelift-codegen", "cranelift-entity", @@ -9177,37 +9329,37 @@ dependencies = [ "more-asserts", "rayon", "serde", - "sha2", + "sha2 0.8.2", "thiserror", "toml", "wasmparser 0.51.4", - "winapi 0.3.8", + "winapi 0.3.9", "zstd", ] [[package]] name = "wast" -version = "18.0.0" +version = "21.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b1f23531740a81f9300bd2febd397a95c76bfa4aa4bfaf4ca8b1ee3438f337" +checksum = "0b1844f66a2bc8526d71690104c0e78a8e59ffa1597b7245769d174ebb91deb5" dependencies = [ "leb128", ] [[package]] name = "wat" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4006d418d59293172aebfeeadb7673459dc151874a79135946ea7996b6a98515" +checksum = "ce85d72b74242c340e9e3492cfb602652d7bb324c3172dd441b5577e39a2e18c" dependencies = [ "wast", ] [[package]] name = "web-sys" -version = "0.3.40" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b72fe77fd39e4bd3eaa4412fd299a0be6b3dfe9d2597e2f1c20beb968f41d17" +checksum = "863539788676619aac1a23e2df3655e96b32b0e05eb72ca34ba045ad573c625d" dependencies = [ "js-sys", "wasm-bindgen", @@ -9344,9 +9496,9 @@ checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", @@ -9370,7 +9522,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -9420,9 +9572,9 @@ dependencies = [ [[package]] name = "yamux" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84300bb493cc878f3638b981c62b4632ec1a5c52daaa3036651e8c106d3b55ea" +checksum = "cd37e58a1256a0b328ce9c67d8b62ecdd02f4803ba443df478835cb1a41a637c" dependencies = [ "futures 0.3.5", "log 0.4.8", @@ -9455,7 +9607,7 @@ checksum = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2" dependencies = [ "proc-macro2 1.0.18", "quote 1.0.7", - "syn 1.0.31", + "syn 1.0.33", "synstructure", ] diff --git a/Cargo.toml b/Cargo.toml index fe5bbcf2f9bd..b6d1aa53eaa2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ members = [ "node/overseer", "node/primitives", "node/service", + "node/core/backing", "node/subsystem", "node/test-helpers/subsystem", "node/test-service", diff --git a/node/core/backing/Cargo.toml b/node/core/backing/Cargo.toml new file mode 100644 index 000000000000..b25055293add --- /dev/null +++ b/node/core/backing/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "polkadot-node-core-backing" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +futures = "0.3.5" +log = "0.4.8" +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" } +keystore = { package = "sc-keystore", git = "https://github.com/paritytech/substrate", branch = "master" } +primitives = { package = "sp-core", git = "https://github.com/paritytech/substrate", branch = "master" } + +polkadot-primitives = { path = "../../../primitives" } +polkadot-node-primitives = { path = "../../primitives" } +polkadot-subsystem = { package = "polkadot-node-subsystem", path = "../../subsystem" } +erasure-coding = { package = "polkadot-erasure-coding", path = "../../../erasure-coding" } +statement-table = { package = "polkadot-statement-table", path = "../../../statement-table" } +futures-timer = "3.0.2" +streamunordered = "0.5.1" +derive_more = "0.99.9" +bitvec = { version = "0.17.4", default-features = false, features = ["alloc"] } + +[dev-dependencies] +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +futures = { version = "0.3.5", features = ["thread-pool"] } +subsystem-test = { package = "polkadot-subsystem-test-helpers", path = "../../test-helpers/subsystem" } +assert_matches = "1.3.0" diff --git a/node/core/backing/src/lib.rs b/node/core/backing/src/lib.rs new file mode 100644 index 000000000000..e4490d20d3f1 --- /dev/null +++ b/node/core/backing/src/lib.rs @@ -0,0 +1,1729 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Implements a `CandidateBackingSubsystem`. + +#![recursion_limit="256"] + +use std::collections::{HashMap, HashSet}; +use std::convert::TryFrom; +use std::pin::Pin; +use std::time::Duration; + +use bitvec::vec::BitVec; +use log; +use futures::{ + select, FutureExt, SinkExt, StreamExt, + channel::{oneshot, mpsc}, + future::{self, Either}, + task::{Spawn, SpawnError, SpawnExt}, +}; +use futures_timer::Delay; +use streamunordered::{StreamUnordered, StreamYield}; + +use primitives::Pair; +use keystore::KeyStorePtr; +use polkadot_primitives::{ + Hash, + parachain::{ + AbridgedCandidateReceipt, BackedCandidate, Id as ParaId, ValidatorPair, ValidatorId, + ValidatorIndex, HeadData, SigningContext, PoVBlock, OmittedValidationData, + CandidateDescriptor, LocalValidationData, GlobalValidationSchedule, AvailableData, + ErasureChunk, + }, +}; +use polkadot_node_primitives::{ + FromTableMisbehavior, Statement, SignedFullStatement, MisbehaviorReport, ValidationResult, +}; +use polkadot_subsystem::{ + FromOverseer, OverseerSignal, Subsystem, SubsystemContext, SpawnedSubsystem, +}; +use polkadot_subsystem::messages::{ + AllMessages, CandidateBackingMessage, CandidateSelectionMessage, SchedulerRoster, + RuntimeApiMessage, RuntimeApiRequest, CandidateValidationMessage, ValidationFailed, + StatementDistributionMessage, NewBackedCandidate, ProvisionerMessage, ProvisionableData, + PoVDistributionMessage, AvailabilityStoreMessage, +}; +use statement_table::{ + generic::AttestedCandidate as TableAttestedCandidate, + Table, Context as TableContextTrait, Statement as TableStatement, + SignedStatement as TableSignedStatement, Summary as TableSummary, +}; + +#[derive(Debug, derive_more::From)] +enum Error { + NotInValidatorSet, + CandidateNotFound, + JobNotFound(Hash), + InvalidSignature, + #[from] + Erasure(erasure_coding::Error), + #[from] + ValidationFailed(ValidationFailed), + #[from] + Oneshot(oneshot::Canceled), + #[from] + Mpsc(mpsc::SendError), + #[from] + Spawn(SpawnError), +} + +/// Holds all data needed for candidate backing job operation. +struct CandidateBackingJob { + /// The hash of the relay parent on top of which this job is doing it's work. + parent: Hash, + /// Inbound message channel receiving part. + rx_to: mpsc::Receiver, + /// Outbound message channel sending part. + tx_from: mpsc::Sender, + + /// `HeadData`s of the parachains that this validator is assigned to. + head_data: HeadData, + /// The `ParaId`s assigned to this validator. + assignment: ParaId, + /// We issued `Valid` or `Invalid` statements on about these candidates. + issued_statements: HashSet, + /// `Some(h)` if this job has already issues `Seconded` statemt for some candidate with `h` hash. + seconded: Option, + /// We have already reported misbehaviors for these validators. + reported_misbehavior_for: HashSet, + + table: Table, + table_context: TableContext, +} + +const fn group_quorum(n_validators: usize) -> usize { + (n_validators / 2) + 1 +} + +#[derive(Default)] +struct TableContext { + signing_context: SigningContext, + key: Option, + groups: HashMap>, + validators: Vec, +} + +impl TableContextTrait for TableContext { + fn is_member_of(&self, authority: ValidatorIndex, group: &ParaId) -> bool { + self.groups.get(group).map_or(false, |g| g.iter().position(|&a| a == authority).is_some()) + } + + fn requisite_votes(&self, group: &ParaId) -> usize { + self.groups.get(group).map_or(usize::max_value(), |g| group_quorum(g.len())) + } +} + +impl TableContext { + fn local_id(&self) -> Option { + self.key.as_ref().map(|k| k.public()) + } + + fn local_index(&self) -> Option { + self.local_id().and_then(|id| + self.validators + .iter() + .enumerate() + .find(|(_, k)| k == &&id) + .map(|(i, _)| i as ValidatorIndex) + ) + } +} + +const CHANNEL_CAPACITY: usize = 64; + +/// A message type that is sent from `CandidateBackingSubsystem` to `CandidateBackingJob`. +enum ToJob { + /// A `CandidateBackingMessage`. + CandidateBacking(CandidateBackingMessage), + /// Stop working. + Stop, +} + +/// A message type that is sent from `CandidateBackingJob` to `CandidateBackingSubsystem`. +enum FromJob { + AvailabilityStore(AvailabilityStoreMessage), + RuntimeApiMessage(RuntimeApiMessage), + CandidateValidation(CandidateValidationMessage), + CandidateSelection(CandidateSelectionMessage), + Provisioner(ProvisionerMessage), + PoVDistribution(PoVDistributionMessage), + StatementDistribution(StatementDistributionMessage), +} + +impl From for AllMessages { + fn from(f: FromJob) -> Self { + match f { + FromJob::AvailabilityStore(msg) => AllMessages::AvailabilityStore(msg), + FromJob::RuntimeApiMessage(msg) => AllMessages::RuntimeApi(msg), + FromJob::CandidateValidation(msg) => AllMessages::CandidateValidation(msg), + FromJob::CandidateSelection(msg) => AllMessages::CandidateSelection(msg), + FromJob::StatementDistribution(msg) => AllMessages::StatementDistribution(msg), + FromJob::PoVDistribution(msg) => AllMessages::PoVDistribution(msg), + FromJob::Provisioner(msg) => AllMessages::Provisioner(msg), + } + } +} + +// It looks like it's not possible to do an `impl From` given the current state of +// the code. So this does the necessary conversion. +fn primitive_statement_to_table(s: &SignedFullStatement) -> TableSignedStatement { + let statement = match s.payload() { + Statement::Seconded(c) => TableStatement::Candidate(c.clone()), + Statement::Valid(h) => TableStatement::Valid(h.clone()), + Statement::Invalid(h) => TableStatement::Invalid(h.clone()), + }; + + TableSignedStatement { + statement, + signature: s.signature().clone(), + sender: s.validator_index(), + } +} + +// finds the first key we are capable of signing with out of the given set of validators, +// if any. +fn signing_key(validators: &[ValidatorId], keystore: &KeyStorePtr) -> Option { + let keystore = keystore.read(); + validators.iter() + .find_map(|v| { + keystore.key_pair::(&v).ok() + }) +} + +impl CandidateBackingJob { + /// Run asynchronously. + async fn run(mut self) -> Result<(), Error> { + while let Some(msg) = self.rx_to.next().await { + match msg { + ToJob::CandidateBacking(msg) => { + self.process_msg(msg).await?; + } + _ => break, + } + } + + Ok(()) + } + + async fn issue_candidate_invalid_message( + &mut self, + candidate: AbridgedCandidateReceipt, + ) -> Result<(), Error> { + self.tx_from.send(FromJob::CandidateSelection( + CandidateSelectionMessage::Invalid(self.parent, candidate) + )).await?; + + Ok(()) + } + + /// Validate the candidate that is requested to be `Second`ed and distribute validation result. + async fn validate_and_second( + &mut self, + candidate: AbridgedCandidateReceipt, + pov: PoVBlock, + ) -> Result { + let valid = self.request_candidate_validation(candidate.clone(), pov.clone()).await?; + let statement = match valid.0 { + ValidationResult::Valid => { + // make PoV available for later distribution. Send data to the availability + // store to keep. Sign and dispatch `valid` statement to network if we + // have not seconded the given candidate. + self.make_pov_available(pov, valid.1, valid.2).await?; + self.issued_statements.insert(candidate.hash()); + Statement::Seconded(candidate) + } + ValidationResult::Invalid => { + let candidate_hash = candidate.hash(); + self.issue_candidate_invalid_message(candidate).await?; + Statement::Invalid(candidate_hash) + } + }; + + if let Some(signed_statement) = self.sign_statement(statement) { + self.import_statement(&signed_statement).await?; + self.distribute_signed_statement(signed_statement).await?; + } + + Ok(valid.0) + } + + fn get_backed(&self) -> Vec { + let proposed = self.table.proposed_candidates(&self.table_context); + let mut res = Vec::with_capacity(proposed.len()); + + for p in proposed.into_iter() { + let TableAttestedCandidate { candidate, validity_votes, .. } = p; + + let (ids, validity_votes): (Vec<_>, Vec<_>) = validity_votes + .into_iter() + .map(|(id, vote)| (id, vote.into())) + .unzip(); + + let group = match self.table_context.groups.get(&self.assignment) { + Some(group) => group, + None => continue, + }; + + let mut validator_indices = BitVec::with_capacity( + group.len() + ); + + validator_indices.resize(group.len(), false); + + for id in ids.iter() { + if let Some(position) = group.iter().position(|x| x == id) { + validator_indices.set(position, true); + } + } + + let backed = BackedCandidate { + candidate, + validity_votes, + validator_indices, + }; + + res.push(NewBackedCandidate(backed.clone())); + } + + res + } + + /// Check if there have happened any new misbehaviors and issue necessary messages. + /// + /// TODO: Report multiple misbehaviors (https://github.com/paritytech/polkadot/issues/1387) + async fn issue_new_misbehaviors(&mut self) -> Result<(), Error> { + let mut reports = Vec::new(); + + for (k, v) in self.table.get_misbehavior().iter() { + if !self.reported_misbehavior_for.contains(k) { + self.reported_misbehavior_for.insert(*k); + + let f = FromTableMisbehavior { + id: *k, + report: v.clone(), + signing_context: self.table_context.signing_context.clone(), + key: self.table_context.validators[*k as usize].clone(), + }; + + if let Ok(report) = MisbehaviorReport::try_from(f) { + let message = ProvisionerMessage::ProvisionableData( + ProvisionableData::MisbehaviorReport(self.parent, report) + ); + + reports.push(message); + } + } + } + + for report in reports.drain(..) { + self.send_to_provisioner(report).await? + } + + Ok(()) + } + + /// Import a statement into the statement table and return the summary of the import. + async fn import_statement( + &mut self, + statement: &SignedFullStatement, + ) -> Result, Error> { + let stmt = primitive_statement_to_table(statement); + + let summary = self.table.import_statement(&self.table_context, stmt); + + self.issue_new_misbehaviors().await?; + + return Ok(summary); + } + + async fn process_msg(&mut self, msg: CandidateBackingMessage) -> Result<(), Error> { + match msg { + CandidateBackingMessage::Second(_, candidate, pov) => { + // Sanity check that candidate is from our assignment. + if candidate.parachain_index != self.assignment { + return Ok(()); + } + + // If the message is a `CandidateBackingMessage::Second`, sign and dispatch a + // Seconded statement only if we have not seconded any other candidate and + // have not signed a Valid statement for the requested candidate. + match self.seconded { + // This job has not seconded a candidate yet. + None => { + let candidate_hash = candidate.hash(); + + if !self.issued_statements.contains(&candidate_hash) { + if let Ok(ValidationResult::Valid) = self.validate_and_second( + candidate, + pov, + ).await { + self.seconded = Some(candidate_hash); + } + } + } + // This job has already seconded a candidate. + Some(_) => {} + } + } + CandidateBackingMessage::Statement(_, statement) => { + self.check_statement_signature(&statement)?; + self.maybe_validate_and_import(statement).await?; + } + CandidateBackingMessage::GetBackedCandidates(_, tx) => { + let backed = self.get_backed(); + + tx.send(backed).map_err(|_| oneshot::Canceled)?; + } + } + + Ok(()) + } + + /// Kick off validation work and distribute the result as a signed statement. + async fn kick_off_validation_work( + &mut self, + summary: TableSummary, + ) -> Result { + let candidate = self.table.get_candidate(&summary.candidate).ok_or(Error::CandidateNotFound)?; + let candidate = candidate.clone(); + let descriptor = candidate.to_descriptor(); + let candidate_hash = candidate.hash(); + let pov = self.request_pov_from_distribution(descriptor).await?; + let v = self.request_candidate_validation(candidate, pov).await?; + + let statement = match v.0 { + ValidationResult::Valid => { + Statement::Valid(candidate_hash) + } + ValidationResult::Invalid => { + Statement::Invalid(candidate_hash) + } + }; + + self.issued_statements.insert(candidate_hash); + + if let Some(signed_statement) = self.sign_statement(statement) { + self.distribute_signed_statement(signed_statement).await?; + } + + Ok(v.0) + } + + /// Import the statement and kick off validation work if it is a part of our assignment. + async fn maybe_validate_and_import( + &mut self, + statement: SignedFullStatement, + ) -> Result<(), Error> { + if let Some(summary) = self.import_statement(&statement).await? { + if let Statement::Seconded(_) = statement.payload() { + if summary.group_id == self.assignment { + self.kick_off_validation_work(summary).await?; + } + } + } + + Ok(()) + } + + fn sign_statement(&self, statement: Statement) -> Option { + let local_index = self.table_context.local_index()?; + + let signing_key = self.table_context.key.as_ref()?; + + let signed_statement = SignedFullStatement::sign( + statement, + &self.table_context.signing_context, + local_index, + signing_key, + ); + + Some(signed_statement) + } + + fn check_statement_signature(&self, statement: &SignedFullStatement) -> Result<(), Error> { + let idx = statement.validator_index() as usize; + + if self.table_context.validators.len() > idx { + statement.check_signature( + &self.table_context.signing_context, + &self.table_context.validators[idx], + ).map_err(|_| Error::InvalidSignature)?; + } else { + return Err(Error::InvalidSignature); + } + + Ok(()) + } + + async fn send_to_provisioner(&mut self, msg: ProvisionerMessage) -> Result<(), Error> { + self.tx_from.send(FromJob::Provisioner(msg)).await?; + + Ok(()) + } + + async fn request_pov_from_distribution( + &mut self, + descriptor: CandidateDescriptor, + ) -> Result { + let (tx, rx) = oneshot::channel(); + + self.tx_from.send(FromJob::PoVDistribution( + PoVDistributionMessage::FetchPoV(self.parent, descriptor, tx) + )).await?; + + let pov = rx.await?; + Ok((*pov).clone()) + } + + async fn request_candidate_validation( + &mut self, + candidate: AbridgedCandidateReceipt, + pov: PoVBlock, + ) -> Result<(ValidationResult, GlobalValidationSchedule, LocalValidationData), Error> { + let (tx, rx) = oneshot::channel(); + + self.tx_from.send(FromJob::CandidateValidation( + CandidateValidationMessage::Validate( + self.parent, + candidate, + self.head_data.clone(), + pov, + tx, + ) + ) + ).await?; + + Ok(rx.await??) + } + + async fn store_chunk( + &mut self, + id: ValidatorIndex, + chunk: ErasureChunk, + ) -> Result<(), Error> { + self.tx_from.send(FromJob::AvailabilityStore( + AvailabilityStoreMessage::StoreChunk(self.parent, id, chunk) + ) + ).await?; + + Ok(()) + } + + async fn make_pov_available( + &mut self, + pov_block: PoVBlock, + global_validation: GlobalValidationSchedule, + local_validation: LocalValidationData, + ) -> Result<(), Error> { + let omitted_validation = OmittedValidationData { + global_validation, + local_validation, + }; + + let available_data = AvailableData { + pov_block, + omitted_validation, + }; + + let chunks = erasure_coding::obtain_chunks( + self.table_context.validators.len(), + &available_data, + )?; + + let branches = erasure_coding::branches(chunks.as_ref()); + + for (index, (chunk, proof)) in chunks.iter().zip(branches.map(|(proof, _)| proof)).enumerate() { + let chunk = ErasureChunk { + chunk: chunk.clone(), + index: index as u32, + proof, + }; + + self.store_chunk(index as ValidatorIndex, chunk).await?; + } + + Ok(()) + } + + async fn distribute_signed_statement(&mut self, s: SignedFullStatement) -> Result<(), Error> { + let smsg = StatementDistributionMessage::Share(self.parent, s); + + self.tx_from.send(FromJob::StatementDistribution(smsg)).await?; + + Ok(()) + } +} + +struct JobHandle { + abort_handle: future::AbortHandle, + to_job: mpsc::Sender, + finished: oneshot::Receiver<()>, + su_handle: usize, +} + +impl JobHandle { + async fn stop(mut self) { + let _ = self.to_job.send(ToJob::Stop).await; + let stop_timer = Delay::new(Duration::from_secs(1)); + + match future::select(stop_timer, self.finished).await { + Either::Left((_, _)) => { + }, + Either::Right((_, _)) => { + self.abort_handle.abort(); + }, + } + } + + async fn send_msg(&mut self, msg: ToJob) -> Result<(), Error> { + Ok(self.to_job.send(msg).await?) + } +} + +struct Jobs { + spawner: S, + running: HashMap, + outgoing_msgs: StreamUnordered>, +} + +async fn run_job( + parent: Hash, + keystore: KeyStorePtr, + rx_to: mpsc::Receiver, + mut tx_from: mpsc::Sender, +) -> Result<(), Error> { + let (validators, roster) = futures::try_join!( + request_validators(parent, &mut tx_from).await?, + request_validator_groups(parent, &mut tx_from).await?, + )?; + + let key = signing_key(&validators[..], &keystore).ok_or(Error::NotInValidatorSet)?; + let mut groups = HashMap::new(); + + for assignment in roster.scheduled { + if let Some(g) = roster.validator_groups.get(assignment.group_idx.0 as usize) { + groups.insert( + assignment.para_id, + g.clone(), + ); + } + } + + let mut assignment = Default::default(); + + if let Some(idx) = validators.iter().position(|k| *k == key.public()) { + let idx = idx as u32; + for (para_id, group) in groups.iter() { + if group.contains(&idx) { + assignment = *para_id; + break; + } + } + } + + let ( + head_data, + signing_context, + ) = futures::try_join!( + request_head_data(parent, &mut tx_from, assignment).await?, + request_signing_context(parent, &mut tx_from).await?, + )?; + + let table_context = TableContext { + signing_context, + key: Some(key), + groups, + validators, + }; + + let job = CandidateBackingJob { + parent, + rx_to, + tx_from, + head_data, + assignment, + issued_statements: HashSet::new(), + seconded: None, + reported_misbehavior_for: HashSet::new(), + table: Table::default(), + table_context, + }; + + job.run().await +} + +/// Request a validator set from the `RuntimeApi`. +async fn request_validators( + parent: Hash, + s: &mut mpsc::Sender, +) -> Result>, Error> { + let (tx, rx) = oneshot::channel(); + + s.send(FromJob::RuntimeApiMessage(RuntimeApiMessage::Request( + parent, + RuntimeApiRequest::Validators(tx), + ) + )).await?; + + Ok(rx) +} + +/// Request the scheduler roster from `RuntimeApi`. +async fn request_validator_groups( + parent: Hash, + s: &mut mpsc::Sender, +) -> Result, Error> { + let (tx, rx) = oneshot::channel(); + + s.send(FromJob::RuntimeApiMessage(RuntimeApiMessage::Request( + parent, + RuntimeApiRequest::ValidatorGroups(tx), + ) + )).await?; + + Ok(rx) +} + +/// Request a `SigningContext` from the `RuntimeApi`. +async fn request_signing_context( + parent: Hash, + s: &mut mpsc::Sender, +) -> Result, Error> { + let (tx, rx) = oneshot::channel(); + + s.send(FromJob::RuntimeApiMessage(RuntimeApiMessage::Request( + parent, + RuntimeApiRequest::SigningContext(tx), + ) + )).await?; + + Ok(rx) +} + +/// Request `HeadData` for some `ParaId` from `RuntimeApi`. +async fn request_head_data( + parent: Hash, + s: &mut mpsc::Sender, + id: ParaId, +) -> Result, Error> { + let (tx, rx) = oneshot::channel(); + + s.send(FromJob::RuntimeApiMessage(RuntimeApiMessage::Request( + parent, + RuntimeApiRequest::HeadData(id, tx), + ) + )).await?; + + Ok(rx) +} + +impl Jobs { + fn new(spawner: S) -> Self { + Self { + spawner, + running: HashMap::default(), + outgoing_msgs: StreamUnordered::new(), + } + } + + fn spawn_job(&mut self, parent_hash: Hash, keystore: KeyStorePtr) -> Result<(), Error> { + let (to_job_tx, to_job_rx) = mpsc::channel(CHANNEL_CAPACITY); + let (from_job_tx, from_job_rx) = mpsc::channel(CHANNEL_CAPACITY); + + let (future, abort_handle) = future::abortable(async move { + if let Err(e) = run_job(parent_hash, keystore, to_job_rx, from_job_tx).await { + log::error!( + "CandidateBackingJob({}) finished with an error {:?}", + parent_hash, + e, + ); + } + }); + + let (finished_tx, finished) = oneshot::channel(); + + let future = async move { + let _ = future.await; + let _ = finished_tx.send(()); + }; + self.spawner.spawn(future)?; + + let su_handle = self.outgoing_msgs.push(from_job_rx); + + let handle = JobHandle { + abort_handle, + to_job: to_job_tx, + finished, + su_handle, + }; + + self.running.insert(parent_hash, handle); + + Ok(()) + } + + async fn stop_job(&mut self, parent_hash: Hash) -> Result<(), Error> { + match self.running.remove(&parent_hash) { + Some(handle) => { + Pin::new(&mut self.outgoing_msgs).remove(handle.su_handle); + handle.stop().await; + Ok(()) + } + None => Err(Error::JobNotFound(parent_hash)) + } + } + + async fn send_msg(&mut self, parent_hash: Hash, msg: ToJob) -> Result<(), Error> { + if let Some(job) = self.running.get_mut(&parent_hash) { + job.send_msg(msg).await?; + } + Ok(()) + } + + async fn next(&mut self) -> Option { + self.outgoing_msgs.next().await.and_then(|(e, _)| match e { + StreamYield::Item(e) => Some(e), + _ => None, + }) + } +} + +/// An implementation of the Candidate Backing subsystem. +pub struct CandidateBackingSubsystem { + spawner: S, + keystore: KeyStorePtr, + _context: std::marker::PhantomData, +} + +impl CandidateBackingSubsystem + where + S: Spawn + Clone, + Context: SubsystemContext, +{ + /// Creates a new `CandidateBackingSubsystem`. + pub fn new(keystore: KeyStorePtr, spawner: S) -> Self { + Self { + spawner, + keystore, + _context: std::marker::PhantomData, + } + } + + async fn run( + mut ctx: Context, + keystore: KeyStorePtr, + spawner: S, + ) { + let mut jobs = Jobs::new(spawner.clone()); + + loop { + select! { + incoming = ctx.recv().fuse() => { + match incoming { + Ok(msg) => match msg { + FromOverseer::Signal(OverseerSignal::StartWork(hash)) => { + if let Err(e) = jobs.spawn_job(hash, keystore.clone()) { + log::error!("Failed to spawn a job: {:?}", e); + break; + } + } + FromOverseer::Signal(OverseerSignal::StopWork(hash)) => { + if let Err(e) = jobs.stop_job(hash).await { + log::error!("Failed to spawn a job: {:?}", e); + break; + } + } + FromOverseer::Communication { msg } => { + match msg { + CandidateBackingMessage::Second(hash, _, _) | + CandidateBackingMessage::Statement(hash, _) | + CandidateBackingMessage::GetBackedCandidates(hash, _) => { + let res = jobs.send_msg( + hash.clone(), + ToJob::CandidateBacking(msg), + ).await; + + if let Err(e) = res { + log::error!( + "Failed to send a message to a job: {:?}", + e, + ); + + break; + } + } + _ => (), + } + } + _ => (), + }, + Err(_) => break, + } + } + outgoing = jobs.next().fuse() => { + match outgoing { + Some(msg) => { + let _ = ctx.send_message(msg.into()).await; + } + None => break, + } + } + complete => break, + } + } + } +} + +impl Subsystem for CandidateBackingSubsystem + where + S: Spawn + Send + Clone + 'static, + Context: SubsystemContext, +{ + fn start(self, ctx: Context) -> SpawnedSubsystem { + let keystore = self.keystore.clone(); + let spawner = self.spawner.clone(); + + SpawnedSubsystem(Box::pin(async move { + Self::run(ctx, keystore, spawner).await; + })) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use futures::{Future, executor::{self, ThreadPool}}; + use std::collections::HashMap; + use std::sync::Arc; + use sp_keyring::Sr25519Keyring; + use polkadot_primitives::parachain::{ + AssignmentKind, CollatorId, CoreAssignment, BlockData, CoreIndex, GroupIndex, ValidityAttestation, + }; + use assert_matches::assert_matches; + + fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> Vec { + val_ids.iter().map(|v| v.public().into()).collect() + } + + struct TestState { + chain_ids: Vec, + keystore: KeyStorePtr, + validators: Vec, + validator_public: Vec, + global_validation_schedule: GlobalValidationSchedule, + local_validation_data: LocalValidationData, + roster: SchedulerRoster, + head_data: HashMap, + signing_context: SigningContext, + relay_parent: Hash, + } + + impl Default for TestState { + fn default() -> Self { + let chain_a = ParaId::from(1); + let chain_b = ParaId::from(2); + let thread_a = ParaId::from(3); + + let chain_ids = vec![chain_a, chain_b, thread_a]; + + let validators = vec![ + Sr25519Keyring::Alice, + Sr25519Keyring::Bob, + Sr25519Keyring::Charlie, + Sr25519Keyring::Dave, + Sr25519Keyring::Ferdie, + ]; + + let keystore = keystore::Store::new_in_memory(); + // Make sure `Alice` key is in the keystore, so this mocked node will be a parachain validator. + keystore.write().insert_ephemeral_from_seed::(&validators[0].to_seed()) + .expect("Insert key into keystore"); + + let validator_public = validator_pubkeys(&validators); + + let chain_a_assignment = CoreAssignment { + core: CoreIndex::from(0), + para_id: chain_a, + kind: AssignmentKind::Parachain, + group_idx: GroupIndex::from(0), + }; + + let chain_b_assignment = CoreAssignment { + core: CoreIndex::from(1), + para_id: chain_b, + kind: AssignmentKind::Parachain, + group_idx: GroupIndex::from(1), + }; + + let thread_collator: CollatorId = Sr25519Keyring::Two.public().into(); + + let thread_a_assignment = CoreAssignment { + core: CoreIndex::from(2), + para_id: thread_a, + kind: AssignmentKind::Parathread(thread_collator.clone(), 0), + group_idx: GroupIndex::from(2), + }; + + let validator_groups = vec![vec![2, 0, 3], vec![1], vec![4]]; + + let parent_hash_1 = [1; 32].into(); + + let roster = SchedulerRoster { + validator_groups, + scheduled: vec![ + chain_a_assignment, + chain_b_assignment, + thread_a_assignment, + ], + upcoming: vec![], + availability_cores: vec![], + }; + let signing_context = SigningContext { + session_index: 1, + parent_hash: parent_hash_1, + }; + + let mut head_data = HashMap::new(); + head_data.insert(chain_a, HeadData(vec![4, 5, 6])); + + let relay_parent = Hash::from([5; 32]); + + let local_validation_data = LocalValidationData { + parent_head: HeadData(vec![7, 8, 9]), + balance: Default::default(), + code_upgrade_allowed: None, + }; + + let global_validation_schedule = GlobalValidationSchedule { + max_code_size: 1000, + max_head_data_size: 1000, + block_number: Default::default(), + }; + + Self { + chain_ids, + keystore, + validators, + validator_public, + roster, + head_data, + local_validation_data, + global_validation_schedule, + signing_context, + relay_parent, + } + } + } + + struct TestHarness { + virtual_overseer: subsystem_test::TestSubsystemContextHandle, + } + + fn test_harness>(keystore: KeyStorePtr, test: impl FnOnce(TestHarness) -> T) { + let pool = ThreadPool::new().unwrap(); + + let (context, virtual_overseer) = subsystem_test::make_subsystem_context(pool.clone()); + + let subsystem = CandidateBackingSubsystem::run(context, keystore, pool.clone()); + + let test_fut = test(TestHarness { + virtual_overseer, + }); + + futures::pin_mut!(test_fut); + futures::pin_mut!(subsystem); + + executor::block_on(future::select(test_fut, subsystem)); + } + + // Tests that the subsystem performs actions that are requied on startup. + async fn test_startup( + virtual_overseer: &mut subsystem_test::TestSubsystemContextHandle, + test_state: &TestState, + ) { + // Start work on some new parent. + virtual_overseer.send(FromOverseer::Signal( + OverseerSignal::StartWork(test_state.relay_parent)) + ).await; + + // Check that subsystem job issues a request for a validator set. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(parent, RuntimeApiRequest::Validators(tx)) + ) if parent == test_state.relay_parent => { + tx.send(test_state.validator_public.clone()).unwrap(); + } + ); + + // Check that subsystem job issues a request for the validator groups. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(parent, RuntimeApiRequest::ValidatorGroups(tx)) + ) if parent == test_state.relay_parent => { + tx.send(test_state.roster.clone()).unwrap(); + } + ); + + // Check that subsystem job issues a request for the head data. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(parent, RuntimeApiRequest::HeadData(id, tx)) + ) if parent == test_state.relay_parent => { + tx.send(test_state.head_data.get(&id).unwrap().clone()).unwrap(); + } + ); + + // Check that subsystem job issues a request for the signing context. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(parent, RuntimeApiRequest::SigningContext(tx)) + ) if parent == test_state.relay_parent => { + tx.send(test_state.signing_context.clone()).unwrap(); + } + ); + } + + // Test that a `CandidateBackingMessage::Second` issues validation work + // and in case validation is successful issues a `StatementDistributionMessage`. + #[test] + fn backing_second_works() { + let test_state = TestState::default(); + test_harness(test_state.keystore.clone(), |test_harness| async move { + let TestHarness { mut virtual_overseer } = test_harness; + + test_startup(&mut virtual_overseer, &test_state).await; + + let pov_block = PoVBlock { + block_data: BlockData(vec![42, 43, 44]), + }; + + let pov_block_hash = pov_block.hash(); + let candidate = AbridgedCandidateReceipt { + parachain_index: test_state.chain_ids[0], + relay_parent: test_state.relay_parent, + pov_block_hash, + ..Default::default() + }; + + let second = CandidateBackingMessage::Second( + test_state.relay_parent, + candidate.clone(), + pov_block.clone(), + ); + + virtual_overseer.send(FromOverseer::Communication{ msg: second }).await; + + let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap(); + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::CandidateValidation( + CandidateValidationMessage::Validate( + parent_hash, + c, + head_data, + pov, + tx, + ) + ) if parent_hash == test_state.relay_parent && + pov == pov_block && c == candidate => { + assert_eq!(head_data, *expected_head_data); + tx.send(Ok(( + ValidationResult::Valid, + test_state.global_validation_schedule, + test_state.local_validation_data, + ))).unwrap(); + } + ); + + for _ in 0..test_state.validators.len() { + assert_matches!( + virtual_overseer.recv().await, + AllMessages::AvailabilityStore( + AvailabilityStoreMessage::StoreChunk(parent_hash, _, _) + ) if parent_hash == test_state.relay_parent + ); + } + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::Share( + parent_hash, + signed_statement, + ) + ) if parent_hash == test_state.relay_parent => { + signed_statement.check_signature( + &test_state.signing_context, + &test_state.validator_public[0], + ).unwrap(); + } + ); + + virtual_overseer.send(FromOverseer::Signal( + OverseerSignal::StopWork(test_state.relay_parent)) + ).await; + }); + } + + // Test that the candidate reaches quorum succesfully. + #[test] + fn backing_works() { + let test_state = TestState::default(); + test_harness(test_state.keystore.clone(), |test_harness| async move { + let TestHarness { mut virtual_overseer } = test_harness; + + test_startup(&mut virtual_overseer, &test_state).await; + + let pov_block = PoVBlock { + block_data: BlockData(vec![1, 2, 3]), + }; + + let pov_block_hash = pov_block.hash(); + + let candidate_a = AbridgedCandidateReceipt { + parachain_index: test_state.chain_ids[0], + relay_parent: test_state.relay_parent, + pov_block_hash, + ..Default::default() + }; + + let candidate_a_hash = candidate_a.hash(); + + let signed_a = SignedFullStatement::sign( + Statement::Seconded(candidate_a.clone()), + &test_state.signing_context, + 2, + &test_state.validators[2].pair().into(), + ); + + let signed_b = SignedFullStatement::sign( + Statement::Valid(candidate_a_hash), + &test_state.signing_context, + 0, + &test_state.validators[0].pair().into(), + ); + + let statement = CandidateBackingMessage::Statement(test_state.relay_parent, signed_a.clone()); + + virtual_overseer.send(FromOverseer::Communication{ msg: statement }).await; + + // Sending a `Statement::Seconded` for our assignment will start + // validation process. The first thing requested is PoVBlock from the + // `PoVDistribution`. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::PoVDistribution( + PoVDistributionMessage::FetchPoV(relay_parent, _, tx) + ) if relay_parent == test_state.relay_parent => { + tx.send(Arc::new(pov_block.clone())).unwrap(); + } + ); + + let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap(); + + // The next step is the actual request to Validation subsystem + // to validate the `Seconded` candidate. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::CandidateValidation( + CandidateValidationMessage::Validate( + relay_parent, + candidate, + head_data, + pov, + tx, + ) + ) if relay_parent == test_state.relay_parent && candidate == candidate_a => { + assert_eq!(head_data, *expected_head_data); + assert_eq!(pov, pov_block); + tx.send(Ok(( + ValidationResult::Valid, + test_state.global_validation_schedule, + test_state.local_validation_data, + ))).unwrap(); + } + ); + + let statement = CandidateBackingMessage::Statement( + test_state.relay_parent, + signed_b.clone(), + ); + + virtual_overseer.send(FromOverseer::Communication{ msg: statement }).await; + + let (tx, rx) = oneshot::channel(); + + // The backed candidats set should be not empty at this point. + virtual_overseer.send(FromOverseer::Communication{ + msg: CandidateBackingMessage::GetBackedCandidates( + test_state.relay_parent, + tx, + ) + }).await; + + let backed = rx.await.unwrap(); + + // `validity_votes` may be in any order so we can't do this in a single assert. + assert_eq!(backed[0].0.candidate, candidate_a); + assert_eq!(backed[0].0.validity_votes.len(), 2); + assert!(backed[0].0.validity_votes.contains( + &ValidityAttestation::Explicit(signed_b.signature().clone()) + )); + assert!(backed[0].0.validity_votes.contains( + &ValidityAttestation::Implicit(signed_a.signature().clone()) + )); + assert_eq!(backed[0].0.validator_indices, bitvec::bitvec![Lsb0, u8; 1, 1, 0]); + + virtual_overseer.send(FromOverseer::Signal( + OverseerSignal::StopWork(test_state.relay_parent)) + ).await; + }); + } + + // Issuing conflicting statements on the same candidate should + // be a misbehavior. + #[test] + fn backing_misbehavior_works() { + let test_state = TestState::default(); + test_harness(test_state.keystore.clone(), |test_harness| async move { + let TestHarness { mut virtual_overseer } = test_harness; + + test_startup(&mut virtual_overseer, &test_state).await; + + let pov_block = PoVBlock { + block_data: BlockData(vec![1, 2, 3]), + }; + + let pov_block_hash = pov_block.hash(); + let candidate_a = AbridgedCandidateReceipt { + parachain_index: test_state.chain_ids[0], + relay_parent: test_state.relay_parent, + pov_block_hash, + ..Default::default() + }; + + let candidate_a_hash = candidate_a.hash(); + + let signed_a = SignedFullStatement::sign( + Statement::Seconded(candidate_a.clone()), + &test_state.signing_context, + 2, + &test_state.validators[2].pair().into(), + ); + + let signed_b = SignedFullStatement::sign( + Statement::Valid(candidate_a_hash), + &test_state.signing_context, + 0, + &test_state.validators[0].pair().into(), + ); + + let signed_c = SignedFullStatement::sign( + Statement::Invalid(candidate_a_hash), + &test_state.signing_context, + 0, + &test_state.validators[0].pair().into(), + ); + + let statement = CandidateBackingMessage::Statement(test_state.relay_parent, signed_a.clone()); + + virtual_overseer.send(FromOverseer::Communication{ msg: statement }).await; + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::PoVDistribution( + PoVDistributionMessage::FetchPoV(relay_parent, _, tx) + ) if relay_parent == test_state.relay_parent => { + tx.send(Arc::new(pov_block.clone())).unwrap(); + } + ); + + let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap(); + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::CandidateValidation( + CandidateValidationMessage::Validate( + relay_parent, + candidate, + head_data, + pov, + tx, + ) + ) if relay_parent == test_state.relay_parent && candidate == candidate_a => { + assert_eq!(pov, pov_block); + assert_eq!(head_data, *expected_head_data); + tx.send(Ok(( + ValidationResult::Valid, + test_state.global_validation_schedule, + test_state.local_validation_data, + ))).unwrap(); + } + ); + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::Share( + relay_parent, + signed_statement, + ) + ) if relay_parent == test_state.relay_parent => { + signed_statement.check_signature( + &test_state.signing_context, + &test_state.validator_public[0], + ).unwrap(); + + assert_eq!(*signed_statement.payload(), Statement::Valid(candidate_a_hash)); + } + ); + + let statement = CandidateBackingMessage::Statement(test_state.relay_parent, signed_b.clone()); + + virtual_overseer.send(FromOverseer::Communication{ msg: statement }).await; + + let statement = CandidateBackingMessage::Statement(test_state.relay_parent, signed_c.clone()); + + virtual_overseer.send(FromOverseer::Communication{ msg: statement }).await; + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::Provisioner( + ProvisionerMessage::ProvisionableData( + ProvisionableData::MisbehaviorReport( + relay_parent, + MisbehaviorReport::SelfContradiction(_, s1, s2), + ) + ) + ) if relay_parent == test_state.relay_parent => { + s1.check_signature( + &test_state.signing_context, + &test_state.validator_public[s1.validator_index() as usize], + ).unwrap(); + + s2.check_signature( + &test_state.signing_context, + &test_state.validator_public[s2.validator_index() as usize], + ).unwrap(); + } + ); + + }); + } + + // Test that if we are asked to second an invalid candidate we + // can still second a valid one afterwards. + #[test] + fn backing_dont_second_invalid() { + let test_state = TestState::default(); + test_harness(test_state.keystore.clone(), |test_harness| async move { + let TestHarness { mut virtual_overseer } = test_harness; + + test_startup(&mut virtual_overseer, &test_state).await; + + let pov_block_a = PoVBlock { + block_data: BlockData(vec![42, 43, 44]), + }; + + let pov_block_b = PoVBlock { + block_data: BlockData(vec![45, 46, 47]), + }; + + let pov_block_hash_a = pov_block_a.hash(); + let pov_block_hash_b = pov_block_b.hash(); + + let candidate_a = AbridgedCandidateReceipt { + parachain_index: test_state.chain_ids[0], + relay_parent: test_state.relay_parent, + pov_block_hash: pov_block_hash_a, + ..Default::default() + }; + + let candidate_a_hash = candidate_a.hash(); + + let candidate_b = AbridgedCandidateReceipt { + parachain_index: test_state.chain_ids[0], + relay_parent: test_state.relay_parent, + pov_block_hash: pov_block_hash_b, + ..Default::default() + }; + + let second = CandidateBackingMessage::Second( + test_state.relay_parent, + candidate_a.clone(), + pov_block_a.clone(), + ); + + virtual_overseer.send(FromOverseer::Communication{ msg: second }).await; + + let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap(); + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::CandidateValidation( + CandidateValidationMessage::Validate( + parent_hash, + c, + head_data, + pov, + tx, + ) + ) if parent_hash == test_state.relay_parent && + pov == pov_block_a && c == candidate_a => { + assert_eq!(head_data, *expected_head_data); + tx.send(Ok(( + ValidationResult::Invalid, + test_state.global_validation_schedule.clone(), + test_state.local_validation_data.clone(), + ))).unwrap(); + } + ); + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::CandidateSelection( + CandidateSelectionMessage::Invalid(parent_hash, candidate) + ) if parent_hash == test_state.relay_parent && candidate == candidate_a + ); + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::Share( + relay_parent, + statement, + ) + ) if relay_parent == test_state.relay_parent => { + assert_eq!(*statement.payload(), Statement::Invalid(candidate_a_hash)); + } + ); + + let second = CandidateBackingMessage::Second( + test_state.relay_parent, + candidate_b.clone(), + pov_block_b.clone(), + ); + + virtual_overseer.send(FromOverseer::Communication{ msg: second }).await; + + let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap(); + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::CandidateValidation( + CandidateValidationMessage::Validate( + parent_hash, + c, + head_data, + pov, + tx, + ) + ) if parent_hash == test_state.relay_parent && + pov == pov_block_b && c == candidate_b => { + assert_eq!(head_data, *expected_head_data); + tx.send(Ok(( + ValidationResult::Valid, + test_state.global_validation_schedule, + test_state.local_validation_data, + ))).unwrap(); + } + ); + + for _ in 0..test_state.validators.len() { + assert_matches!( + virtual_overseer.recv().await, + AllMessages::AvailabilityStore( + AvailabilityStoreMessage::StoreChunk(parent_hash, _, _) + ) if parent_hash == test_state.relay_parent + ); + } + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::Share( + parent_hash, + signed_statement, + ) + ) if parent_hash == test_state.relay_parent => { + signed_statement.check_signature( + &test_state.signing_context, + &test_state.validator_public[0], + ).unwrap(); + + assert_eq!(*signed_statement.payload(), Statement::Seconded(candidate_b)); + } + ); + + virtual_overseer.send(FromOverseer::Signal( + OverseerSignal::StopWork(test_state.relay_parent)) + ).await; + }); + } + + // Test that if we have already issued a statement (in this case `Invalid`) about a + // candidate we will not be issuing a `Seconded` statement on it. + #[test] + fn backing_multiple_statements_work() { + let test_state = TestState::default(); + test_harness(test_state.keystore.clone(), |test_harness| async move { + let TestHarness { mut virtual_overseer } = test_harness; + + test_startup(&mut virtual_overseer, &test_state).await; + + let pov_block = PoVBlock { + block_data: BlockData(vec![42, 43, 44]), + }; + + let pov_block_hash = pov_block.hash(); + + let candidate = AbridgedCandidateReceipt { + parachain_index: test_state.chain_ids[0], + relay_parent: test_state.relay_parent, + pov_block_hash, + ..Default::default() + }; + + let candidate_hash = candidate.hash(); + + let signed_a = SignedFullStatement::sign( + Statement::Seconded(candidate.clone()), + &test_state.signing_context, + 2, + &test_state.validators[2].pair().into(), + ); + + // Send in a `Statement` with a candidate. + let statement = CandidateBackingMessage::Statement( + test_state.relay_parent, + signed_a.clone(), + ); + + virtual_overseer.send(FromOverseer::Communication{ msg: statement }).await; + + // Subsystem requests PoV and requests validation. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::PoVDistribution( + PoVDistributionMessage::FetchPoV(relay_parent, _, tx) + ) => { + assert_eq!(relay_parent, test_state.relay_parent); + tx.send(Arc::new(pov_block.clone())).unwrap(); + } + ); + + let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap(); + + // Tell subsystem that this candidate is invalid. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::CandidateValidation( + CandidateValidationMessage::Validate( + relay_parent, + candidate_recvd, + head_data, + pov, + tx, + ) + ) => { + assert_eq!(relay_parent, test_state.relay_parent); + assert_eq!(candidate_recvd, candidate); + assert_eq!(head_data, *expected_head_data); + assert_eq!(pov, pov_block); + tx.send(Ok(( + ValidationResult::Invalid, + test_state.global_validation_schedule, + test_state.local_validation_data, + ))).unwrap(); + } + ); + + // The invalid message is shared. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::Share( + relay_parent, + signed_statement, + ) + ) => { + assert_eq!(relay_parent, test_state.relay_parent); + signed_statement.check_signature( + &test_state.signing_context, + &test_state.validator_public[0], + ).unwrap(); + assert_eq!(*signed_statement.payload(), Statement::Invalid(candidate_hash)); + } + ); + + // Ask subsystem to `Second` a candidate that already has a statement issued about. + // This should emit no actions from subsystem. + let second = CandidateBackingMessage::Second( + test_state.relay_parent, + candidate.clone(), + pov_block.clone(), + ); + + virtual_overseer.send(FromOverseer::Communication{ msg: second }).await; + + let pov_to_second = PoVBlock { + block_data: BlockData(vec![3, 2, 1]), + }; + + let pov_block_hash = pov_to_second.hash(); + + let candidate_to_second = AbridgedCandidateReceipt { + parachain_index: test_state.chain_ids[0], + relay_parent: test_state.relay_parent, + pov_block_hash, + ..Default::default() + }; + + let second = CandidateBackingMessage::Second( + test_state.relay_parent, + candidate_to_second.clone(), + pov_to_second.clone(), + ); + + // In order to trigger _some_ actions from subsystem ask it to second another + // candidate. The only reason to do so is to make sure that no actions were + // triggered on the prev step. + virtual_overseer.send(FromOverseer::Communication{ msg: second }).await; + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::CandidateValidation( + CandidateValidationMessage::Validate( + relay_parent, + _, + _, + pov, + _, + ) + ) => { + assert_eq!(relay_parent, test_state.relay_parent); + assert_eq!(pov, pov_to_second); + } + ); + }); + } +} diff --git a/node/overseer/examples/minimal-example.rs b/node/overseer/examples/minimal-example.rs index cdef0340d04f..aefb627f7f56 100644 --- a/node/overseer/examples/minimal-example.rs +++ b/node/overseer/examples/minimal-example.rs @@ -59,6 +59,7 @@ impl Subsystem1 { ctx.send_message(AllMessages::CandidateValidation( CandidateValidationMessage::Validate( + Default::default(), Default::default(), Default::default(), PoVBlock { diff --git a/node/overseer/src/lib.rs b/node/overseer/src/lib.rs index 70de3c1d86f8..ffebf33ce4f9 100644 --- a/node/overseer/src/lib.rs +++ b/node/overseer/src/lib.rs @@ -726,6 +726,7 @@ mod tests { ctx.send_message( AllMessages::CandidateValidation( CandidateValidationMessage::Validate( + Default::default(), Default::default(), Default::default(), PoVBlock { diff --git a/node/primitives/src/lib.rs b/node/primitives/src/lib.rs index 921f620ea9dc..25313c09154e 100644 --- a/node/primitives/src/lib.rs +++ b/node/primitives/src/lib.rs @@ -23,10 +23,17 @@ use parity_scale_codec::{Decode, Encode}; use polkadot_primitives::{Hash, parachain::{ - AbridgedCandidateReceipt, CandidateReceipt, CompactStatement, - EncodeAs, Signed, + AbridgedCandidateReceipt, CompactStatement, + EncodeAs, Signed, SigningContext, ValidatorIndex, ValidatorId, } }; +use polkadot_statement_table::{ + generic::{ + ValidityDoubleVote as TableValidityDoubleVote, + MultipleCandidates as TableMultipleCandidates, + }, + Misbehavior as TableMisbehavior, +}; /// A statement, where the candidate receipt is included in the `Seconded` variant. #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] @@ -77,11 +84,128 @@ pub enum MisbehaviorReport { /// this message should be dispatched with all of them, in arbitrary order. /// /// This variant is also used when our own validity checks disagree with others'. - CandidateValidityDisagreement(CandidateReceipt, Vec), + CandidateValidityDisagreement(AbridgedCandidateReceipt, Vec), /// I've noticed a peer contradicting itself about a particular candidate - SelfContradiction(CandidateReceipt, SignedFullStatement, SignedFullStatement), + SelfContradiction(AbridgedCandidateReceipt, SignedFullStatement, SignedFullStatement), /// This peer has seconded more than one parachain candidate for this relay parent head - DoubleVote(CandidateReceipt, SignedFullStatement, SignedFullStatement), + DoubleVote(SignedFullStatement, SignedFullStatement), +} + +/// A utility struct used to convert `TableMisbehavior` to `MisbehaviorReport`s. +pub struct FromTableMisbehavior { + /// Index of the validator. + pub id: ValidatorIndex, + /// The misbehavior reported by the table. + pub report: TableMisbehavior, + /// Signing context. + pub signing_context: SigningContext, + /// Misbehaving validator's public key. + pub key: ValidatorId, +} + +/// Result of the validation of the candidate. +#[derive(Debug)] +pub enum ValidationResult { + /// Candidate is valid. + Valid, + /// Candidate is invalid. + Invalid, +} + +impl std::convert::TryFrom for MisbehaviorReport { + type Error = (); + + fn try_from(f: FromTableMisbehavior) -> Result { + match f.report { + TableMisbehavior::ValidityDoubleVote( + TableValidityDoubleVote::IssuedAndValidity((c, s1), (d, s2)) + ) => { + let receipt = c.clone(); + let signed_1 = SignedFullStatement::new( + Statement::Seconded(c), + f.id, + s1, + &f.signing_context, + &f.key, + ).ok_or(())?; + let signed_2 = SignedFullStatement::new( + Statement::Valid(d), + f.id, + s2, + &f.signing_context, + &f.key, + ).ok_or(())?; + + Ok(MisbehaviorReport::SelfContradiction(receipt, signed_1, signed_2)) + } + TableMisbehavior::ValidityDoubleVote( + TableValidityDoubleVote::IssuedAndInvalidity((c, s1), (d, s2)) + ) => { + let receipt = c.clone(); + let signed_1 = SignedFullStatement::new( + Statement::Seconded(c), + f.id, + s1, + &f.signing_context, + &f.key, + ).ok_or(())?; + let signed_2 = SignedFullStatement::new( + Statement::Invalid(d), + f.id, + s2, + &f.signing_context, + &f.key, + ).ok_or(())?; + + Ok(MisbehaviorReport::SelfContradiction(receipt, signed_1, signed_2)) + } + TableMisbehavior::ValidityDoubleVote( + TableValidityDoubleVote::ValidityAndInvalidity(c, s1, s2) + ) => { + let signed_1 = SignedFullStatement::new( + Statement::Valid(c.hash()), + f.id, + s1, + &f.signing_context, + &f.key, + ).ok_or(())?; + let signed_2 = SignedFullStatement::new( + Statement::Invalid(c.hash()), + f.id, + s2, + &f.signing_context, + &f.key, + ).ok_or(())?; + + Ok(MisbehaviorReport::SelfContradiction(c, signed_1, signed_2)) + } + TableMisbehavior::MultipleCandidates( + TableMultipleCandidates { + first, + second, + } + ) => { + let signed_1 = SignedFullStatement::new( + Statement::Seconded(first.0), + f.id, + first.1, + &f.signing_context, + &f.key, + ).ok_or(())?; + + let signed_2 = SignedFullStatement::new( + Statement::Seconded(second.0), + f.id, + second.1, + &f.signing_context, + &f.key, + ).ok_or(())?; + + Ok(MisbehaviorReport::DoubleVote(signed_1, signed_2)) + } + _ => Err(()), + } + } } /// A unique identifier for a network protocol. diff --git a/node/subsystem/src/messages.rs b/node/subsystem/src/messages.rs index 73371e28fd9b..c98658e4aeab 100644 --- a/node/subsystem/src/messages.rs +++ b/node/subsystem/src/messages.rs @@ -28,10 +28,11 @@ use polkadot_primitives::{BlockNumber, Hash, Signature}; use polkadot_primitives::parachain::{ AbridgedCandidateReceipt, PoVBlock, ErasureChunk, BackedCandidate, Id as ParaId, SignedAvailabilityBitfield, SigningContext, ValidatorId, ValidationCode, ValidatorIndex, - CandidateDescriptor, + CoreAssignment, CoreOccupied, HeadData, CandidateDescriptor, GlobalValidationSchedule, + LocalValidationData, }; use polkadot_node_primitives::{ - MisbehaviorReport, SignedFullStatement, View, ProtocolId, + MisbehaviorReport, SignedFullStatement, View, ProtocolId, ValidationResult, }; use std::sync::Arc; @@ -53,12 +54,12 @@ pub enum CandidateSelectionMessage { /// Messages received by the Candidate Backing subsystem. #[derive(Debug)] pub enum CandidateBackingMessage { - /// Registers a stream listener for updates to the set of backable candidates that could be backed - /// in a child of the given relay-parent, referenced by its hash. - RegisterBackingWatcher(Hash, mpsc::Sender), + /// Requests a set of backable candidates that could be backed in a child of the given + /// relay-parent, referenced by its hash. + GetBackedCandidates(Hash, oneshot::Sender>), /// Note that the Candidate Backing subsystem should second the given candidate in the context of the /// given relay-parent (ref. by hash). This candidate must be validated. - Second(Hash, AbridgedCandidateReceipt), + Second(Hash, AbridgedCandidateReceipt, PoVBlock), /// Note a validator's statement about a particular candidate. Disagreements about validity must be escalated /// to a broader check by Misbehavior Arbitration. Agreements are simply tallied until a quorum is reached. Statement(Hash, SignedFullStatement), @@ -78,8 +79,12 @@ pub enum CandidateValidationMessage { Validate( Hash, AbridgedCandidateReceipt, + HeadData, PoVBlock, - oneshot::Sender>, + oneshot::Sender>, ), } @@ -151,17 +156,34 @@ pub enum AvailabilityStoreMessage { StoreChunk(Hash, ValidatorIndex, ErasureChunk), } +/// The information on scheduler assignments that some somesystems may be querying. +#[derive(Debug, Clone)] +pub struct SchedulerRoster { + /// Validator-to-groups assignments. + pub validator_groups: Vec>, + /// All scheduled paras. + pub scheduled: Vec, + /// Upcoming paras (chains and threads). + pub upcoming: Vec, + /// Occupied cores. + pub availability_cores: Vec>, +} + /// A request to the Runtime API subsystem. #[derive(Debug)] pub enum RuntimeApiRequest { /// Get the current validator set. Validators(oneshot::Sender>), + /// Get the assignments of validators to cores. + ValidatorGroups(oneshot::Sender), /// Get a signing context for bitfields and statements. SigningContext(oneshot::Sender), /// Get the validation code for a specific para, assuming execution under given block number, and /// an optional block number representing an intermediate parablock executed in the context of /// that block. ValidationCode(ParaId, BlockNumber, Option, oneshot::Sender), + /// Get head data for a specific para. + HeadData(ParaId, oneshot::Sender), } /// A message to the Runtime API subsystem. diff --git a/primitives/src/parachain.rs b/primitives/src/parachain.rs index d0d3dce558c9..19937798c646 100644 --- a/primitives/src/parachain.rs +++ b/primitives/src/parachain.rs @@ -171,6 +171,100 @@ pub struct DutyRoster { pub validator_duty: Vec, } +/// The unique (during session) index of a core. +#[derive(Encode, Decode, Default, PartialOrd, Ord, Eq, PartialEq, Clone, Copy)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct CoreIndex(pub u32); + +impl From for CoreIndex { + fn from(i: u32) -> CoreIndex { + CoreIndex(i) + } +} + +/// The unique (during session) index of a validator group. +#[derive(Encode, Decode, Default, Clone, Copy)] +#[cfg_attr(feature = "std", derive(Eq, Hash, PartialEq, Debug))] +pub struct GroupIndex(pub u32); + +impl From for GroupIndex { + fn from(i: u32) -> GroupIndex { + GroupIndex(i) + } +} + +/// A claim on authoring the next block for a given parathread. +#[derive(Clone, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(PartialEq, Debug))] +pub struct ParathreadClaim(pub Id, pub CollatorId); + +/// An entry tracking a claim to ensure it does not pass the maximum number of retries. +#[derive(Clone, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(PartialEq, Debug))] +pub struct ParathreadEntry { + /// The claim. + pub claim: ParathreadClaim, + /// Number of retries. + pub retries: u32, +} + +/// What is occupying a specific availability core. +#[derive(Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(PartialEq, Debug))] +pub enum CoreOccupied { + /// A parathread. + Parathread(ParathreadEntry), + /// A parachain. + Parachain, +} + +/// The assignment type. +#[derive(Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(PartialEq, Debug))] +pub enum AssignmentKind { + /// A parachain. + Parachain, + /// A parathread. + Parathread(CollatorId, u32), +} + +/// How a free core is scheduled to be assigned. +#[derive(Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(PartialEq, Debug))] +pub struct CoreAssignment { + /// The core that is assigned. + pub core: CoreIndex, + /// The unique ID of the para that is assigned to the core. + pub para_id: Id, + /// The kind of the assignment. + pub kind: AssignmentKind, + /// The index of the validator group assigned to the core. + pub group_idx: GroupIndex, +} + +impl CoreAssignment { + /// Get the ID of a collator who is required to collate this block. + pub fn required_collator(&self) -> Option<&CollatorId> { + match self.kind { + AssignmentKind::Parachain => None, + AssignmentKind::Parathread(ref id, _) => Some(id), + } + } + + /// Get the `CoreOccupied` from this. + pub fn to_core_occupied(&self) -> CoreOccupied { + match self.kind { + AssignmentKind::Parachain => CoreOccupied::Parachain, + AssignmentKind::Parathread(ref collator, retries) => CoreOccupied::Parathread( + ParathreadEntry { + claim: ParathreadClaim(self.para_id, collator.clone()), + retries, + } + ), + } + } +} + /// Extra data that is needed along with the other fields in a `CandidateReceipt` /// to fully validate the candidate. /// @@ -382,6 +476,15 @@ pub struct AbridgedCandidateReceipt { pub commitments: CandidateCommitments, } +/// A candidate-receipt with commitments directly included. +pub struct CommitedCandidateReceipt { + /// The descriptor of the candidae. + pub descriptor: CandidateDescriptor, + + /// The commitments of the candidate receipt. + pub commitments: CandidateCommitments +} + impl + Encode> AbridgedCandidateReceipt { /// Check integrity vs. provided block data. pub fn check_signature(&self) -> Result<(), ()> { @@ -473,7 +576,6 @@ impl AbridgedCandidateReceipt { } } - impl PartialOrd for AbridgedCandidateReceipt { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) @@ -923,6 +1025,27 @@ impl, RealPayload: Encode> Signed( + payload: Payload, + validator_index: ValidatorIndex, + signature: ValidatorSignature, + context: &SigningContext, + key: &ValidatorId, + ) -> Option { + let s = Self { + payload, + validator_index, + signature, + real_payload: std::marker::PhantomData, + }; + + s.check_signature(context, key).ok()?; + + Some(s) + } + /// Sign this payload with the given context and key, storing the validator index. #[cfg(feature = "std")] pub fn sign( diff --git a/roadmap/implementers-guide/src/node/backing/candidate-backing.md b/roadmap/implementers-guide/src/node/backing/candidate-backing.md index 1490bb074ccb..2044fbd8e75b 100644 --- a/roadmap/implementers-guide/src/node/backing/candidate-backing.md +++ b/roadmap/implementers-guide/src/node/backing/candidate-backing.md @@ -2,30 +2,43 @@ The Candidate Backing subsystem ensures every parablock considered for relay block inclusion has been seconded by at least one validator, and approved by a quorum. Parablocks for which no validator will assert correctness are discarded. If the block later proves invalid, the initial backers are slashable; this gives polkadot a rational threat model during subsequent stages. -Its role is to produce backable candidates for inclusion in new relay-chain blocks. It does so by issuing signed [`Statement`s](../../types/backing.md#statement-type) and tracking received statements signed by other validators. Once enough statements are received, they can be combined into backing for specific candidates. +Its role is to produce backable candidates for inclusion in new relay-chain blocks. It does so by issuing signed [`Statement`s][Statement] and tracking received statements signed by other validators. Once enough statements are received, they can be combined into backing for specific candidates. Note that though the candidate backing subsystem attempts to produce as many backable candidates as possible, it does _not_ attempt to choose a single authoritative one. The choice of which actually gets included is ultimately up to the block author, by whatever metrics it may use; those are opaque to this subsystem. -Once a sufficient quorum has agreed that a candidate is valid, this subsystem notifies the [Provisioner](../utility/provisioner.md), which in turn engages block production mechanisms to include the parablock. +Once a sufficient quorum has agreed that a candidate is valid, this subsystem notifies the [Provisioner][PV], which in turn engages block production mechanisms to include the parablock. ## Protocol -The [Candidate Selection subsystem](candidate-selection.md) is the primary source of non-overseer messages into this subsystem. That subsystem generates appropriate [`CandidateBackingMessage`s](../../types/overseer-protocol.md#candidate-backing-message), and passes them to this subsystem. +Input: [`CandidateBackingMessage`][CBM] -This subsystem validates the candidates and generates an appropriate [`SignedStatement`](../../types/backing.md#signed-statement-type). All `SignedStatement`s are then passed on to the [Statement Distribution subsystem](statement-distribution.md) to be gossiped to peers. All [Proofs of Validity](../../types/availability.md#proof-of-validity) should be distributed via the [PoV Distribution](pov-distribution.md) subsystem. When this subsystem decides that a candidate is invalid, and it was recommended to us to second by our own Candidate Selection subsystem, a message is sent to the Candidate Selection subsystem with the candidate's hash so that the collator which recommended it can be penalized. +Output: + +- [`CandidateValidationMessage`][CVM] +- [`RuntimeApiMessage`][RAM] +- [`CandidateSelectionMessage`][CSM] +- [`ProvisionerMessage`][PM] +- [`PoVDistributionMessage`][PDM] +- [`StatementDistributionMessage`][SDM] ## Functionality +The [Candidate Selection][CS] subsystem is the primary source of non-overseer messages into this subsystem. That subsystem generates appropriate [`CandidateBackingMessage`s][CBM] and passes them to this subsystem. + +This subsystem requests validation from the [Candidate Validation][CV] and generates an appropriate [`Statement`][Statement]. All `Statement`s are then passed on to the [Statement Distribution][SD] subsystem to be gossiped to peers. When [Candidate Validation][CV] decides that a candidate is invalid, and it was recommended to us to second by our own [Candidate Selection][CS] subsystem, a message is sent to the [Candidate Selection][CS] subsystem with the candidate's hash so that the collator which recommended it can be penalized. + The subsystem should maintain a set of handles to Candidate Backing Jobs that are currently live, as well as the relay-parent to which they correspond. ### On Overseer Signal -* If the signal is an [`OverseerSignal`](../../types/overseer-protocol.md#overseer-signal)`::StartWork(relay_parent)`, spawn a Candidate Backing Job with the given relay parent, storing a bidirectional channel with the Candidate Backing Job in the set of handles. -* If the signal is an [`OverseerSignal`](../../types/overseer-protocol.md#overseer-signal)`::StopWork(relay_parent)`, cease the Candidate Backing Job under that relay parent, if any. +* If the signal is an [`OverseerSignal`][OverseerSignal]`::StartWork(relay_parent)`, spawn a Candidate Backing Job with the given relay parent, storing a bidirectional channel with the Candidate Backing Job in the set of handles. +* If the signal is an [`OverseerSignal`][OverseerSignal]`::StopWork(relay_parent)`, cease the Candidate Backing Job under that relay parent, if any. -### On `CandidateBackingMessage` +### On Receiving `CandidateBackingMessage` -* If the message corresponds to a particular relay-parent, forward the message to the Candidate Backing Job for that relay-parent, if any is live. +* If the message is a [`CandidateBackingMessage`][CBM]`::GetBackedCandidates`, get all backable candidates from the statement table and send them back. +* If the message is a [`CandidateBackingMessage`][CBM]`::Second`, sign and dispatch a `Seconded` statement only if we have not seconded any other candidate and have not signed a `Valid` statement for the requested candidate. Signing both a `Seconded` and `Valid` message is a double-voting misbehavior with a heavy penalty, and this could occur if another validator has seconded the same candidate and we've received their message before the internal seconding request. +* If the message is a [`CandidateBackingMessage`][CBM]`::Statement`, count the statement to the quorum. If the statement in the message is `Seconded` and it contains a candidate that belongs to our assignment, request the corresponding `PoV` from the `PoVDistribution` and launch validation. Issue our own `Valid` or `Invalid` statement as a result. > big TODO: "contextual execution" > @@ -39,36 +52,49 @@ The subsystem should maintain a set of handles to Candidate Backing Jobs that ar The Candidate Backing Job represents the work a node does for backing candidates with respect to a particular relay-parent. -The goal of a Candidate Backing Job is to produce as many backable candidates as possible. This is done via signed [`Statement`s](../../types/backing.md#statement-type) by validators. If a candidate receives a majority of supporting Statements from the Parachain Validators currently assigned, then that candidate is considered backable. +The goal of a Candidate Backing Job is to produce as many backable candidates as possible. This is done via signed [`Statement`s][STMT] by validators. If a candidate receives a majority of supporting Statements from the Parachain Validators currently assigned, then that candidate is considered backable. ### On Startup -* Fetch current validator set, validator -> parachain assignments from runtime API. +* Fetch current validator set, validator -> parachain assignments from [`Runtime API`][RA] subsystem using [`RuntimeApiRequest::Validators`][RAM] and [`RuntimeApiRequest::ValidatorGroups`][RAM] * Determine if the node controls a key in the current validator set. Call this the local key if so. -* If the local key exists, extract the parachain head and validation function for the parachain the local key is assigned to. +* If the local key exists, extract the parachain head and validation function from the [`Runtime API`][RA] for the parachain the local key is assigned to by issuing a [`RuntimeApiRequest::Validators`][RAM] +* Issue a [`RuntimeApiRequest::SigningContext`][RAM] message to get a context that will later be used upon signing. -### On Receiving New Signed Statement +### On Receiving New Candidate Backing Message ```rust -if let Statement::Seconded(candidate) = signed.statement { - if candidate is unknown and in local assignment { - spawn_validation_work(candidate, parachain head, validation function) +match msg { + CetBackedCandidates(hash, tx) => { + // Send back a set of backable candidates. + } + CandidateBackingMessage::Second(hash, candidate) => { + if candidate is unknown and in local assignment { + spawn_validation_work(candidate, parachain head, validation function) + } + } + CandidateBackingMessage::Statement(hash, statement) => { + // count to the votes on this candidate + if let Statement::Seconded(candidate) = statement { + if candidate.parachain_id == our_assignment { + spawn_validation_work(candidate, parachain head, validation function) + } + } } } - -// add `Seconded` statements and `Valid` statements to a quorum. If quorum reaches validator-group -// majority, send a `BlockAuthorshipProvisioning::BackableCandidate(relay_parent, Candidate, Backing)` message. ``` -### Spawning Validation Work +Add `Seconded` statements and `Valid` statements to a quorum. If quorum reaches validator-group majority, send a [`ProvisionerMessage`][PM]`::ProvisionableData(ProvisionableData::BackedCandidate(BackedCandidate))` message. +`Invalid` statements that conflict with already witnessed `Seconded` and `Valid` statements for the given candidate, statements that are double-votes, self-contradictions and so on, should result in issuing a [`ProvisionerMessage`][PM]`::MisbehaviorReport` message for each newly detected case of this kind. + +### Validating Candidates. ```rust fn spawn_validation_work(candidate, parachain head, validation function) { asynchronously { let pov = (fetch pov block).await - // dispatched to sub-process (OS process) pool. - let valid = validate_candidate(candidate, validation function, parachain head, pov).await; + let valid = (validate pov block).await; if valid { // make PoV available for later distribution. Send data to the availability store to keep. // sign and dispatch `valid` statement to network if we have not seconded the given candidate. @@ -82,11 +108,30 @@ fn spawn_validation_work(candidate, parachain head, validation function) { ### Fetch Pov Block Create a `(sender, receiver)` pair. -Dispatch a `PovFetchSubsystemMessage(relay_parent, candidate_hash, sender)` and listen on the receiver for a response. +Dispatch a [`PoVDistributionMessage`][PDM]`::FecthPoV(relay_parent, candidate_hash, sender)` and listen on the receiver for a response. -### On Receiving `CandidateBackingMessage` - -* If the message is a `CandidateBackingMessage::RegisterBackingWatcher`, register the watcher and trigger it each time a new candidate is backable. Also trigger it once initially if there are any backable candidates at the time of receipt. -* If the message is a `CandidateBackingMessage::Second`, sign and dispatch a `Seconded` statement only if we have not seconded any other candidate and have not signed a `Valid` statement for the requested candidate. Signing both a `Seconded` and `Valid` message is a double-voting misbehavior with a heavy penalty, and this could occur if another validator has seconded the same candidate and we've received their message before the internal seconding request. +### Validate PoV Block -> TODO: send statements to Statement Distribution subsystem, handle shutdown signal from candidate backing subsystem +Create a `(sender, receiver)` pair. +Dispatch a `CandidateValidationMessage::Validate(validation function, candidate, pov, sender)` and listen on the receiver for a response. + +### Distribute Signed Statemnet + +Dispatch a [`StatementDistributionMessage`][PDM]`::Share(relay_parent, SignedFullStatement)`. + +[OverseerSignal]: ../../types/overseer-protocol.md#overseer-signal +[Statement]: ../../types/backing.md#statement-type +[STMT]: ../../types/backing.md#statement-type +[CSM]: ../../types/overseer-protocol.md#candidate-selection-message +[RAM]: ../../types/overseer-protocol.md#runtime-api-message +[CVM]: ../../types/overseer-protocol.md#validation-request-type +[PM]: ../../types/overseer-protocol.md#provisioner-message +[CBM]: ../../types/overseer-protocol.md#candidate-backing-message +[PDM]: ../../types/overseer-protocol.md#pov-distribution-message +[SDM]: ../../types/overseer-protocol.md#statement-distribution-message + +[CS]: candidate-selection.md +[CV]: ../utility/candidate-validation.md +[SD]: statement-distribution.md +[RA]: ../utility/runtime-api.md +[PV]: ../utility/provisioner.md diff --git a/roadmap/implementers-guide/src/types/overseer-protocol.md b/roadmap/implementers-guide/src/types/overseer-protocol.md index 799d1e2a7f8f..1e59eedff8db 100644 --- a/roadmap/implementers-guide/src/types/overseer-protocol.md +++ b/roadmap/implementers-guide/src/types/overseer-protocol.md @@ -86,9 +86,9 @@ enum BitfieldSigningMessage { } ```rust enum CandidateBackingMessage { - /// Registers a stream listener for updates to the set of backable candidates that could be backed - /// in a child of the given relay-parent, referenced by its hash. - RegisterBackingWatcher(Hash, TODO), + /// Requests a set of backable candidates that could be backed in a child of the given + /// relay-parent, referenced by its hash. + GetBackedCandidates(Hash, ResponseChannel>), /// Note that the Candidate Backing subsystem should second the given candidate in the context of the /// given relay-parent (ref. by hash). This candidate must be validated using the provided PoV. Second(Hash, CandidateReceipt, PoV), @@ -230,9 +230,24 @@ The Runtime API subsystem is responsible for providing an interface to the state Other subsystems query this data by sending these messages. ```rust +/// The information on validator groups, core assignments, +/// upcoming paras and availability cores. +struct SchedulerRoster { + /// Validator-to-groups assignments. + validator_groups: Vec>, + /// All scheduled paras. + scheduled: Vec, + /// Upcoming paras (chains and threads). + upcoming: Vec, + /// Occupied cores. + availability_cores: Vec>, +} + enum RuntimeApiRequest { /// Get the current validator set. Validators(ResponseChannel>), + /// Get the assignments of validators to cores, upcoming parachains. + SchedulerRoster(ResponseChannel), /// Get a signing context for bitfields and statements. SigningContext(ResponseChannel), /// Get the validation code for a specific para, assuming execution under given block number, and @@ -270,10 +285,26 @@ enum StatementDistributionMessage { Various modules request that the [Candidate Validation subsystem](../node/utility/candidate-validation.md) validate a block with this message ```rust + +/// Result of the validation of the candidate. +enum ValidationResult { + /// Candidate is valid. + Valid, + /// Candidate is invalid. + Invalid, +} + enum CandidateValidationMessage { /// Validate a candidate with provided parameters. Returns `Err` if an only if an internal - /// error is encountered. A bad candidate will return `Ok(false)`, while a good one will - /// return `Ok(true)`. - Validate(ValidationCode, CandidateReceipt, PoV, ResponseChannel>), + /// error is encountered. + /// In case no internal error was encontered it returns a tuple containing the result of + /// validation and `GlobalValidationSchedule` and `LocalValidationData` structures that + /// may be used by the caller to make the candidate available. + /// A bad candidate will return `Ok((ValidationResult::Invalid, _, _)`, while a good one will + /// return `Ok((ValidationResult::Valid, _, _))`. + Validate( + Hash, CandidateReceipt, HeadData, PoV, ResponseChannel< + Result<(ValidationResult, GlobalValidationSchedule, LocalValidationData)> + >), } ``` diff --git a/runtime/parachains/src/inclusion.rs b/runtime/parachains/src/inclusion.rs index 5819e3a06c47..33a5e2d1e919 100644 --- a/runtime/parachains/src/inclusion.rs +++ b/runtime/parachains/src/inclusion.rs @@ -25,7 +25,7 @@ use primitives::{ parachain::{ ValidatorId, AbridgedCandidateReceipt, ValidatorIndex, Id as ParaId, AvailabilityBitfield as AvailabilityBitfield, SignedAvailabilityBitfields, SigningContext, - BackedCandidate, + BackedCandidate, CoreIndex, GroupIndex, CoreAssignment, }, }; use frame_support::{ @@ -38,7 +38,7 @@ use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec}; use sp_staking::SessionIndex; use sp_runtime::{DispatchError, traits::{One, Saturating}}; -use crate::{configuration, paras, scheduler::{CoreIndex, GroupIndex, CoreAssignment}}; +use crate::{configuration, paras}; /// A bitfield signed by a validator indicating that it is keeping its piece of the erasure-coding /// for any backed candidates referred to by a `1` bit available. @@ -498,7 +498,7 @@ mod tests { use primitives::{BlockNumber, Hash}; use primitives::parachain::{ SignedAvailabilityBitfield, CompactStatement as Statement, ValidityAttestation, CollatorId, - CandidateCommitments, SignedStatement, + CandidateCommitments, SignedStatement, AssignmentKind, }; use frame_support::traits::{OnFinalize, OnInitialize}; use keyring::Sr25519Keyring; @@ -510,7 +510,6 @@ mod tests { use crate::initializer::SessionChangeNotification; use crate::configuration::HostConfiguration; use crate::paras::ParaGenesisArgs; - use crate::scheduler::AssignmentKind; fn default_config() -> HostConfiguration { let mut config = HostConfiguration::default(); diff --git a/runtime/parachains/src/scheduler.rs b/runtime/parachains/src/scheduler.rs index 212c782d6463..772ab25cf4fd 100644 --- a/runtime/parachains/src/scheduler.rs +++ b/runtime/parachains/src/scheduler.rs @@ -38,7 +38,10 @@ use sp_std::prelude::*; use sp_std::convert::TryInto; use primitives::{ - parachain::{Id as ParaId, CollatorId, ValidatorIndex}, + parachain::{ + Id as ParaId, ValidatorIndex, CoreAssignment, CoreOccupied, CoreIndex, AssignmentKind, + GroupIndex, ParathreadClaim, ParathreadEntry, + }, }; use frame_support::{ decl_storage, decl_module, decl_error, @@ -52,41 +55,6 @@ use rand_chacha::ChaCha20Rng; use crate::{configuration, paras, initializer::SessionChangeNotification}; -/// The unique (during session) index of a core. -#[derive(Encode, Decode, Default, PartialOrd, Ord, Eq, PartialEq, Clone, Copy)] -#[cfg_attr(test, derive(Debug))] -pub struct CoreIndex(u32); - -impl From for CoreIndex { - fn from(i: u32) -> CoreIndex { - CoreIndex(i) - } -} - -/// The unique (during session) index of a validator group. -#[derive(Encode, Decode, Default, Clone, Copy)] -#[cfg_attr(test, derive(PartialEq, Debug))] -pub struct GroupIndex(u32); - -impl From for GroupIndex { - fn from(i: u32) -> GroupIndex { - GroupIndex(i) - } -} - -/// A claim on authoring the next block for a given parathread. -#[derive(Clone, Encode, Decode, Default)] -#[cfg_attr(test, derive(PartialEq, Debug))] -pub struct ParathreadClaim(pub ParaId, pub CollatorId); - -/// An entry tracking a claim to ensure it does not pass the maximum number of retries. -#[derive(Clone, Encode, Decode, Default)] -#[cfg_attr(test, derive(PartialEq, Debug))] -pub struct ParathreadEntry { - claim: ParathreadClaim, - retries: u32, -} - /// A queued parathread entry, pre-assigned to a core. #[derive(Encode, Decode, Default)] #[cfg_attr(test, derive(PartialEq, Debug))] @@ -125,58 +93,6 @@ impl ParathreadClaimQueue { } } -/// What is occupying a specific availability core. -#[derive(Clone, Encode, Decode)] -#[cfg_attr(test, derive(PartialEq, Debug))] -pub(crate) enum CoreOccupied { - Parathread(ParathreadEntry), - Parachain, -} - -/// The assignment type. -#[derive(Clone, Encode, Decode)] -#[cfg_attr(test, derive(PartialEq, Debug))] -pub enum AssignmentKind { - Parachain, - Parathread(CollatorId, u32), -} - -/// How a free core is scheduled to be assigned. -#[derive(Clone, Encode, Decode)] -#[cfg_attr(test, derive(PartialEq, Debug))] -pub struct CoreAssignment { - /// The core that is assigned. - pub core: CoreIndex, - /// The unique ID of the para that is assigned to the core. - pub para_id: ParaId, - /// The kind of the assignment. - pub kind: AssignmentKind, - /// The index of the validator group assigned to the core. - pub group_idx: GroupIndex, -} - -impl CoreAssignment { - /// Get the ID of a collator who is required to collate this block. - pub(crate) fn required_collator(&self) -> Option<&CollatorId> { - match self.kind { - AssignmentKind::Parachain => None, - AssignmentKind::Parathread(ref id, _) => Some(id), - } - } - - fn to_core_occupied(&self) -> CoreOccupied { - match self.kind { - AssignmentKind::Parachain => CoreOccupied::Parachain, - AssignmentKind::Parathread(ref collator, retries) => CoreOccupied::Parathread( - ParathreadEntry { - claim: ParathreadClaim(self.para_id, collator.clone()), - retries, - } - ), - } - } -} - /// Reasons a core might be freed pub enum FreedReason { /// The core's work concluded and the parablock assigned to it is considered available. @@ -670,7 +586,7 @@ impl Module { mod tests { use super::*; - use primitives::{BlockNumber, parachain::ValidatorId}; + use primitives::{BlockNumber, parachain::{CollatorId, ValidatorId}}; use frame_support::traits::{OnFinalize, OnInitialize}; use keyring::Sr25519Keyring; diff --git a/statement-table/src/generic.rs b/statement-table/src/generic.rs index 83cae9daf26b..11c6a3c02478 100644 --- a/statement-table/src/generic.rs +++ b/statement-table/src/generic.rs @@ -28,6 +28,8 @@ use std::collections::hash_map::{HashMap, Entry}; use std::hash::Hash; use std::fmt::Debug; +use primitives::parachain::{ValidityAttestation as PrimitiveValidityAttestation, ValidatorSignature}; + use codec::{Encode, Decode}; /// Context for the statement table. @@ -98,7 +100,7 @@ pub enum ValidityDoubleVote { /// Implicit vote by issuing and explicitly voting invalidity IssuedAndInvalidity((C, S), (D, S)), /// Direct votes for validity and invalidity - ValidityAndInvalidity(D, S, S), + ValidityAndInvalidity(C, S, S), } /// Misbehavior: multiple signatures on same statement. @@ -180,6 +182,15 @@ pub enum ValidityAttestation { Explicit(S), } +impl Into for ValidityAttestation { + fn into(self) -> PrimitiveValidityAttestation { + match self { + Self::Implicit(s) => PrimitiveValidityAttestation::Implicit(s), + Self::Explicit(s) => PrimitiveValidityAttestation::Explicit(s), + } + } +} + /// An attested-to candidate. #[derive(Clone, PartialEq, Decode, Encode)] pub struct AttestedCandidate { @@ -550,7 +561,7 @@ impl Table { // valid vote conflicting with invalid vote (ValidityVote::Valid(good), ValidityVote::Invalid(bad)) | (ValidityVote::Invalid(bad), ValidityVote::Valid(good)) => - make_vdv(ValidityDoubleVote::ValidityAndInvalidity(digest, good, bad)), + make_vdv(ValidityDoubleVote::ValidityAndInvalidity(votes.candidate.clone(), good, bad)), // two signatures on same candidate (ValidityVote::Issued(a), ValidityVote::Issued(b)) => @@ -817,7 +828,7 @@ mod tests { assert_eq!( table.detected_misbehavior.get(&AuthorityId(2)).unwrap(), &Misbehavior::ValidityDoubleVote(ValidityDoubleVote::ValidityAndInvalidity( - candidate_digest, + Candidate(2, 100), Signature(2), Signature(2), ))