diff --git a/Cargo.lock b/Cargo.lock index 84872ce141da4..a9fafd1bbafd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,7 +226,7 @@ dependencies = [ "fastrand", "futures-lite", "libc", - "log 0.4.14", + "log 0.4.16", "nb-connect", "once_cell", "parking", @@ -272,7 +272,7 @@ dependencies = [ "futures-lite", "gloo-timers", "kv-log-macro", - "log 0.4.14", + "log 0.4.16", "memchr", "num_cpus", "once_cell", @@ -474,7 +474,7 @@ dependencies = [ "futures 0.3.21", "futures-timer", "hex", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parking_lot 0.12.0", "sc-chain-spec", @@ -519,7 +519,7 @@ dependencies = [ "jsonrpc-core-client", "jsonrpc-derive", "jsonrpc-pubsub", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parking_lot 0.12.0", "sc-rpc", @@ -539,7 +539,7 @@ dependencies = [ "env_logger 0.9.0", "hex", "hex-literal", - "log 0.4.14", + "log 0.4.16", "tiny-keccak", ] @@ -1171,7 +1171,7 @@ dependencies = [ "cranelift-codegen-shared 0.76.0", "cranelift-entity 0.76.0", "gimli 0.25.0", - "log 0.4.14", + "log 0.4.16", "regalloc 0.0.31", "smallvec 1.8.0", "target-lexicon", @@ -1188,7 +1188,7 @@ dependencies = [ "cranelift-codegen-shared 0.82.3", "cranelift-entity 0.82.3", "gimli 0.26.1", - "log 0.4.14", + "log 0.4.16", "regalloc 0.0.34", "smallvec 1.8.0", "target-lexicon", @@ -1247,7 +1247,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "279afcc0d3e651b773f94837c3d581177b348c8d69e928104b2e9fccb226f921" dependencies = [ "cranelift-codegen 0.76.0", - "log 0.4.14", + "log 0.4.16", "smallvec 1.8.0", "target-lexicon", ] @@ -1259,7 +1259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a006e3e32d80ce0e4ba7f1f9ddf66066d052a8c884a110b91d05404d6ce26dce" dependencies = [ "cranelift-codegen 0.82.3", - "log 0.4.14", + "log 0.4.16", "smallvec 1.8.0", "target-lexicon", ] @@ -1285,7 +1285,7 @@ dependencies = [ "cranelift-entity 0.82.3", "cranelift-frontend 0.82.3", "itertools", - "log 0.4.14", + "log 0.4.16", "smallvec 1.8.0", "wasmparser 0.83.0", "wasmtime-types", @@ -1937,7 +1937,7 @@ checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" dependencies = [ "atty", "humantime 1.3.0", - "log 0.4.14", + "log 0.4.16", "regex", "termcolor", ] @@ -1948,7 +1948,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ - "log 0.4.14", + "log 0.4.16", "regex", ] @@ -1960,7 +1960,7 @@ checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" dependencies = [ "atty", "humantime 2.1.0", - "log 0.4.14", + "log 0.4.16", "regex", "termcolor", ] @@ -2054,7 +2054,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fdbe0d94371f9ce939b555dd342d0686cc4c0cadbcd4b61d70af5ff97eb4126" dependencies = [ "env_logger 0.7.1", - "log 0.4.14", + "log 0.4.16", ] [[package]] @@ -2066,7 +2066,7 @@ dependencies = [ "either", "futures 0.3.21", "futures-timer", - "log 0.4.14", + "log 0.4.16", "num-traits", "parity-scale-codec", "parking_lot 0.11.2", @@ -2151,7 +2151,7 @@ dependencies = [ "frame-system", "hex-literal", "linregress", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "paste 1.0.6", "scale-info", @@ -2182,7 +2182,7 @@ dependencies = [ "itertools", "kvdb", "linked-hash-map", - "log 0.4.14", + "log 0.4.16", "memory-db", "parity-scale-codec", "prettytable-rs", @@ -2236,6 +2236,7 @@ dependencies = [ "frame-election-provider-solution-type", "frame-support", "frame-system", + "log 0.4.16", "parity-scale-codec", "rand 0.7.3", "scale-info", @@ -2307,7 +2308,7 @@ dependencies = [ "frame-system", "impl-trait-for-tuples", "k256", - "log 0.4.14", + "log 0.4.16", "once_cell", "parity-scale-codec", "parity-util-mem", @@ -2411,7 +2412,7 @@ version = "4.0.0-dev" dependencies = [ "criterion", "frame-support", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "scale-info", "serde", @@ -2746,7 +2747,7 @@ dependencies = [ "bitflags", "libc", "libgit2-sys", - "log 0.4.14", + "log 0.4.16", "url 2.2.1", ] @@ -2765,7 +2766,7 @@ dependencies = [ "aho-corasick", "bstr", "fnv", - "log 0.4.14", + "log 0.4.16", "regex", ] @@ -2824,7 +2825,7 @@ version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d6a30320f094710245150395bc763ad23128d6a1ebbad7594dc4164b62c56b" dependencies = [ - "log 0.4.14", + "log 0.4.16", "pest", "pest_derive", "quick-error 2.0.0", @@ -3061,7 +3062,7 @@ dependencies = [ "ct-logs", "futures-util", "hyper 0.14.16", - "log 0.4.14", + "log 0.4.16", "rustls 0.19.1", "rustls-native-certs 0.5.0", "tokio", @@ -3143,7 +3144,7 @@ dependencies = [ "if-addrs", "ipnet", "libc", - "log 0.4.14", + "log 0.4.16", "winapi 0.3.9", ] @@ -3295,7 +3296,7 @@ dependencies = [ "hyper-tls", "jsonrpc-core", "jsonrpc-pubsub", - "log 0.4.14", + "log 0.4.16", "serde", "serde_json", "tokio", @@ -3312,7 +3313,7 @@ dependencies = [ "futures 0.3.21", "futures-executor", "futures-util", - "log 0.4.14", + "log 0.4.16", "serde", "serde_derive", "serde_json", @@ -3350,7 +3351,7 @@ dependencies = [ "hyper 0.14.16", "jsonrpc-core", "jsonrpc-server-utils", - "log 0.4.14", + "log 0.4.16", "net2", "parking_lot 0.11.2", "unicase 2.6.0", @@ -3365,7 +3366,7 @@ dependencies = [ "futures 0.3.21", "jsonrpc-core", "jsonrpc-server-utils", - "log 0.4.14", + "log 0.4.16", "parity-tokio-ipc", "parking_lot 0.11.2", "tower-service", @@ -3380,7 +3381,7 @@ dependencies = [ "futures 0.3.21", "jsonrpc-core", "lazy_static", - "log 0.4.14", + "log 0.4.16", "parking_lot 0.11.2", "rand 0.7.3", "serde", @@ -3397,7 +3398,7 @@ dependencies = [ "globset", "jsonrpc-core", "lazy_static", - "log 0.4.14", + "log 0.4.16", "tokio", "tokio-stream", "tokio-util 0.6.7", @@ -3413,7 +3414,7 @@ dependencies = [ "futures 0.3.21", "jsonrpc-core", "jsonrpc-server-utils", - "log 0.4.14", + "log 0.4.16", "parity-ws", "parking_lot 0.11.2", "slab", @@ -3557,7 +3558,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" dependencies = [ - "log 0.4.14", + "log 0.4.16", ] [[package]] @@ -3589,7 +3590,7 @@ checksum = "ca7fbdfd71cd663dceb0faf3367a99f8cf724514933e9867cec4995b6027cbc1" dependencies = [ "fs-swap", "kvdb", - "log 0.4.14", + "log 0.4.16", "num_cpus", "owning_ref", "parity-util-mem", @@ -3723,7 +3724,7 @@ dependencies = [ "futures-timer", "lazy_static", "libsecp256k1", - "log 0.4.14", + "log 0.4.16", "multiaddr", "multihash 0.14.0", "multistream-select", @@ -3762,7 +3763,7 @@ dependencies = [ "async-std-resolver", "futures 0.3.21", "libp2p-core", - "log 0.4.14", + "log 0.4.16", "smallvec 1.8.0", "trust-dns-resolver", ] @@ -3778,7 +3779,7 @@ dependencies = [ "futures 0.3.21", "libp2p-core", "libp2p-swarm", - "log 0.4.14", + "log 0.4.16", "prost", "prost-build", "rand 0.7.3", @@ -3800,7 +3801,7 @@ dependencies = [ "hex_fmt", "libp2p-core", "libp2p-swarm", - "log 0.4.14", + "log 0.4.16", "prost", "prost-build", "rand 0.7.3", @@ -3820,7 +3821,7 @@ dependencies = [ "futures 0.3.21", "libp2p-core", "libp2p-swarm", - "log 0.4.14", + "log 0.4.16", "lru 0.6.6", "prost", "prost-build", @@ -3842,7 +3843,7 @@ dependencies = [ "futures 0.3.21", "libp2p-core", "libp2p-swarm", - "log 0.4.14", + "log 0.4.16", "prost", "prost-build", "rand 0.7.3", @@ -3868,7 +3869,7 @@ dependencies = [ "lazy_static", "libp2p-core", "libp2p-swarm", - "log 0.4.14", + "log 0.4.16", "rand 0.8.4", "smallvec 1.8.0", "socket2 0.4.4", @@ -3899,7 +3900,7 @@ dependencies = [ "bytes 1.1.0", "futures 0.3.21", "libp2p-core", - "log 0.4.14", + "log 0.4.16", "nohash-hasher", "parking_lot 0.11.2", "rand 0.7.3", @@ -3918,7 +3919,7 @@ dependencies = [ "futures 0.3.21", "lazy_static", "libp2p-core", - "log 0.4.14", + "log 0.4.16", "prost", "prost-build", "rand 0.8.4", @@ -3938,7 +3939,7 @@ dependencies = [ "futures 0.3.21", "libp2p-core", "libp2p-swarm", - "log 0.4.14", + "log 0.4.16", "rand 0.7.3", "void", "wasm-timer", @@ -3954,7 +3955,7 @@ dependencies = [ "bytes 1.1.0", "futures 0.3.21", "libp2p-core", - "log 0.4.14", + "log 0.4.16", "prost", "prost-build", "unsigned-varint 0.7.0", @@ -3968,7 +3969,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f1a458bbda880107b5b36fcb9b5a1ef0c329685da0e203ed692a8ebe64cc92c" dependencies = [ "futures 0.3.21", - "log 0.4.14", + "log 0.4.16", "pin-project 1.0.10", "rand 0.7.3", "salsa20", @@ -3987,7 +3988,7 @@ dependencies = [ "futures-timer", "libp2p-core", "libp2p-swarm", - "log 0.4.14", + "log 0.4.16", "pin-project 1.0.10", "prost", "prost-build", @@ -4009,7 +4010,7 @@ dependencies = [ "futures 0.3.21", "libp2p-core", "libp2p-swarm", - "log 0.4.14", + "log 0.4.16", "prost", "prost-build", "rand 0.8.4", @@ -4031,7 +4032,7 @@ dependencies = [ "futures 0.3.21", "libp2p-core", "libp2p-swarm", - "log 0.4.14", + "log 0.4.16", "lru 0.7.5", "rand 0.7.3", "smallvec 1.8.0", @@ -4048,7 +4049,7 @@ dependencies = [ "either", "futures 0.3.21", "libp2p-core", - "log 0.4.14", + "log 0.4.16", "rand 0.7.3", "smallvec 1.8.0", "void", @@ -4078,7 +4079,7 @@ dependencies = [ "ipnet", "libc", "libp2p-core", - "log 0.4.14", + "log 0.4.16", "socket2 0.4.4", ] @@ -4091,7 +4092,7 @@ dependencies = [ "async-std", "futures 0.3.21", "libp2p-core", - "log 0.4.14", + "log 0.4.16", ] [[package]] @@ -4118,7 +4119,7 @@ dependencies = [ "futures 0.3.21", "futures-rustls", "libp2p-core", - "log 0.4.14", + "log 0.4.16", "quicksink", "rw-stream-sink", "soketto", @@ -4287,14 +4288,14 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" dependencies = [ - "log 0.4.14", + "log 0.4.16", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" dependencies = [ "cfg-if 1.0.0", "value-bag", @@ -4528,7 +4529,7 @@ dependencies = [ "iovec", "kernel32-sys", "libc", - "log 0.4.14", + "log 0.4.16", "miow 0.2.2", "net2", "slab", @@ -4542,7 +4543,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" dependencies = [ "libc", - "log 0.4.14", + "log 0.4.16", "miow 0.3.6", "ntapi", "winapi 0.3.9", @@ -4555,7 +4556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" dependencies = [ "lazycell", - "log 0.4.14", + "log 0.4.16", "mio 0.6.23", "slab", ] @@ -4675,7 +4676,7 @@ checksum = "7d91ec0a2440aaff5f78ec35631a7027d50386c6163aa975f7caa0d5da4b6ff8" dependencies = [ "bytes 1.1.0", "futures 0.3.21", - "log 0.4.14", + "log 0.4.16", "pin-project 1.0.10", "smallvec 1.8.0", "unsigned-varint 0.7.0", @@ -4727,7 +4728,7 @@ checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" dependencies = [ "lazy_static", "libc", - "log 0.4.14", + "log 0.4.16", "openssl", "openssl-probe", "openssl-sys", @@ -4784,7 +4785,7 @@ dependencies = [ "kvdb", "kvdb-rocksdb", "lazy_static", - "log 0.4.14", + "log 0.4.16", "node-primitives", "node-runtime", "node-testing", @@ -4822,7 +4823,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "futures 0.3.21", "hex-literal", - "log 0.4.14", + "log 0.4.16", "nix", "node-executor", "node-inspect", @@ -4996,7 +4997,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex-literal", - "log 0.4.14", + "log 0.4.16", "node-primitives", "pallet-asset-tx-payment", "pallet-assets", @@ -5167,7 +5168,7 @@ dependencies = [ "frame-system", "fs_extra", "futures 0.3.21", - "log 0.4.14", + "log 0.4.16", "node-executor", "node-primitives", "node-runtime", @@ -5550,7 +5551,7 @@ dependencies = [ "frame-election-provider-support", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-authorship", "pallet-balances", "pallet-offences", @@ -5579,7 +5580,7 @@ dependencies = [ "frame-election-provider-support", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-balances", "parity-scale-codec", "scale-info", @@ -5607,7 +5608,7 @@ dependencies = [ "frame-election-provider-support", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-bags-list", "pallet-staking", "remote-externalities", @@ -5626,7 +5627,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-transaction-payment", "parity-scale-codec", "scale-info", @@ -5664,7 +5665,7 @@ dependencies = [ "frame-system", "hex", "hex-literal", - "log 0.4.14", + "log 0.4.16", "pallet-beefy", "pallet-mmr", "pallet-session", @@ -5685,7 +5686,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-balances", "pallet-treasury", "parity-scale-codec", @@ -5703,7 +5704,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-balances", "pallet-bounties", "pallet-treasury", @@ -5722,7 +5723,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "scale-info", "sp-core", @@ -5742,7 +5743,7 @@ dependencies = [ "frame-support", "frame-system", "hex-literal", - "log 0.4.14", + "log 0.4.16", "pallet-balances", "pallet-contracts-primitives", "pallet-contracts-proc-macro", @@ -5866,7 +5867,7 @@ dependencies = [ "frame-election-provider-support", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-balances", "pallet-election-provider-support-benchmarking", "parity-scale-codec", @@ -5903,7 +5904,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-balances", "parity-scale-codec", "scale-info", @@ -5922,7 +5923,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-balances", "parity-scale-codec", "scale-info", @@ -5939,7 +5940,7 @@ dependencies = [ "frame-support", "frame-system", "lite-json", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "scale-info", "sp-core", @@ -5990,7 +5991,7 @@ dependencies = [ "frame-election-provider-support", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-authorship", "pallet-balances", "pallet-offences", @@ -6035,7 +6036,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-authorship", "pallet-session", "parity-scale-codec", @@ -6089,7 +6090,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "scale-info", "sp-core", @@ -6171,7 +6172,7 @@ version = "4.0.0-dev" dependencies = [ "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "scale-info", "sp-core", @@ -6186,7 +6187,7 @@ version = "4.0.0-dev" dependencies = [ "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-balances", "parity-scale-codec", "scale-info", @@ -6330,7 +6331,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-preimage", "parity-scale-codec", "scale-info", @@ -6363,7 +6364,7 @@ dependencies = [ "frame-support", "frame-system", "impl-trait-for-tuples", - "log 0.4.14", + "log 0.4.16", "pallet-timestamp", "parity-scale-codec", "scale-info", @@ -6424,7 +6425,7 @@ dependencies = [ "frame-election-provider-support", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-authorship", "pallet-bags-list", "pallet-balances", @@ -6461,7 +6462,7 @@ dependencies = [ name = "pallet-staking-reward-fn" version = "4.0.0-dev" dependencies = [ - "log 0.4.14", + "log 0.4.16", "sp-arithmetic", ] @@ -6472,7 +6473,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-balances", "parity-scale-codec", "parking_lot 0.12.0", @@ -6525,7 +6526,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "scale-info", "sp-core", @@ -6543,7 +6544,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-balances", "pallet-treasury", "parity-scale-codec", @@ -6645,7 +6646,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-balances", "parity-scale-codec", "scale-info", @@ -6678,7 +6679,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log 0.4.14", + "log 0.4.16", "pallet-balances", "parity-scale-codec", "scale-info", @@ -6717,7 +6718,7 @@ dependencies = [ "fs2", "hex", "libc", - "log 0.4.14", + "log 0.4.16", "lz4", "memmap2 0.2.1", "parking_lot 0.11.2", @@ -6765,7 +6766,7 @@ checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6" dependencies = [ "futures 0.3.21", "libc", - "log 0.4.14", + "log 0.4.16", "rand 0.7.3", "tokio", "winapi 0.3.9", @@ -6822,7 +6823,7 @@ dependencies = [ "byteorder", "bytes 0.4.12", "httparse", - "log 0.4.14", + "log 0.4.16", "mio 0.6.23", "mio-extras", "rand 0.7.3", @@ -7131,7 +7132,7 @@ checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4" dependencies = [ "cfg-if 0.1.10", "libc", - "log 0.4.14", + "log 0.4.16", "wepoll-sys", "winapi 0.3.9", ] @@ -7323,7 +7324,7 @@ dependencies = [ "heck 0.3.2", "itertools", "lazy_static", - "log 0.4.14", + "log 0.4.16", "multimap", "petgraph", "prost", @@ -7404,7 +7405,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" dependencies = [ "env_logger 0.8.4", - "log 0.4.14", + "log 0.4.16", "rand 0.8.4", ] @@ -7752,7 +7753,7 @@ version = "0.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5" dependencies = [ - "log 0.4.14", + "log 0.4.16", "rustc-hash", "smallvec 1.8.0", ] @@ -7763,7 +7764,7 @@ version = "0.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62446b1d3ebf980bdc68837700af1d77b37bc430e524bf95319c6eada2a4cc02" dependencies = [ - "log 0.4.14", + "log 0.4.16", "rustc-hash", "smallvec 1.8.0", ] @@ -7826,7 +7827,7 @@ dependencies = [ "env_logger 0.9.0", "frame-support", "jsonrpsee", - "log 0.4.14", + "log 0.4.16", "pallet-elections-phragmen", "parity-scale-codec", "serde", @@ -8012,7 +8013,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" dependencies = [ "base64 0.13.0", - "log 0.4.14", + "log 0.4.16", "ring", "sct 0.6.0", "webpki 0.21.4", @@ -8024,7 +8025,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" dependencies = [ - "log 0.4.14", + "log 0.4.16", "ring", "sct 0.7.0", "webpki 0.22.0", @@ -8123,7 +8124,7 @@ dependencies = [ name = "sc-allocator" version = "4.1.0-dev" dependencies = [ - "log 0.4.14", + "log 0.4.16", "sp-core", "sp-wasm-interface", "thiserror", @@ -8138,7 +8139,7 @@ dependencies = [ "futures-timer", "ip_network", "libp2p", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "prost", "prost-build", @@ -8164,7 +8165,7 @@ version = "0.10.0-dev" dependencies = [ "futures 0.3.21", "futures-timer", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parking_lot 0.12.0", "sc-block-builder", @@ -8235,7 +8236,7 @@ dependencies = [ "futures 0.3.21", "hex", "libp2p", - "log 0.4.14", + "log 0.4.16", "names", "parity-scale-codec", "rand 0.7.3", @@ -8270,7 +8271,7 @@ dependencies = [ "fnv", "futures 0.3.21", "hash-db", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parking_lot 0.12.0", "sc-executor", @@ -8302,7 +8303,7 @@ dependencies = [ "kvdb-memorydb", "kvdb-rocksdb", "linked-hash-map", - "log 0.4.14", + "log 0.4.16", "parity-db", "parity-scale-codec", "parking_lot 0.12.0", @@ -8329,7 +8330,7 @@ dependencies = [ "futures 0.3.21", "futures-timer", "libp2p", - "log 0.4.14", + "log 0.4.16", "parking_lot 0.12.0", "sc-client-api", "sc-utils", @@ -8351,7 +8352,7 @@ version = "0.10.0-dev" dependencies = [ "async-trait", "futures 0.3.21", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parking_lot 0.12.0", "sc-block-builder", @@ -8389,7 +8390,7 @@ dependencies = [ "async-trait", "fork-tree", "futures 0.3.21", - "log 0.4.14", + "log 0.4.16", "merlin", "num-bigint", "num-rational 0.2.4", @@ -8483,7 +8484,7 @@ dependencies = [ "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "sc-basic-authorship", "sc-client-api", @@ -8519,7 +8520,7 @@ dependencies = [ "async-trait", "futures 0.3.21", "futures-timer", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parking_lot 0.12.0", "sc-client-api", @@ -8543,7 +8544,7 @@ dependencies = [ "async-trait", "futures 0.3.21", "futures-timer", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "sc-client-api", "sc-consensus", @@ -8631,7 +8632,7 @@ dependencies = [ name = "sc-executor-wasmi" version = "0.10.0-dev" dependencies = [ - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "sc-allocator", "sc-executor-common", @@ -8648,7 +8649,7 @@ version = "0.10.0-dev" dependencies = [ "cfg-if 1.0.0", "libc", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parity-wasm 0.42.2", "sc-allocator", @@ -8675,7 +8676,7 @@ dependencies = [ "futures 0.3.21", "futures-timer", "hex", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parking_lot 0.12.0", "rand 0.8.4", @@ -8719,7 +8720,7 @@ dependencies = [ "jsonrpc-core-client", "jsonrpc-derive", "jsonrpc-pubsub", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "sc-block-builder", "sc-client-api", @@ -8743,7 +8744,7 @@ dependencies = [ "ansi_term", "futures 0.3.21", "futures-timer", - "log 0.4.14", + "log 0.4.16", "parity-util-mem", "sc-client-api", "sc-network", @@ -8788,7 +8789,7 @@ dependencies = [ "libp2p", "linked-hash-map", "linked_hash_set", - "log 0.4.14", + "log 0.4.16", "lru 0.7.5", "parity-scale-codec", "parking_lot 0.12.0", @@ -8832,7 +8833,7 @@ dependencies = [ "futures 0.3.21", "futures-timer", "libp2p", - "log 0.4.14", + "log 0.4.16", "lru 0.7.5", "quickcheck", "sc-network", @@ -8851,7 +8852,7 @@ dependencies = [ "futures 0.3.21", "futures-timer", "libp2p", - "log 0.4.14", + "log 0.4.16", "parking_lot 0.12.0", "rand 0.7.3", "sc-block-builder", @@ -8911,7 +8912,7 @@ version = "4.0.0-dev" dependencies = [ "futures 0.3.21", "libp2p", - "log 0.4.14", + "log 0.4.16", "rand 0.7.3", "sc-utils", "serde_json", @@ -8922,7 +8923,7 @@ dependencies = [ name = "sc-proposer-metrics" version = "0.10.0-dev" dependencies = [ - "log 0.4.14", + "log 0.4.16", "substrate-prometheus-endpoint", ] @@ -8936,7 +8937,7 @@ dependencies = [ "jsonrpc-core", "jsonrpc-pubsub", "lazy_static", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parking_lot 0.12.0", "sc-block-builder", @@ -8972,7 +8973,7 @@ dependencies = [ "jsonrpc-core-client", "jsonrpc-derive", "jsonrpc-pubsub", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parking_lot 0.12.0", "sc-chain-spec", @@ -8998,7 +8999,7 @@ dependencies = [ "jsonrpc-ipc-server", "jsonrpc-pubsub", "jsonrpc-ws-server", - "log 0.4.14", + "log 0.4.16", "serde_json", "substrate-prometheus-endpoint", "tokio", @@ -9031,7 +9032,7 @@ dependencies = [ "hash-db", "jsonrpc-core", "jsonrpc-pubsub", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parity-util-mem", "parking_lot 0.12.0", @@ -9093,7 +9094,7 @@ dependencies = [ "futures 0.3.21", "hex", "hex-literal", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parking_lot 0.12.0", "sc-block-builder", @@ -9125,7 +9126,7 @@ dependencies = [ name = "sc-state-db" version = "0.10.0-dev" dependencies = [ - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parity-util-mem", "parity-util-mem-derive", @@ -9160,7 +9161,7 @@ version = "6.0.0-dev" dependencies = [ "futures 0.3.21", "libc", - "log 0.4.14", + "log 0.4.16", "rand 0.7.3", "rand_pcg 0.2.1", "regex", @@ -9179,7 +9180,7 @@ dependencies = [ "chrono", "futures 0.3.21", "libp2p", - "log 0.4.14", + "log 0.4.16", "parking_lot 0.12.0", "pin-project 1.0.10", "rand 0.7.3", @@ -9199,7 +9200,7 @@ dependencies = [ "criterion", "lazy_static", "libc", - "log 0.4.14", + "log 0.4.16", "once_cell", "parking_lot 0.12.0", "regex", @@ -9240,7 +9241,7 @@ dependencies = [ "futures-timer", "hex", "linked-hash-map", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parity-util-mem", "parking_lot 0.12.0", @@ -9269,7 +9270,7 @@ name = "sc-transaction-pool-api" version = "4.0.0-dev" dependencies = [ "futures 0.3.21", - "log 0.4.14", + "log 0.4.16", "serde", "sp-blockchain", "sp-runtime", @@ -9283,7 +9284,7 @@ dependencies = [ "futures 0.3.21", "futures-timer", "lazy_static", - "log 0.4.14", + "log 0.4.16", "parking_lot 0.12.0", "prometheus", "tokio-test", @@ -9766,7 +9767,7 @@ dependencies = [ "flate2", "futures 0.3.21", "httparse", - "log 0.4.14", + "log 0.4.16", "rand 0.8.4", "sha-1 0.9.4", ] @@ -9776,7 +9777,7 @@ name = "sp-api" version = "4.0.0-dev" dependencies = [ "hash-db", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "sp-api-proc-macro", "sp-core", @@ -9805,7 +9806,7 @@ version = "2.0.1" dependencies = [ "criterion", "futures 0.3.21", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "rustversion", "sc-block-builder", @@ -9910,7 +9911,7 @@ name = "sp-blockchain" version = "4.0.0-dev" dependencies = [ "futures 0.3.21", - "log 0.4.14", + "log 0.4.16", "lru 0.7.5", "parity-scale-codec", "parking_lot 0.12.0", @@ -9929,7 +9930,7 @@ dependencies = [ "async-trait", "futures 0.3.21", "futures-timer", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "sp-core", "sp-inherents", @@ -10034,7 +10035,7 @@ dependencies = [ "impl-serde", "lazy_static", "libsecp256k1", - "log 0.4.14", + "log 0.4.16", "merlin", "num-traits", "parity-scale-codec", @@ -10120,7 +10121,7 @@ name = "sp-finality-grandpa" version = "4.0.0-dev" dependencies = [ "finality-grandpa", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "scale-info", "serde", @@ -10153,7 +10154,7 @@ dependencies = [ "futures 0.3.21", "hash-db", "libsecp256k1", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parking_lot 0.12.0", "secp256k1", @@ -10211,7 +10212,7 @@ name = "sp-mmr-primitives" version = "4.0.0-dev" dependencies = [ "hex-literal", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "serde", "sp-api", @@ -10284,7 +10285,7 @@ dependencies = [ "either", "hash256-std-hasher", "impl-trait-for-tuples", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "parity-util-mem", "paste 1.0.6", @@ -10380,7 +10381,7 @@ name = "sp-sandbox" version = "0.10.0-dev" dependencies = [ "assert_matches", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "sp-core", "sp-io", @@ -10427,7 +10428,7 @@ version = "0.12.0" dependencies = [ "hash-db", "hex-literal", - "log 0.4.14", + "log 0.4.16", "num-traits", "parity-scale-codec", "parking_lot 0.12.0", @@ -10465,7 +10466,7 @@ dependencies = [ name = "sp-tasks" version = "4.0.0-dev" dependencies = [ - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "sp-core", "sp-externalities", @@ -10492,7 +10493,7 @@ version = "4.0.0-dev" dependencies = [ "async-trait", "futures-timer", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "sp-api", "sp-inherents", @@ -10525,7 +10526,7 @@ name = "sp-transaction-storage-proof" version = "4.0.0-dev" dependencies = [ "async-trait", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "scale-info", "sp-core", @@ -10587,7 +10588,7 @@ name = "sp-wasm-interface" version = "6.0.0" dependencies = [ "impl-trait-for-tuples", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "sp-std", "wasmi", @@ -10732,7 +10733,7 @@ dependencies = [ "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "sc-client-api", "sc-rpc-api", @@ -10753,7 +10754,7 @@ version = "0.10.0-dev" dependencies = [ "futures-util", "hyper 0.14.16", - "log 0.4.14", + "log 0.4.16", "prometheus", "thiserror", "tokio", @@ -10766,7 +10767,7 @@ dependencies = [ "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "sc-client-api", "sc-rpc-api", @@ -10817,7 +10818,7 @@ dependencies = [ "frame-system", "frame-system-rpc-runtime-api", "futures 0.3.21", - "log 0.4.14", + "log 0.4.16", "memory-db", "pallet-babe", "pallet-timestamp", @@ -11190,7 +11191,7 @@ checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ "bytes 0.4.12", "futures 0.1.31", - "log 0.4.14", + "log 0.4.16", ] [[package]] @@ -11223,7 +11224,7 @@ dependencies = [ "crossbeam-utils 0.7.2", "futures 0.1.31", "lazy_static", - "log 0.4.14", + "log 0.4.16", "mio 0.6.23", "num_cpus", "parking_lot 0.9.0", @@ -11323,7 +11324,7 @@ dependencies = [ "bytes 1.1.0", "futures-core", "futures-sink", - "log 0.4.14", + "log 0.4.16", "pin-project-lite 0.2.6", "tokio", ] @@ -11364,7 +11365,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ "cfg-if 1.0.0", - "log 0.4.14", + "log 0.4.16", "pin-project-lite 0.2.6", "tracing-attributes", "tracing-core", @@ -11407,7 +11408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" dependencies = [ "lazy_static", - "log 0.4.14", + "log 0.4.16", "tracing-core", ] @@ -11480,7 +11481,7 @@ checksum = "d32d034c0d3db64b43c31de38e945f15b40cd4ca6d2dcfc26d4798ce8de4ab83" dependencies = [ "hash-db", "hashbrown 0.12.0", - "log 0.4.14", + "log 0.4.16", "rustc-hex", "smallvec 1.8.0", ] @@ -11520,7 +11521,7 @@ dependencies = [ "idna 0.2.2", "ipnet", "lazy_static", - "log 0.4.14", + "log 0.4.16", "rand 0.8.4", "smallvec 1.8.0", "thiserror", @@ -11538,7 +11539,7 @@ dependencies = [ "futures-util", "ipconfig", "lazy_static", - "log 0.4.14", + "log 0.4.16", "lru-cache", "parking_lot 0.11.2", "resolv-conf", @@ -11559,7 +11560,7 @@ version = "0.10.0-dev" dependencies = [ "clap 3.1.6", "jsonrpsee", - "log 0.4.14", + "log 0.4.16", "parity-scale-codec", "remote-externalities", "sc-chain-spec", @@ -11765,11 +11766,12 @@ dependencies = [ [[package]] name = "value-bag" -version = "1.0.0-alpha.6" +version = "1.0.0-alpha.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b676010e055c99033117c2343b33a40a30b91fecd6c49055ac9cd2d6c305ab1" +checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f" dependencies = [ "ctor", + "version_check 0.9.2", ] [[package]] @@ -11834,7 +11836,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ - "log 0.4.14", + "log 0.4.16", "try-lock", ] @@ -11868,7 +11870,7 @@ checksum = "f34c405b4f0658583dba0c1c7c9b694f3cac32655db463b56c254a1c75269523" dependencies = [ "bumpalo", "lazy_static", - "log 0.4.14", + "log 0.4.16", "proc-macro2", "quote", "syn", @@ -11922,7 +11924,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0c32691b6c7e6c14e7f8fd55361a9088b507aa49620fcd06c09b3a1082186b9" dependencies = [ - "log 0.4.14", + "log 0.4.16", "parity-wasm 0.32.0", "rustc-demangle", ] @@ -12215,7 +12217,7 @@ dependencies = [ "indexmap", "lazy_static", "libc", - "log 0.4.14", + "log 0.4.16", "object 0.27.1", "once_cell", "paste 1.0.6", @@ -12244,7 +12246,7 @@ dependencies = [ "bincode", "directories-next", "file-per-thread-logger", - "log 0.4.14", + "log 0.4.16", "rustix", "serde", "sha2 0.9.8", @@ -12266,7 +12268,7 @@ dependencies = [ "cranelift-native", "cranelift-wasm", "gimli 0.26.1", - "log 0.4.14", + "log 0.4.16", "more-asserts", "object 0.27.1", "target-lexicon", @@ -12285,7 +12287,7 @@ dependencies = [ "cranelift-entity 0.82.3", "gimli 0.26.1", "indexmap", - "log 0.4.14", + "log 0.4.16", "more-asserts", "object 0.27.1", "serde", @@ -12307,7 +12309,7 @@ dependencies = [ "cfg-if 1.0.0", "cpp_demangle", "gimli 0.26.1", - "log 0.4.14", + "log 0.4.16", "object 0.27.1", "region 2.2.0", "rustc-demangle", @@ -12344,7 +12346,7 @@ dependencies = [ "cfg-if 1.0.0", "indexmap", "libc", - "log 0.4.14", + "log 0.4.16", "mach", "memoffset", "more-asserts", @@ -12633,7 +12635,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7d9028f208dd5e63c614be69f115c1b53cacc1111437d4c765185856666c107" dependencies = [ "futures 0.3.21", - "log 0.4.14", + "log 0.4.16", "nohash-hasher", "parking_lot 0.11.2", "rand 0.8.4", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index dca386b303610..40129d3bbf5fd 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -559,6 +559,7 @@ impl pallet_staking::Config for Runtime { type ElectionProvider = ElectionProviderMultiPhase; type GenesisElectionProvider = onchain::UnboundedExecution; type VoterList = BagsList; + type Pages = ConstU32<1>; type MaxUnlockingChunks = ConstU32<32>; type WeightInfo = pallet_staking::weights::SubstrateWeight; type BenchmarkingConfig = StakingBenchmarkingConfig; diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index 15f53e7da0823..b37004506290d 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -186,6 +186,7 @@ impl pallet_staking::Config for Test { type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote; type Event = Event; type Currency = Balances; + type Pages = ConstU32<1>; type Slash = (); type Reward = (); type SessionsPerEra = SessionsPerEra; diff --git a/frame/bags-list/remote-tests/src/snapshot.rs b/frame/bags-list/remote-tests/src/snapshot.rs index 408f5f2bd8aa2..3ccef6e4eee9c 100644 --- a/frame/bags-list/remote-tests/src/snapshot.rs +++ b/frame/bags-list/remote-tests/src/snapshot.rs @@ -16,19 +16,19 @@ //! Test to execute the snapshot using the voter bag. -use frame_election_provider_support::SortedListProvider; -use frame_support::traits::PalletInfoAccess; +use frame_election_provider_support::{ElectionDataProvider, SortedListProvider}; +use frame_support::{storage::generator::StorageMap, traits::PalletInfoAccess}; +use pallet_staking::Pallet as Staking; use remote_externalities::{Builder, Mode, OnlineConfig}; use sp_runtime::{traits::Block as BlockT, DeserializeOwned}; /// Execute create a snapshot from pallet-staking. pub async fn execute( - voter_limit: Option, + page_limit: Option, + pages: usize, currency_unit: u64, ws_url: String, ) { - use frame_support::storage::generator::StorageMap; - let mut ext = Builder::::new() .mode(Mode::Online(OnlineConfig { transport: ws_url.to_string().into(), @@ -49,38 +49,49 @@ pub async fn execute .unwrap(); ext.execute_with(|| { - use frame_election_provider_support::ElectionDataProvider; log::info!( target: crate::LOG_TARGET, "{} nodes in bags list.", ::VoterList::count(), ); + log::info!( + target: crate::LOG_TARGET, + "generating {} pages of snapshot, ranging {:?}", + pages, + >::range(pages as u32).collect::>(), + ); + + assert!(Staking::::last_iterated_nominator().is_none()); - let voters = - as ElectionDataProvider>::electing_voters(voter_limit) + for page in >::range(pages as u32) { + let page_voters = + as ElectionDataProvider>::electing_voters_paged( + page_limit, page, + ) .unwrap(); - let mut voters_nominator_only = voters - .iter() - .filter(|(v, _, _)| pallet_staking::Nominators::::contains_key(v)) - .cloned() - .collect::>(); - voters_nominator_only.sort_by_key(|(_, w, _)| *w); + let currency_unit = currency_unit as f64; + let min_voter = + page_voters.last().map(|(x, y, _)| (x.clone(), *y as f64 / currency_unit)); + let max_voter = + page_voters.first().map(|(x, y, _)| (x.clone(), *y as f64 / currency_unit)); + assert!( + page == 0 || + Staking::::last_iterated_nominator() == + page_voters.last().map(|(x, _, _)| x.clone()), + ); - let currency_unit = currency_unit as f64; - let min_voter = voters_nominator_only - .first() - .map(|(x, y, _)| (x.clone(), *y as f64 / currency_unit)); - let max_voter = voters_nominator_only - .last() - .map(|(x, y, _)| (x.clone(), *y as f64 / currency_unit)); - log::info!( - target: crate::LOG_TARGET, - "a snapshot with limit {:?} has been created, {} voters are taken. min nominator: {:?}, max: {:?}", - voter_limit, - voters.len(), - min_voter, - max_voter - ); + log::info!( + target: crate::LOG_TARGET, + "took snapshot page {:?} with limit {:?}, {} voters are taken. min voter: {:?}, max: {:?}", + page, + page_limit, + page_voters.len(), + min_voter, + max_voter + ); + } + + assert!(Staking::::last_iterated_nominator().is_none()); }); } diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs index db8c06a38d674..c7cb0dc18558b 100644 --- a/frame/bags-list/src/list/mod.rs +++ b/frame/bags-list/src/list/mod.rs @@ -255,7 +255,6 @@ impl, I: 'static> List { // We chain two iterators: // 1. from the given `start` till the end of the bag // 2. all the bags that come after `start`'s bag. - let start_node = Node::::get(start).ok_or(ListError::NodeNotFound)?; let start_node_upper = start_node.bag_upper; let start_bag = sp_std::iter::successors(start_node.next(), |prev| prev.next()); diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 7c06ff6bee546..7055210eec9f5 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -18,7 +18,7 @@ use super::*; use crate as multi_phase; use frame_election_provider_support::{ - data_provider, onchain, ElectionDataProvider, NposSolution, SequentialPhragmen, + data_provider, onchain, ElectionDataProvider, NposSolution, PageIndex, SequentialPhragmen, }; pub use frame_support::{assert_noop, assert_ok}; use frame_support::{ @@ -461,8 +461,13 @@ impl ElectionDataProvider for StakingMock { type AccountId = AccountId; type BlockNumber = u64; type MaxVotesPerVoter = MaxNominations; + type Pages = ConstU32<1>; - fn electable_targets(maybe_max_len: Option) -> data_provider::Result> { + fn electable_targets_paged( + maybe_max_len: Option, + remaining: PageIndex, + ) -> data_provider::Result> { + assert_eq!(remaining, 0, "this pallet only works with single page snapshots"); let targets = Targets::get(); if maybe_max_len.map_or(false, |max_len| targets.len() > max_len) { @@ -472,9 +477,11 @@ impl ElectionDataProvider for StakingMock { Ok(targets) } - fn electing_voters( + fn electing_voters_paged( maybe_max_len: Option, + remaining: PageIndex, ) -> data_provider::Result>> { + assert_eq!(remaining, 0, "this pallet only works with single page snapshots"); let mut voters = Voters::get(); if let Some(max_len) = maybe_max_len { voters.truncate(max_len) diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index be0c05e46df32..550302eae9f03 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -22,6 +22,7 @@ sp-runtime = { version = "6.0.0", default-features = false, path = "../../primit frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-election-provider-solution-type = { version = "4.0.0-dev", path = "solution-type" } +log = { version = "0.4.16" } [dev-dependencies] rand = "0.7.3" diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index 37ea2fcc59091..8ebf5ab48553a 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -103,16 +103,17 @@ //! type AccountId = AccountId; //! type BlockNumber = BlockNumber; //! type MaxVotesPerVoter = ConstU32<1>; +//! type Pages = ConstU32<1>; //! //! fn desired_targets() -> data_provider::Result { //! Ok(1) //! } -//! fn electing_voters(maybe_max_len: Option) +//! fn electing_voters_paged(maybe_max_len: Option, _: PageIndex) //! -> data_provider::Result>> //! { //! Ok(Default::default()) //! } -//! fn electable_targets(maybe_max_len: Option) -> data_provider::Result> { +//! fn electable_targets_paged(maybe_max_len: Option, _: PageIndex) -> data_provider::Result> { //! Ok(vec![10, 20, 30]) //! } //! fn next_election_prediction(now: BlockNumber) -> BlockNumber { @@ -170,13 +171,14 @@ pub mod onchain; pub mod traits; #[cfg(feature = "std")] use codec::{Decode, Encode}; -use frame_support::{weights::Weight, BoundedVec, RuntimeDebug}; +use frame_support::{traits::DefensiveSaturating, weights::Weight, BoundedVec, RuntimeDebug}; use sp_runtime::traits::Bounded; use sp_std::{fmt::Debug, prelude::*}; /// Re-export the solution generation macro. pub use frame_election_provider_solution_type::generate_solution_type; pub use frame_support::traits::Get; + /// Re-export some type as they are used in the interface. pub use sp_arithmetic::PerThing; pub use sp_npos_elections::{ @@ -185,6 +187,13 @@ pub use sp_npos_elections::{ }; pub use traits::NposSolution; +/// The index used to indicate the page number. +/// +/// A u8 would have probably been enough until the end of universe, but since we use this as the +/// bound of `BoundedVec` and similar, using `u32` will save us some hassle. +// TODO: https://github.com/paritytech/substrate/issues/11076 +pub type PageIndex = u32; + // re-export for the solution macro, with the dependencies of the macro. #[doc(hidden)] pub use codec; @@ -275,6 +284,12 @@ pub trait ElectionDataProvider { /// Maximum number of votes per voter that this data provider is providing. type MaxVotesPerVoter: Get; + /// The maximum number of pages that this data provider is expected to be able to provide. An + /// implementation could use this to verify the value of `remaining: PageIndex`. + // NOTE: this should maybe be a generic, because a single type might want implement it with + // different bounds. + type Pages: Get; + /// All possible targets for the election, i.e. the targets that could become elected, thus /// "electable". /// @@ -283,8 +298,9 @@ pub trait ElectionDataProvider { /// /// This should be implemented as a self-weighing function. The implementor should register its /// appropriate weight at the end of execution with the system pallet directly. - fn electable_targets( + fn electable_targets_paged( maybe_max_len: Option, + remaining_pages: PageIndex, ) -> data_provider::Result>; /// All the voters that participate in the election, thus "electing". @@ -296,7 +312,27 @@ pub trait ElectionDataProvider { /// /// This should be implemented as a self-weighing function. The implementor should register its /// appropriate weight at the end of execution with the system pallet directly. - fn electing_voters(maybe_max_len: Option) -> data_provider::Result>>; + fn electing_voters_paged( + maybe_max_len: Option, + remaining_pages: PageIndex, + ) -> data_provider::Result>>; + + /// Same as [`Self::electable_targets_paged`], but the most significant page is assumed. + /// + /// This should almost only be used in the case where `Self::Pages` is `1`. + fn electable_targets( + maybe_max_len: Option, + ) -> data_provider::Result> { + Self::electable_targets_paged(maybe_max_len, Self::msp()) + } + + /// Same as [`Self::electing_voters_paged`], but the page 0 is assumed. + /// + /// + /// This should almost only be used in the case where `Self::Pages` is `1`. + fn electing_voters(maybe_max_len: Option) -> data_provider::Result>> { + Self::electing_voters_paged(maybe_max_len, Self::msp()) + } /// The number of targets to elect. /// @@ -306,8 +342,6 @@ pub trait ElectionDataProvider { /// A sensible implementation should use the minimum between this value and /// [`Self::targets().len()`], since desiring a winner set larger than candidates is not /// feasible. - /// - /// This is documented further in issue: fn desired_targets() -> data_provider::Result; /// Provide a best effort prediction about when the next election is about to happen. @@ -318,8 +352,28 @@ pub trait ElectionDataProvider { /// This is only useful for stateful election providers. fn next_election_prediction(now: Self::BlockNumber) -> Self::BlockNumber; + /// Shorthand for "most significant page". + /// + /// The least significant, aka "first" page that this election provider is expected to receive. + fn msp() -> PageIndex { + Self::Pages::get().defensive_saturating_sub(1) + } + + /// Shorthand for "least significant page". + /// + /// The most significant, aka "first" page that this election provider is expected to receive. + fn lsp() -> PageIndex { + 0 + } + + /// The range of `take` pages, from most significant to least significant. + fn range(take: PageIndex) -> Box> { + Box::new((Self::lsp()..Self::Pages::get()).take(take as usize).rev()) + } + /// Utility function only to be used in benchmarking scenarios, to be implemented optionally, /// else a noop. + #[cfg(any(feature = "runtime-benchmarks", test))] fn put_snapshot( _voters: Vec>, diff --git a/frame/election-provider-support/src/onchain.rs b/frame/election-provider-support/src/onchain.rs index 62e76c3888822..c43fde114eac8 100644 --- a/frame/election-provider-support/src/onchain.rs +++ b/frame/election-provider-support/src/onchain.rs @@ -29,6 +29,8 @@ use sp_std::{collections::btree_map::BTreeMap, marker::PhantomData, prelude::*}; /// Errors of the on-chain election. #[derive(Eq, PartialEq, Debug)] pub enum Error { + /// The number of pages is incorrect. + WrongPageSize, /// An internal error in the NPoS elections crate. NposElections(sp_npos_elections::Error), /// Errors from the data provider. @@ -97,6 +99,9 @@ fn elect_with( maybe_max_voters: Option, maybe_max_targets: Option, ) -> Result::AccountId>, Error> { + if ::Pages::get() != 1 { + return Err(Error::WrongPageSize) + } let voters = T::DataProvider::electing_voters(maybe_max_voters).map_err(Error::DataProvider)?; let targets = T::DataProvider::electable_targets(maybe_max_targets).map_err(Error::DataProvider)?; @@ -266,14 +271,20 @@ mod tests { use frame_support::{bounded_vec, traits::ConstU32}; use super::*; - use crate::{data_provider, VoterOf}; + use crate::{data_provider, PageIndex, VoterOf}; pub struct DataProvider; impl ElectionDataProvider for DataProvider { type AccountId = AccountId; type BlockNumber = BlockNumber; type MaxVotesPerVoter = ConstU32<2>; - fn electing_voters(_: Option) -> data_provider::Result>> { + type Pages = ConstU32<1>; + + fn electing_voters_paged( + _: Option, + remaining: PageIndex, + ) -> data_provider::Result>> { + assert_eq!(remaining, 0); Ok(vec![ (1, 10, bounded_vec![10, 20]), (2, 20, bounded_vec![30, 20]), @@ -281,7 +292,11 @@ mod tests { ]) } - fn electable_targets(_: Option) -> data_provider::Result> { + fn electable_targets_paged( + _: Option, + remaining: PageIndex, + ) -> data_provider::Result> { + assert_eq!(remaining, 0); Ok(vec![10, 20, 30]) } diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index 67d5a3d7fd373..5cb9855fdaa71 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -194,6 +194,7 @@ impl pallet_staking::Config for Test { type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote; type Event = Event; type Currency = Balances; + type Pages = ConstU32<1>; type Slash = (); type Reward = (); type SessionsPerEra = SessionsPerEra; diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 74cc29586920d..b1b09d4b1c278 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -164,6 +164,7 @@ impl pallet_staking::Config for Test { type UnixTime = pallet_timestamp::Pallet; type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote; type RewardRemainder = (); + type Pages = ConstU32<1>; type Event = Event; type Slash = (); type Reward = (); diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 5acc484f9ba62..628734c75038a 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -170,6 +170,7 @@ impl pallet_staking::Config for Test { type UnixTime = pallet_timestamp::Pallet; type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote; type RewardRemainder = (); + type Pages = ConstU32<1>; type Event = Event; type Slash = (); type Reward = (); diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 983f1bd54deb7..a8619078a5219 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -22,7 +22,7 @@ use crate::{ConfigOp, Pallet as Staking}; use testing_utils::*; use codec::Decode; -use frame_election_provider_support::SortedListProvider; +use frame_election_provider_support::{ElectionDataProvider, SortedListProvider}; use frame_support::{ dispatch::UnfilteredDispatchable, pallet_prelude::*, @@ -809,7 +809,7 @@ benchmarks! { assert!(balance_before > balance_after); } - get_npos_voters { + electing_voters_paged { // number of validator intention. let v in (MaxValidators::::get() / 2) .. MaxValidators::::get(); // number of nominator intention. @@ -830,11 +830,11 @@ benchmarks! { let num_voters = (v + n) as usize; }: { - let voters = >::get_npos_voters(None); + let voters = >::electing_voters(None).unwrap(); assert_eq!(voters.len(), num_voters); } - get_npos_targets { + electable_targets_paged { // number of validator intention. let v in (MaxValidators::::get() / 2) .. MaxValidators::::get(); // number of nominator intention. @@ -844,7 +844,7 @@ benchmarks! { v, n, T::MaxNominations::get() as usize, false, None )?; }: { - let targets = >::get_npos_targets(); + let targets = >::electable_targets(None).unwrap(); assert_eq!(targets.len() as u32, v); } diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 09809483ec155..0e6a5e3ad49a9 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -237,6 +237,7 @@ const THRESHOLDS: [sp_npos_elections::VoteWeight; 9] = parameter_types! { pub static BagThresholds: &'static [sp_npos_elections::VoteWeight] = &THRESHOLDS; pub static MaxNominations: u32 = 16; + pub static Pages: u32 = 1; } impl pallet_bags_list::Config for Test { @@ -277,6 +278,7 @@ impl crate::pallet::pallet::Config for Test { type GenesisElectionProvider = Self::ElectionProvider; // NOTE: consider a macro and use `UseNominatorsAndValidatorsMap` as well. type VoterList = BagsList; + type Pages = Pages; type MaxUnlockingChunks = ConstU32<32>; type BenchmarkingConfig = TestBenchmarkingConfig; type WeightInfo = (); @@ -435,6 +437,8 @@ impl ExtBuilder { (71, self.balance_factor * 2000), (80, self.balance_factor), (81, self.balance_factor * 2000), + (90, self.balance_factor), + (91, self.balance_factor * 2000), // This allows us to have a total_payout different from 0. (999, 1_000_000_000_000), ], diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 90f19c6badd8f..263d73e577853 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -18,8 +18,8 @@ //! Implementations for the Staking FRAME Pallet. use frame_election_provider_support::{ - data_provider, ElectionDataProvider, ElectionProvider, ScoreProvider, SortedListProvider, - Supports, VoteWeight, VoterOf, + data_provider, ElectionDataProvider, ElectionProvider, PageIndex, ScoreProvider, + SortedListProvider, Supports, VoteWeight, VoterOf, }; use frame_support::{ pallet_prelude::*, @@ -218,12 +218,17 @@ impl Pallet { } /// Chill a stash account. - pub(crate) fn chill_stash(stash: &T::AccountId) { - let chilled_as_validator = Self::do_remove_validator(stash); - let chilled_as_nominator = Self::do_remove_nominator(stash); - if chilled_as_validator || chilled_as_nominator { + /// + /// Returns `Ok(())` if it was actually chilled (either from a validator or a nominator), and + /// `Error` otherwise. + pub(crate) fn try_chill_stash(stash: &T::AccountId) -> Result<(), Error> { + let chilled_as_validator = Self::try_remove_validator(stash); + let chilled_as_nominator = Self::try_remove_nominator(stash); + if chilled_as_validator.is_ok() || chilled_as_nominator.is_ok() { Self::deposit_event(Event::::Chilled(stash.clone())); } + + chilled_as_validator.or(chilled_as_nominator) } /// Actually make a payment to a staker. This uses the currency's reward function @@ -574,8 +579,10 @@ impl Pallet { >::remove(&controller); >::remove(stash); - Self::do_remove_validator(stash); - Self::do_remove_nominator(stash); + // dropping result is justified: we just want to make sure they are no longer + // nominator/validator. + let _ = Self::try_remove_validator(stash); + let _ = Self::try_remove_nominator(stash); frame_system::Pallet::::dec_consumers(stash); @@ -655,35 +662,42 @@ impl Pallet { SlashRewardFraction::::put(fraction); } - /// Get all of the voters that are eligible for the npos election. - /// - /// `maybe_max_len` can imposes a cap on the number of voters returned; - /// - /// This function is self-weighing as [`DispatchClass::Mandatory`]. - /// - /// ### Slashing + /// Get at most `maybe_max_len` voters ready for the npos election, starting from `maybe_last` + /// if specified. /// - /// All votes that have been submitted before the last non-zero slash of the corresponding - /// target are *auto-chilled*, but still count towards the limit imposed by `maybe_max_len`. - pub fn get_npos_voters(maybe_max_len: Option) -> Vec> { + /// Returns the vector of voters (which is implicitly at most `maybe_max_len`), grouped with the + /// number of validators taken and the number of nominators taken respectively. + pub fn get_npos_voters_page( + maybe_max_len: Option, + maybe_last: Option, + slashing_spans: &BTreeMap, + ) -> (Vec>, u32, u32) { let max_allowed_len = { let all_voter_count = T::VoterList::count() as usize; maybe_max_len.unwrap_or(all_voter_count).min(all_voter_count) }; - let mut all_voters = Vec::<_>::with_capacity(max_allowed_len); + let mut voters = Vec::<_>::with_capacity(max_allowed_len); - // cache a few things. + // cache the total-issuance once in this function let weight_of = Self::weight_of_fn(); - let slashing_spans = >::iter().collect::>(); - let mut voters_seen = 0u32; let mut validators_taken = 0u32; let mut nominators_taken = 0u32; - let mut sorted_voters = T::VoterList::iter(); - while all_voters.len() < max_allowed_len && - voters_seen < (NPOS_MAX_ITERATIONS_COEFFICIENT * max_allowed_len as u32) + let mut sorted_voters = if let Some(last) = maybe_last { + // Defensive: a correctly working pallet-staking will store a last node that is already + // part of of the voter list. If otherwise, we start from the beginning and return + // duplicates, hopefully our beloved `ElectionProvider` can handle duplicate voters + // (substrate implementations do). This is guaranteed by making sure while + // `LastIteratedNominator` is set, this voter cannot chill themselves. + T::VoterList::iter_from(&last).defensive_unwrap_or_else(T::VoterList::iter) + } else { + T::VoterList::iter() + }; + + while voters.len() < max_allowed_len && + voters_seen < (max_allowed_len as u32 * NPOS_MAX_ITERATIONS_COEFFICIENT) { let voter = match sorted_voters.next() { Some(voter) => { @@ -696,14 +710,13 @@ impl Pallet { if let Some(Nominations { submitted_in, mut targets, suppressed: _ }) = >::get(&voter) { - // if this voter is a nominator: targets.retain(|stash| { slashing_spans .get(stash) .map_or(true, |spans| submitted_in >= spans.last_nonzero_slash()) }); if !targets.len().is_zero() { - all_voters.push((voter.clone(), weight_of(&voter), targets)); + voters.push((voter.clone(), weight_of(&voter), targets)); nominators_taken.saturating_inc(); } } else if Validators::::contains_key(&voter) { @@ -715,24 +728,24 @@ impl Pallet { .try_into() .expect("`MaxVotesPerVoter` must be greater than or equal to 1"), ); - all_voters.push(self_vote); + voters.push(self_vote); validators_taken.saturating_inc(); } else { - // this can only happen if: 1. there a bug in the bags-list (or whatever is the - // sorted list) logic and the state of the two pallets is no longer compatible, or - // because the nominators is not decodable since they have more nomination than - // `T::MaxNominations`. The latter can rarely happen, and is not really an emergency - // or bug if it does. + // this can only happen if: 1. there a pretty bad bug in the bags-list (or whatever + // is the sorted list) logic and the state of the two pallets is no longer + // compatible, or because the nominators is not decodable since they have more + // nomination than `T::MaxNominations`. This can rarely happen, and is not really an + // emergency or bug if it does. log!( warn, - "DEFENSIVE: invalid item in `VoterList`: {:?}, this nominator probably has too many nominations now", + "DEFENSIVE: invalid item in `SortedListProvider`: {:?}, this nominator probably has too many nominations now", voter - ) + ); } } - // all_voters should have not re-allocated. - debug_assert!(all_voters.capacity() == max_allowed_len); + // voters should have never re-allocated. + debug_assert!(voters.capacity() >= voters.len()); Self::register_weight(T::WeightInfo::get_npos_voters( validators_taken, @@ -740,15 +753,7 @@ impl Pallet { slashing_spans.len() as u32, )); - log!( - info, - "generated {} npos voters, {} from validators and {} nominators", - all_voters.len(), - validators_taken, - nominators_taken - ); - - all_voters + (voters, validators_taken, nominators_taken) } /// Get the targets for an upcoming npos election. @@ -768,14 +773,13 @@ impl Pallet { targets } - /// This function will add a nominator to the `Nominators` storage map, - /// and `VoterList`. + /// This function will add a nominator to the `Nominators` storage map, and reflect it in + /// `VoterList`. /// /// If the nominator already exists, their nominations will be updated. /// /// NOTE: you must ALWAYS use this function to add nominator or update their targets. Any access - /// to `Nominators` or `VoterList` outside of this function is almost certainly - /// wrong. + /// to `Nominators` or `VoterList` outside of this function is almost certainly wrong. pub fn do_add_nominator(who: &T::AccountId, nominations: Nominations) { if !Nominators::::contains_key(who) { // maybe update sorted list. @@ -792,20 +796,24 @@ impl Pallet { } /// This function will remove a nominator from the `Nominators` storage map, - /// and `VoterList`. + /// and reflect it in the `VoterList`. /// - /// Returns true if `who` was removed from `Nominators`, otherwise false. + /// Returns `Ok(())` if `who` was removed from `Nominators`, otherwise `Err(_)`. /// /// NOTE: you must ALWAYS use this function to remove a nominator from the system. Any access to /// `Nominators` or `VoterList` outside of this function is almost certainly /// wrong. - pub fn do_remove_nominator(who: &T::AccountId) -> bool { + pub fn try_remove_nominator(who: &T::AccountId) -> Result<(), Error> { let outcome = if Nominators::::contains_key(who) { + ensure!( + LastIteratedNominator::::get().map_or(true, |last| &last != who), + Error::::TemporarilyNotAllowed + ); Nominators::::remove(who); T::VoterList::on_remove(who); - true + Ok(()) } else { - false + Err(Error::::NotNominator) }; debug_assert_eq!(T::VoterList::sanity_check(), Ok(())); @@ -841,18 +849,18 @@ impl Pallet { /// This function will remove a validator from the `Validators` storage map. /// - /// Returns true if `who` was removed from `Validators`, otherwise false. + /// Returns `Ok(_)` if `who` was removed from `Validators`, `Err(_)` otherwise. /// /// NOTE: you must ALWAYS use this function to remove a validator from the system. Any access to /// `Validators` or `VoterList` outside of this function is almost certainly /// wrong. - pub fn do_remove_validator(who: &T::AccountId) -> bool { + pub fn try_remove_validator(who: &T::AccountId) -> Result<(), Error> { let outcome = if Validators::::contains_key(who) { Validators::::remove(who); T::VoterList::on_remove(who); - true + Ok(()) } else { - false + Err(Error::::NotValidator) }; debug_assert_eq!(T::VoterList::sanity_check(), Ok(())); @@ -879,21 +887,70 @@ impl ElectionDataProvider for Pallet { type AccountId = T::AccountId; type BlockNumber = BlockNumberFor; type MaxVotesPerVoter = T::MaxNominations; + type Pages = T::Pages; fn desired_targets() -> data_provider::Result { Self::register_weight(T::DbWeight::get().reads(1)); Ok(Self::validator_count()) } - fn electing_voters(maybe_max_len: Option) -> data_provider::Result>> { - // This can never fail -- if `maybe_max_len` is `Some(_)` we handle it. - let voters = Self::get_npos_voters(maybe_max_len); - debug_assert!(maybe_max_len.map_or(true, |max| voters.len() <= max)); + /// implementation notes: Given the loose dynamics of the `ElectionProvider`, namely the fact + /// that number of entries returned per page is dynamic, this implementation is best-effort. We + /// try and use the `LastIteratedNominator`, which is always kept as long call with `remaining > + /// 0` are made. Any call with `remaining = 0` will clear this history item, and the next call + /// will be a fresh start. + fn electing_voters_paged( + maybe_max_len: Option, + mut remaining: PageIndex, + ) -> data_provider::Result>> { + remaining = remaining.min(Self::msp()); + + let mut maybe_last = LastIteratedNominator::::get(); + let is_valid_state = if T::Pages::get() > 1 { + // in the first page, the `LastIteratedNominator` should not exist, in the rest of the + // pages it should. + (remaining == Self::msp()) ^ maybe_last.is_some() + } else { + maybe_last.is_none() + }; + // defensive: since, at least as of now, this function is also used for governance fallback, + // we really really prefer it to NEVER fail. Thus, we play defensive and return just the + // first page if the state of `LastIteratedNominator` is corrupt. + if !is_valid_state { + frame_support::defensive!("corrupt state in staking election data provider"); + maybe_last = None; + } + + let slashing_spans = >::iter().collect::>(); + let (voters, _validators_taken, _nominators_taken) = + Self::get_npos_voters_page(maybe_max_len, maybe_last, &slashing_spans); + + log!( + debug, + "generated {} npos voters, {} from validators and {} nominators", + voters.len(), + _validators_taken, + _nominators_taken, + ); + + match remaining { + 0 => LastIteratedNominator::::kill(), + _ => + if let Some(last) = voters.last().map(|(x, _, _)| x) { + LastIteratedNominator::::put(last.clone()) + }, + }; Ok(voters) } - fn electable_targets(maybe_max_len: Option) -> data_provider::Result> { + fn electable_targets_paged( + maybe_max_len: Option, + remaining: PageIndex, + ) -> data_provider::Result> { + if remaining > 0 { + return Err("Cannot support more than a single page of targets") + } let target_count = Validators::::count(); // We can't handle this case yet -- return an error. diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 1a8fd59d23987..caa7b9e93b803 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -50,7 +50,7 @@ const STAKING_ID: LockIdentifier = *b"staking "; #[frame_support::pallet] pub mod pallet { - use frame_election_provider_support::ElectionDataProvider; + use frame_election_provider_support::{ElectionDataProvider, PageIndex}; use crate::BenchmarkingConfig; @@ -170,6 +170,10 @@ pub mod pallet { /// also reported as one independent vote. type VoterList: SortedListProvider; + /// The number of pages that we expect to return as part of our role as + /// [`ElectionDataProvider`]. + type Pages: Get; + /// The maximum number of `unlocking` chunks a [`StakingLedger`] can have. Effectively /// determines how many unique eras a staker may be unbonding in. #[pallet::constant] @@ -495,6 +499,12 @@ pub mod pallet { #[pallet::storage] pub(crate) type ChillThreshold = StorageValue<_, Percent, OptionQuery>; + /// Last nominator that was being iterated. This is only useful for multi-page snapshot, and + /// does not affect anything else. + #[pallet::storage] + #[pallet::getter(fn last_iterated_nominator)] + pub(crate) type LastIteratedNominator = StorageValue<_, T::AccountId, OptionQuery>; + #[pallet::genesis_config] pub struct GenesisConfig { pub history_depth: u32, @@ -638,14 +648,16 @@ pub mod pallet { NotController, /// Not a stash account. NotStash, + /// Not a validators account. + NotValidator, + /// Not a nominator account. + NotNominator, /// Stash is already bonded. AlreadyBonded, /// Controller is already paired. AlreadyPaired, /// Targets cannot be empty. EmptyTargets, - /// Duplicate index. - DuplicateIndex, /// Slash record index out of bounds. InvalidSlashIndex, /// Cannot have a validator or nominator role, with value less than the minimum defined by @@ -686,6 +698,8 @@ pub mod pallet { TooManyValidators, /// Commission is too low. Must be at least `MinCommission`. CommissionTooLow, + /// Operation is not permitted at this time. Try again later. + TemporarilyNotAllowed, } #[pallet::hooks] @@ -718,6 +732,8 @@ pub mod pallet { // and that MaxNominations is always greater than 1, since we count on this. assert!(!T::MaxNominations::get().is_zero()); + assert!(T::Pages::get() > 0, "number of pages can be 1 or more"); + sp_std::if_std! { sp_io::TestExternalities::new_empty().execute_with(|| assert!( @@ -1017,10 +1033,9 @@ pub mod pallet { } } - Self::do_remove_nominator(stash); + let _ = Self::try_remove_nominator(stash); Self::do_add_validator(stash, prefs.clone()); Self::deposit_event(Event::::ValidatorPrefsSet(ledger.stash, prefs)); - Ok(()) } @@ -1087,7 +1102,7 @@ pub mod pallet { suppressed: false, }; - Self::do_remove_validator(stash); + let _ = Self::try_remove_validator(stash); Self::do_add_nominator(stash, nominations); Ok(()) } @@ -1107,8 +1122,7 @@ pub mod pallet { pub fn chill(origin: OriginFor) -> DispatchResult { let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; - Self::chill_stash(&ledger.stash); - Ok(()) + Self::try_chill_stash(&ledger.stash).map_err(Into::into) } /// (Re-)set the payment target for a controller. @@ -1636,8 +1650,7 @@ pub mod pallet { // Otherwise, if caller is the same as the controller, this is just like `chill`. if Nominators::::contains_key(&stash) && Nominators::::get(&stash).is_none() { - Self::chill_stash(&stash); - return Ok(()) + return Self::try_chill_stash(&stash).map_err(Into::into) } if caller != controller { @@ -1667,8 +1680,7 @@ pub mod pallet { ensure!(ledger.active < min_active_bond, Error::::CannotChillOther); } - Self::chill_stash(&stash); - Ok(()) + Self::try_chill_stash(&stash).map_err(Into::into) } /// Force a validator to have at least the minimum commission. This will not affect a diff --git a/frame/staking/src/slashing.rs b/frame/staking/src/slashing.rs index 2f381ad631fe5..862fae9330669 100644 --- a/frame/staking/src/slashing.rs +++ b/frame/staking/src/slashing.rs @@ -281,7 +281,9 @@ pub(crate) fn compute_slash( // chill the validator - it misbehaved in the current span and should // not continue in the next election. also end the slashing span. spans.end_span(params.now); - >::chill_stash(params.stash); + // dropping result is justified: we don't care if they were a validator or not, rather + // that they are certainly no longer a validator. + let _ = >::try_chill_stash(params.stash); } } @@ -316,7 +318,9 @@ fn kick_out_if_recent(params: SlashParams) { if spans.era_span(params.slash_era).map(|s| s.index) == Some(spans.span_index()) { spans.end_span(params.now); - >::chill_stash(params.stash); + // dropping result is justified: we don't care if they were a validator or not, rather + // that they are certainly no longer a validator. + let _ = >::try_chill_stash(params.stash); } let disable_without_slash = params.disable_strategy == DisableStrategy::Always; diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 7161418afc76e..6df032e295158 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4018,6 +4018,8 @@ fn on_finalize_weight_is_nonzero() { mod election_data_provider { use super::*; use frame_election_provider_support::ElectionDataProvider; + use frame_support::{bounded_vec, storage::with_transaction}; + use sp_runtime::{DispatchResult, TransactionOutcome}; #[test] fn targets_2sec_block() { @@ -4123,8 +4125,10 @@ mod election_data_provider { // if limit is more. assert_eq!(Staking::electing_voters(Some(55)).unwrap().len(), 5); + assert_eq!(Staking::electing_voters(None).unwrap().len(), 5); // if target limit is more.. + assert_eq!(Staking::electable_targets(None).unwrap().len(), 4); assert_eq!(Staking::electable_targets(Some(6)).unwrap().len(), 4); assert_eq!(Staking::electable_targets(Some(4)).unwrap().len(), 4); @@ -4133,7 +4137,7 @@ mod election_data_provider { Staking::electable_targets(Some(1)).unwrap_err(), "Target snapshot too big" ); - }); + }) } // Tests the criteria that in `ElectionDataProvider::voters` function, we try to get at most @@ -4278,6 +4282,76 @@ mod election_data_provider { assert_eq!(ForceEra::::get(), Forcing::NotForcing); }) } + + #[test] + fn can_paginate() { + ExtBuilder::default() + .add_staker(61, 60, 500, StakerStatus::Nominator(vec![11])) + .add_staker(71, 70, 500, StakerStatus::Nominator(vec![11])) + .add_staker(81, 80, 500, StakerStatus::Nominator(vec![11])) + .add_staker(91, 90, 500, StakerStatus::Nominator(vec![11])) + .set_status(31, StakerStatus::Idle) + .set_status(41, StakerStatus::Idle) + .build_and_execute(|| { + // we shall have 2 validators and 5 nominators. + assert_eq!(Nominators::::count(), 5); + assert_eq!(Validators::::count(), 2); + + // a correct, 2 page snapshot. + Pages::set(2); + // we have 6 voters in total, get them over two pages, each 4 max. + assert_eq!( + Staking::electing_voters_paged(Some(4), 1).unwrap(), + vec![ + // everything sorted based on stake. + (11, 1000, bounded_vec![11]), + (21, 1000, bounded_vec![21]), + (101, 500, bounded_vec![11, 21]), + (61, 500, bounded_vec![11]), + ] + ); + + assert_eq!(LastIteratedNominator::::get(), Some(61)); + + // tandem: node 61 cannot be chilled in any humanly possible way now. + let _ = with_transaction(|| -> TransactionOutcome { + // normal chilling + assert_noop!( + Staking::chill(Origin::signed(60)), + Error::::TemporarilyNotAllowed + ); + // chill-other with the virtue of being less than min-bond + MinNominatorBond::::put(501); + ChillThreshold::::put(Percent::default()); + MaxNominatorsCount::::put(1); + assert_noop!( + Staking::chill_other(Origin::signed(100), 60), + Error::::TemporarilyNotAllowed + ); + storage::TransactionOutcome::Rollback(Ok(())) + }); + + // and making this nominator un-decodable. + MaxNominations::set(0); + assert_noop!( + Staking::chill_other(Origin::signed(100), 60), + Error::::TemporarilyNotAllowed + ); + // this needs to reverted, despite being transactional scope, because it is + // thread-local, not storage. + MaxNominations::set(16); + + assert_eq!( + Staking::electing_voters_paged(Some(4), 0).unwrap(), + vec![ + (71, 500, bounded_vec![11]), + (81, 500, bounded_vec![11]), + (91, 500, bounded_vec![11]) + ] + ); + assert_eq!(LastIteratedNominator::::get(), None); + }); + } } #[test]