diff --git a/polkadot/Cargo.lock b/polkadot/Cargo.lock index d4c095e58c5507e04e8664280208a351186d57d4..24a3d3bbb2eae9244dcf1a56416d044103363e3a 100644 --- a/polkadot/Cargo.lock +++ b/polkadot/Cargo.lock @@ -451,7 +451,7 @@ dependencies = [ [[package]] name = "ed25519" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -491,7 +491,7 @@ dependencies = [ [[package]] name = "environmental" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" [[package]] name = "error-chain" @@ -1738,30 +1738,11 @@ dependencies = [ name = "polkadot-cli" version = "0.3.0" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "polkadot-primitives 0.1.0", - "polkadot-runtime 0.1.0", "polkadot-service 0.3.0", - "polkadot-transaction-pool 0.1.0", - "slog 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-cli 0.3.0 (git+https://github.com/paritytech/substrate)", - "substrate-client 0.1.0 (git+https://github.com/paritytech/substrate)", - "substrate-codec 0.1.0 (git+https://github.com/paritytech/substrate)", - "substrate-extrinsic-pool 0.1.0 (git+https://github.com/paritytech/substrate)", - "substrate-network 0.1.0 (git+https://github.com/paritytech/substrate)", - "substrate-primitives 0.1.0 (git+https://github.com/paritytech/substrate)", - "substrate-rpc 0.1.0 (git+https://github.com/paritytech/substrate)", - "substrate-rpc-servers 0.1.0 (git+https://github.com/paritytech/substrate)", - "substrate-runtime-primitives 0.1.0 (git+https://github.com/paritytech/substrate)", - "substrate-service 0.3.0 (git+https://github.com/paritytech/substrate)", - "substrate-state-machine 0.1.0 (git+https://github.com/paritytech/substrate)", - "substrate-telemetry 0.3.0 (git+https://github.com/paritytech/substrate)", "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1916,7 +1897,6 @@ dependencies = [ "polkadot-transaction-pool 0.1.0", "slog 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-client 0.1.0 (git+https://github.com/paritytech/substrate)", - "substrate-codec 0.1.0 (git+https://github.com/paritytech/substrate)", "substrate-network 0.1.0 (git+https://github.com/paritytech/substrate)", "substrate-primitives 0.1.0 (git+https://github.com/paritytech/substrate)", "substrate-runtime-io 0.1.0 (git+https://github.com/paritytech/substrate)", @@ -2000,7 +1980,7 @@ dependencies = [ [[package]] name = "pwasm-alloc" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "pwasm-libc 0.1.0 (git+https://github.com/paritytech/substrate)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2009,7 +1989,7 @@ dependencies = [ [[package]] name = "pwasm-libc" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" [[package]] name = "quick-error" @@ -2509,7 +2489,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "substrate-bft" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "ed25519 0.1.0 (git+https://github.com/paritytech/substrate)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2528,7 +2508,7 @@ dependencies = [ [[package]] name = "substrate-cli" version = "0.3.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2546,7 +2526,6 @@ dependencies = [ "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-client 0.1.0 (git+https://github.com/paritytech/substrate)", - "substrate-extrinsic-pool 0.1.0 (git+https://github.com/paritytech/substrate)", "substrate-network 0.1.0 (git+https://github.com/paritytech/substrate)", "substrate-network-libp2p 0.1.0 (git+https://github.com/paritytech/substrate)", "substrate-runtime-primitives 0.1.0 (git+https://github.com/paritytech/substrate)", @@ -2560,7 +2539,7 @@ dependencies = [ [[package]] name = "substrate-client" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "ed25519 0.1.0 (git+https://github.com/paritytech/substrate)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2590,7 +2569,7 @@ dependencies = [ [[package]] name = "substrate-client-db" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "hashdb 0.2.1 (git+https://github.com/paritytech/parity-common.git)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common.git)", @@ -2612,7 +2591,7 @@ dependencies = [ [[package]] name = "substrate-codec" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2620,7 +2599,7 @@ dependencies = [ [[package]] name = "substrate-codec-derive" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "proc-macro2 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2630,7 +2609,7 @@ dependencies = [ [[package]] name = "substrate-executor" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519 0.1.0 (git+https://github.com/paritytech/substrate)", @@ -2656,7 +2635,7 @@ dependencies = [ [[package]] name = "substrate-extrinsic-pool" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2664,13 +2643,14 @@ dependencies = [ "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-runtime-primitives 0.1.0 (git+https://github.com/paritytech/substrate)", "transaction-pool 1.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-keyring" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "ed25519 0.1.0 (git+https://github.com/paritytech/substrate)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2680,7 +2660,7 @@ dependencies = [ [[package]] name = "substrate-keystore" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "ed25519 0.1.0 (git+https://github.com/paritytech/substrate)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2696,7 +2676,7 @@ dependencies = [ [[package]] name = "substrate-network" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519 0.1.0 (git+https://github.com/paritytech/substrate)", @@ -2718,7 +2698,7 @@ dependencies = [ [[package]] name = "substrate-network-libp2p" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2741,7 +2721,7 @@ dependencies = [ [[package]] name = "substrate-primitives" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2767,7 +2747,7 @@ dependencies = [ [[package]] name = "substrate-rpc" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)", @@ -2789,7 +2769,7 @@ dependencies = [ [[package]] name = "substrate-rpc-servers" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-http-server 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)", @@ -2804,7 +2784,7 @@ dependencies = [ [[package]] name = "substrate-runtime-consensus" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2821,7 +2801,7 @@ dependencies = [ [[package]] name = "substrate-runtime-council" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", @@ -2845,7 +2825,7 @@ dependencies = [ [[package]] name = "substrate-runtime-democracy" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2867,7 +2847,7 @@ dependencies = [ [[package]] name = "substrate-runtime-executive" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2883,7 +2863,7 @@ dependencies = [ [[package]] name = "substrate-runtime-io" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "ed25519 0.1.0 (git+https://github.com/paritytech/substrate)", "environmental 0.1.0 (git+https://github.com/paritytech/substrate)", @@ -2898,7 +2878,7 @@ dependencies = [ [[package]] name = "substrate-runtime-primitives" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2916,7 +2896,7 @@ dependencies = [ [[package]] name = "substrate-runtime-sandbox" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0 (git+https://github.com/paritytech/substrate)", @@ -2929,7 +2909,7 @@ dependencies = [ [[package]] name = "substrate-runtime-session" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2950,7 +2930,7 @@ dependencies = [ [[package]] name = "substrate-runtime-staking" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2973,7 +2953,7 @@ dependencies = [ [[package]] name = "substrate-runtime-std" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "pwasm-alloc 0.1.0 (git+https://github.com/paritytech/substrate)", "pwasm-libc 0.1.0 (git+https://github.com/paritytech/substrate)", @@ -2983,7 +2963,7 @@ dependencies = [ [[package]] name = "substrate-runtime-support" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "ed25519 0.1.0 (git+https://github.com/paritytech/substrate)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2998,7 +2978,7 @@ dependencies = [ [[package]] name = "substrate-runtime-system" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3015,7 +2995,7 @@ dependencies = [ [[package]] name = "substrate-runtime-timestamp" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3033,7 +3013,7 @@ dependencies = [ [[package]] name = "substrate-runtime-version" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3046,7 +3026,7 @@ dependencies = [ [[package]] name = "substrate-serializer" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3055,7 +3035,7 @@ dependencies = [ [[package]] name = "substrate-service" version = "0.3.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3087,7 +3067,7 @@ dependencies = [ [[package]] name = "substrate-state-db" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3099,7 +3079,7 @@ dependencies = [ [[package]] name = "substrate-state-machine" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.2.1 (git+https://github.com/paritytech/parity-common.git)", @@ -3117,7 +3097,7 @@ dependencies = [ [[package]] name = "substrate-telemetry" version = "0.3.0" -source = "git+https://github.com/paritytech/substrate#f3709852138d0bd2348d7e13505777c7acb7551e" +source = "git+https://github.com/paritytech/substrate#fa1392a80371818f2ca6069f9c1e6445d42ea467" dependencies = [ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/polkadot/api/Cargo.toml b/polkadot/api/Cargo.toml index 92d8ca81b822e5ca1a5490df890eb48395808da9..0981d0633126cecc296d79816b3191324e8b8695 100644 --- a/polkadot/api/Cargo.toml +++ b/polkadot/api/Cargo.toml @@ -17,6 +17,7 @@ substrate-client = { git = "https://github.com/paritytech/substrate" } substrate-primitives = { git = "https://github.com/paritytech/substrate" } substrate-executor = { git = "https://github.com/paritytech/substrate" } substrate-state-machine = { git = "https://github.com/paritytech/substrate" } +log = "0.3" [dev-dependencies] substrate-keyring = { git = "https://github.com/paritytech/substrate" } diff --git a/polkadot/api/src/full.rs b/polkadot/api/src/full.rs index 7c7cf3b69bd7f36de453444eb852dae8a871e0ed..0d09d539a090416123354f1f682eab828daaaf5b 100644 --- a/polkadot/api/src/full.rs +++ b/polkadot/api/src/full.rs @@ -119,7 +119,7 @@ impl<B: LocalBackend<Block, KeccakHasher, RlpCodec>> PolkadotApi for Client<B, L let encoded = block.encode(); let res: Result<()> = call(self, at, "execute_block", &encoded); match res { - Ok(()) => Ok(true), + Ok(_) => Ok(true), Err(err) => match err.kind() { &ErrorKind::Execution(_) => Ok(false), _ => Err(err) @@ -165,7 +165,8 @@ impl<B: LocalBackend<Block, KeccakHasher, RlpCodec>> PolkadotApi for Client<B, L } fn inherent_extrinsics(&self, at: &BlockId, inherent_data: InherentData) -> Result<Vec<UncheckedExtrinsic>> { - inherent_data.using_encoded(|encoded| { + let runtime_version = self.runtime_version_at(at)?; + (inherent_data, runtime_version.spec_version).using_encoded(|encoded| { call(self, at, "inherent_extrinsics", encoded) }) } @@ -241,6 +242,7 @@ mod tests { assert_eq!(block.header.number, 1); assert!(block.header.extrinsics_root != Default::default()); + assert!(client.evaluate_block(&id, block).unwrap()); } #[test] @@ -263,6 +265,7 @@ mod tests { assert_eq!(block.header.number, 1); assert!(block.header.extrinsics_root != Default::default()); + assert!(client.evaluate_block(&id, block).unwrap()); } #[test] diff --git a/polkadot/cli/Cargo.toml b/polkadot/cli/Cargo.toml index cecfe86f5dbdc9a7eb273699b7a546f8d283a1f2..a3ab18f0f575aa24ff3651488421c1ac9d6b0fcc 100644 --- a/polkadot/cli/Cargo.toml +++ b/polkadot/cli/Cargo.toml @@ -5,29 +5,9 @@ authors = ["Parity Technologies <admin@parity.io>"] description = "Polkadot node implementation in Rust." [dependencies] -clap = { version = "~2.32", features = ["yaml"] } -error-chain = "0.12" log = "0.3" -slog = "^2" -lazy_static = "1.0" tokio = "0.1.7" futures = "0.1.17" -parking_lot = "0.4" exit-future = "0.1" substrate-cli = { git = "https://github.com/paritytech/substrate" } -substrate-client = { git = "https://github.com/paritytech/substrate" } -substrate-codec = { git = "https://github.com/paritytech/substrate" } -substrate-extrinsic-pool = { git = "https://github.com/paritytech/substrate" } -substrate-network = { git = "https://github.com/paritytech/substrate" } -substrate-primitives = { git = "https://github.com/paritytech/substrate" } -substrate-rpc = { git = "https://github.com/paritytech/substrate" } -substrate-rpc-servers = { git = "https://github.com/paritytech/substrate" } -substrate-runtime-primitives = { git = "https://github.com/paritytech/substrate" } -substrate-service = { git = "https://github.com/paritytech/substrate" } -substrate-state-machine = { git = "https://github.com/paritytech/substrate" } -substrate-telemetry = { git = "https://github.com/paritytech/substrate" } -polkadot-primitives = { path = "../primitives" } -polkadot-runtime = { path = "../runtime" } polkadot-service = { path = "../service" } -polkadot-transaction-pool = { path = "../transaction-pool" } - diff --git a/polkadot/consensus/src/lib.rs b/polkadot/consensus/src/lib.rs index 244fdeb55df26e369c07de11017c77b5610a38a4..944f3f85d5d49796f996a3d33c26cefd51dc892f 100644 --- a/polkadot/consensus/src/lib.rs +++ b/polkadot/consensus/src/lib.rs @@ -231,7 +231,10 @@ fn make_group_info(roster: DutyRoster, authorities: &[AuthorityId], local_id: Au } /// Polkadot proposer factory. -pub struct ProposerFactory<C, N, P> { +pub struct ProposerFactory<C, N, P> + where + P: PolkadotApi + Send + Sync + 'static +{ /// The client instance. pub client: Arc<P>, /// The transaction pool. @@ -407,7 +410,7 @@ struct LocalDuty { } /// The Polkadot proposer logic. -pub struct Proposer<C: PolkadotApi> { +pub struct Proposer<C: PolkadotApi + Send + Sync> { client: Arc<C>, dynamic_inclusion: DynamicInclusion, local_key: Arc<ed25519::Pair>, @@ -587,10 +590,10 @@ impl<C> bft::Proposer<Block> for Proposer<C> let local_id = self.local_key.public().0.into(); let mut next_index = { - let cur_index = self.transaction_pool.cull_and_get_pending(BlockId::hash(self.parent_hash), |pending| pending - .filter(|tx| tx.sender().map(|s| s == local_id).unwrap_or(false)) + let cur_index = self.transaction_pool.cull_and_get_pending(&BlockId::hash(self.parent_hash), |pending| pending + .filter(|tx| tx.verified.sender().map(|s| s == local_id).unwrap_or(false)) .last() - .map(|tx| Ok(tx.index())) + .map(|tx| Ok(tx.verified.index())) .unwrap_or_else(|| self.client.index(&self.parent_id, local_id)) ); @@ -636,9 +639,8 @@ impl<C> bft::Proposer<Block> for Proposer<C> index: extrinsic.index, function: extrinsic.function, }; - let uxt = UncheckedExtrinsic::new(extrinsic, signature); - - self.transaction_pool.import_unchecked_extrinsic(BlockId::hash(self.parent_hash), uxt) + let uxt: Vec<u8> = Decode::decode(&mut UncheckedExtrinsic::new(extrinsic, signature).encode().as_slice()).expect("Encoded extrinsic is valid"); + self.transaction_pool.submit_one(&BlockId::hash(self.parent_hash), uxt) .expect("locally signed extrinsic is valid; qed"); } } @@ -720,7 +722,7 @@ impl ProposalTiming { } /// Future which resolves upon the creation of a proposal. -pub struct CreateProposal<C: PolkadotApi> { +pub struct CreateProposal<C: PolkadotApi + Send + Sync> { parent_hash: Hash, parent_number: BlockNumber, parent_id: BlockId, @@ -732,7 +734,7 @@ pub struct CreateProposal<C: PolkadotApi> { offline: SharedOfflineTracker, } -impl<C> CreateProposal<C> where C: PolkadotApi { +impl<C> CreateProposal<C> where C: PolkadotApi + Send + Sync { fn propose_with(&self, candidates: Vec<CandidateReceipt>) -> Result<Block, Error> { use polkadot_api::BlockBuilder; use runtime_primitives::traits::{Hash as HashT, BlakeTwo256}; @@ -767,18 +769,18 @@ impl<C> CreateProposal<C> where C: PolkadotApi { { let mut unqueue_invalid = Vec::new(); - let result = self.transaction_pool.cull_and_get_pending(BlockId::hash(self.parent_hash), |pending_iterator| { + let result = self.transaction_pool.cull_and_get_pending(&BlockId::hash(self.parent_hash), |pending_iterator| { let mut pending_size = 0; for pending in pending_iterator { - if pending_size + pending.encoded_size() >= MAX_TRANSACTIONS_SIZE { break } + if pending_size + pending.verified.encoded_size() >= MAX_TRANSACTIONS_SIZE { break } - match block_builder.push_extrinsic(pending.primitive_extrinsic()) { + match block_builder.push_extrinsic(pending.original.clone()) { Ok(()) => { - pending_size += pending.encoded_size(); + pending_size += pending.verified.encoded_size(); } Err(e) => { trace!(target: "transaction-pool", "Invalid transaction: {}", e); - unqueue_invalid.push(pending.hash().clone()); + unqueue_invalid.push(pending.verified.hash().clone()); } } } @@ -819,7 +821,7 @@ impl<C> CreateProposal<C> where C: PolkadotApi { } } -impl<C> Future for CreateProposal<C> where C: PolkadotApi { +impl<C> Future for CreateProposal<C> where C: PolkadotApi + Send + Sync { type Item = Block; type Error = Error; diff --git a/polkadot/consensus/src/offline_tracker.rs b/polkadot/consensus/src/offline_tracker.rs index efb317ea5c913eb9117f3a4bc562159478bbaf9a..eb6c2480c414a0daa34143f0e2f687fdda9565e7 100644 --- a/polkadot/consensus/src/offline_tracker.rs +++ b/polkadot/consensus/src/offline_tracker.rs @@ -21,14 +21,18 @@ use polkadot_primitives::AccountId; use std::collections::HashMap; use std::time::{Instant, Duration}; -// time before we report a validator. -const REPORT_TIME: Duration = Duration::from_secs(60 * 5); - struct Observed { last_round_end: Instant, offline_since: Instant, } +#[derive(Eq, PartialEq)] +enum Activity { + Offline, + StillOffline(Duration), + Online, +} + impl Observed { fn new() -> Observed { let now = Instant::now(); @@ -38,31 +42,32 @@ impl Observed { } } - fn note_round_end(&mut self, was_online: bool) { - let now = Instant::now(); - + fn note_round_end(&mut self, now: Instant, was_online: Option<bool>) { self.last_round_end = now; - if was_online { + if let Some(false) = was_online { self.offline_since = now; } } - fn is_active(&self) -> bool { + /// Returns what we have observed about the online/offline state of the validator. + fn activity(&self) -> Activity { // can happen if clocks are not monotonic - if self.offline_since > self.last_round_end { return true } - self.last_round_end.duration_since(self.offline_since) < REPORT_TIME + if self.offline_since > self.last_round_end { return Activity::Online } + if self.offline_since == self.last_round_end { return Activity::Offline } + Activity::StillOffline(self.last_round_end.duration_since(self.offline_since)) } } /// Tracks offline validators and can issue a report for those offline. pub struct OfflineTracker { observed: HashMap<AccountId, Observed>, + block_instant: Instant, } impl OfflineTracker { /// Create a new tracker. pub fn new() -> Self { - OfflineTracker { observed: HashMap::new() } + OfflineTracker { observed: HashMap::new(), block_instant: Instant::now() } } /// Note new consensus is starting with the given set of validators. @@ -71,23 +76,33 @@ impl OfflineTracker { let set: HashSet<_> = validators.iter().cloned().collect(); self.observed.retain(|k, _| set.contains(k)); + + self.block_instant = Instant::now(); } /// Note that a round has ended. pub fn note_round_end(&mut self, validator: AccountId, was_online: bool) { - self.observed.entry(validator) - .or_insert_with(Observed::new) - .note_round_end(was_online); + self.observed.entry(validator).or_insert_with(Observed::new); + for (val, obs) in self.observed.iter_mut() { + obs.note_round_end( + self.block_instant, + if val == &validator { + Some(was_online) + } else { + None + } + ) + } } /// Generate a vector of indices for offline account IDs. pub fn reports(&self, validators: &[AccountId]) -> Vec<u32> { validators.iter() .enumerate() - .filter_map(|(i, v)| if self.is_online(v) { - None - } else { + .filter_map(|(i, v)| if self.is_known_offline_now(v) { Some(i as u32) + } else { + None }) .collect() } @@ -101,13 +116,15 @@ impl OfflineTracker { }; // we must think all validators reported externally are offline. - let thinks_online = self.is_online(v); - !thinks_online + self.is_known_offline_now(v) }) } - fn is_online(&self, v: &AccountId) -> bool { - self.observed.get(v).map(Observed::is_active).unwrap_or(true) + /// Rwturns true only if we have seen the validator miss the last round. For further + /// rounds where we can't say for sure that they're still offline, we give them the + /// benefit of the doubt. + fn is_known_offline_now(&self, v: &AccountId) -> bool { + self.observed.get(v).map(|o| o.activity() == Activity::Offline).unwrap_or(false) } } @@ -121,17 +138,30 @@ mod tests { let v = [0; 32].into(); let v2 = [1; 32].into(); let v3 = [2; 32].into(); + tracker.note_new_block(&[v, v2, v3]); tracker.note_round_end(v, true); tracker.note_round_end(v2, true); tracker.note_round_end(v3, true); + assert_eq!(tracker.reports(&[v, v2, v3]), vec![0u32; 0]); + + tracker.note_new_block(&[v, v2, v3]); + tracker.note_round_end(v, true); + tracker.note_round_end(v2, false); + tracker.note_round_end(v3, true); + assert_eq!(tracker.reports(&[v, v2, v3]), vec![1]); - let slash_time = REPORT_TIME + Duration::from_secs(5); - tracker.observed.get_mut(&v).unwrap().offline_since -= slash_time; - tracker.observed.get_mut(&v2).unwrap().offline_since -= slash_time; + tracker.note_new_block(&[v, v2, v3]); + tracker.note_round_end(v, false); + assert_eq!(tracker.reports(&[v, v2, v3]), vec![0]); - assert_eq!(tracker.reports(&[v, v2, v3]), vec![0, 1]); + tracker.note_new_block(&[v, v2, v3]); + tracker.note_round_end(v, false); + tracker.note_round_end(v2, true); + tracker.note_round_end(v3, false); + assert_eq!(tracker.reports(&[v, v2, v3]), vec![0, 2]); - tracker.note_new_block(&[v, v3]); + tracker.note_new_block(&[v, v2]); + tracker.note_round_end(v, false); assert_eq!(tracker.reports(&[v, v2, v3]), vec![0]); } } diff --git a/polkadot/consensus/src/service.rs b/polkadot/consensus/src/service.rs index b7302b5d430d0c6e5b4c2f728fcfd1ebdcbaa797..2db0e8ed707b032a62be34f833ab550d5a94f33d 100644 --- a/polkadot/consensus/src/service.rs +++ b/polkadot/consensus/src/service.rs @@ -62,32 +62,26 @@ fn start_bft<F, C>( const DELAY_UNTIL: Duration = Duration::from_millis(5000); let mut handle = LocalThreadHandle::current(); - let work = Delay::new(Instant::now() + DELAY_UNTIL) - .then(move |res| { - if let Err(e) = res { - warn!(target: "bft", "Failed to force delay of consensus: {:?}", e); - } + match bft_service.build_upon(&header) { + Ok(Some(bft_work)) => { + // do not poll work for some amount of time. + let work = Delay::new(Instant::now() + DELAY_UNTIL).then(move |res| { + if let Err(e) = res { + warn!(target: "bft", "Failed to force delay of consensus: {:?}", e); + } - match bft_service.build_upon(&header) { - Ok(maybe_bft_work) => { - if maybe_bft_work.is_some() { - debug!(target: "bft", "Starting agreement. After forced delay for {:?}", - DELAY_UNTIL); - } + debug!(target: "bft", "Starting agreement. After forced delay for {:?}", + DELAY_UNTIL); - maybe_bft_work - } - Err(e) => { - warn!(target: "bft", "BFT agreement error: {}", e); - None - } + bft_work + }); + if let Err(e) = handle.spawn_local(Box::new(work)) { + warn!(target: "bft", "Couldn't initialize BFT agreement: {:?}", e); } - }) - .map(|_| ()); - - if let Err(e) = handle.spawn_local(Box::new(work)) { - debug!(target: "bft", "Couldn't initialize BFT agreement: {:?}", e); - } + } + Ok(None) => trace!(target: "bft", "Could not start agreement on top of {}", header.hash()), + Err(e) => warn!(target: "bft", "BFT agreement error: {}", e), + } } // creates a task to prune redundant entries in availability store upon block finalization @@ -198,6 +192,7 @@ impl Service { client.import_notification_stream().for_each(move |notification| { if notification.is_new_best { + trace!(target: "bft", "Attempting to start new consensus round after import notification of {:?}", notification.hash); start_bft(notification.header, bft_service.clone()); } Ok(()) @@ -221,15 +216,12 @@ impl Service { let c = client.clone(); let s = bft_service.clone(); - interval.map_err(|e| debug!("Timer error: {:?}", e)).for_each(move |_| { + interval.map_err(|e| debug!(target: "bft", "Timer error: {:?}", e)).for_each(move |_| { if let Ok(best_block) = c.best_block_header() { let hash = best_block.hash(); - let last_agreement = s.last_agreement(); - let can_build_upon = last_agreement - .map_or(true, |x| !x.live || x.parent_hash != hash); - if hash == prev_best && can_build_upon { - debug!("Starting consensus round after a timeout"); + if hash == prev_best { + debug!(target: "bft", "Starting consensus round after a timeout"); start_bft(best_block, s.clone()); } prev_best = hash; diff --git a/polkadot/network/src/lib.rs b/polkadot/network/src/lib.rs index 48b382f66258e7cda7f9e37c3267687abce3d641..5fcd6a951606328b0c7f1f8dbb6f1b5e850ee4c0 100644 --- a/polkadot/network/src/lib.rs +++ b/polkadot/network/src/lib.rs @@ -73,7 +73,7 @@ pub const DOT_PROTOCOL_ID: ::substrate_network::ProtocolId = *b"dot"; type FullStatus = GenericFullStatus<Block>; /// Specialization of the network service for the polkadot protocol. -pub type NetworkService = ::substrate_network::Service<Block, PolkadotProtocol>; +pub type NetworkService = ::substrate_network::Service<Block, PolkadotProtocol, Hash>; /// Status of a Polkadot node. #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] diff --git a/polkadot/primitives/src/lib.rs b/polkadot/primitives/src/lib.rs index bf3e2fd565368facf51dd08570d6e76270e72b03..ecff56529b8f77eae6cf255da00a45fa19843b4e 100644 --- a/polkadot/primitives/src/lib.rs +++ b/polkadot/primitives/src/lib.rs @@ -120,4 +120,4 @@ pub struct InherentData { pub parachain_heads: Vec<::parachain::CandidateReceipt>, /// Indices of offline validators. pub offline_indices: Vec<u32>, -} +} \ No newline at end of file diff --git a/polkadot/runtime/src/lib.rs b/polkadot/runtime/src/lib.rs index 2163fba3f4a98bde20b7fd2b1684b9958aa13548..3bf28f193548694050eed3b5be5fb1bb3045d69f 100644 --- a/polkadot/runtime/src/lib.rs +++ b/polkadot/runtime/src/lib.rs @@ -250,7 +250,7 @@ pub mod api { apply_extrinsic => |extrinsic| super::Executive::apply_extrinsic(extrinsic), execute_block => |block| super::Executive::execute_block(block), finalise_block => |()| super::Executive::finalise_block(), - inherent_extrinsics => |inherent| super::inherent_extrinsics(inherent), + inherent_extrinsics => |(inherent, version)| super::inherent_extrinsics(inherent, version), validator_count => |()| super::Session::validator_count(), validators => |()| super::Session::validators(), duty_roster => |()| super::Parachains::calculate_duty_roster(), diff --git a/polkadot/runtime/src/utils.rs b/polkadot/runtime/src/utils.rs index acef06092539ff6e6163c46ca74a2e17a5c1d7fb..c016d3690ddd2bf44c5339b225c178345f880a7e 100644 --- a/polkadot/runtime/src/utils.rs +++ b/polkadot/runtime/src/utils.rs @@ -22,9 +22,10 @@ use runtime_primitives::traits::{Checkable, AuxLookup}; use timestamp::Call as TimestampCall; use parachains::Call as ParachainsCall; use session::Call as SessionCall; +use version::RuntimeVersion; /// Produces the list of inherent extrinsics. -pub fn inherent_extrinsics(data: ::primitives::InherentData) -> Vec<UncheckedExtrinsic> { +pub fn inherent_extrinsics(data: ::primitives::InherentData, runtime_version: RuntimeVersion) -> Vec<UncheckedExtrinsic> { let make_inherent = |function| UncheckedExtrinsic::new( Extrinsic { signed: Default::default(), @@ -39,7 +40,7 @@ pub fn inherent_extrinsics(data: ::primitives::InherentData) -> Vec<UncheckedExt make_inherent(Call::Parachains(ParachainsCall::set_heads(data.parachain_heads))), ]; - if !data.offline_indices.is_empty() { + if !data.offline_indices.is_empty() && runtime_version.spec_version == 4 { inherent.push(make_inherent( Call::Session(SessionCall::note_offline(data.offline_indices)) )); diff --git a/polkadot/service/Cargo.toml b/polkadot/service/Cargo.toml index b6a32b04b39293825d416d2bda0c0c14a2a066b0..2de430603a3490df7d38fa9ecd2fdfab519ceac8 100644 --- a/polkadot/service/Cargo.toml +++ b/polkadot/service/Cargo.toml @@ -24,6 +24,5 @@ substrate-runtime-io = { git = "https://github.com/paritytech/substrate" } substrate-primitives = { git = "https://github.com/paritytech/substrate" } substrate-network = { git = "https://github.com/paritytech/substrate" } substrate-client = { git = "https://github.com/paritytech/substrate" } -substrate-codec = { git = "https://github.com/paritytech/substrate" } substrate-service = { git = "https://github.com/paritytech/substrate" } substrate-telemetry = { git = "https://github.com/paritytech/substrate" } diff --git a/polkadot/service/src/lib.rs b/polkadot/service/src/lib.rs index 4e59a22ca2b1fbfcc819faae8d6385972c243293..ae6d4779b1bbcf6a2400b04298584161e1c84920 100644 --- a/polkadot/service/src/lib.rs +++ b/polkadot/service/src/lib.rs @@ -29,7 +29,6 @@ extern crate polkadot_transaction_pool as transaction_pool; extern crate polkadot_network; extern crate substrate_primitives as primitives; extern crate substrate_network as network; -extern crate substrate_codec as codec; extern crate substrate_client as client; extern crate substrate_service as service; extern crate tokio; @@ -42,14 +41,12 @@ extern crate hex_literal; pub mod chain_spec; use std::sync::Arc; -use std::collections::HashMap; - -use codec::{Encode, Decode}; +use tokio::prelude::{Stream, Future}; use transaction_pool::TransactionPool; use polkadot_api::{PolkadotApi, light::RemotePolkadotApiWrapper}; use polkadot_primitives::{parachain, AccountId, Block, BlockId, Hash}; use polkadot_runtime::GenesisConfig; -use client::Client; +use client::{Client, BlockchainEvents}; use polkadot_network::{PolkadotProtocol, consensus::ConsensusNetwork}; use tokio::runtime::TaskExecutor; use service::FactoryFullConfiguration; @@ -63,7 +60,7 @@ pub use client::ExecutionStrategy; pub type ChainSpec = service::ChainSpec<GenesisConfig>; /// Polkadot client type for specialised `Components`. pub type ComponentClient<C> = Client<<C as Components>::Backend, <C as Components>::Executor, Block>; -pub type NetworkService = network::Service<Block, <Factory as service::ServiceFactory>::NetworkProtocol>; +pub type NetworkService = network::Service<Block, <Factory as service::ServiceFactory>::NetworkProtocol, Hash>; /// A collection of type to generalise Polkadot specific components over full / light client. pub trait Components: service::Components { @@ -106,16 +103,11 @@ pub struct Factory; impl service::ServiceFactory for Factory { type Block = Block; + type ExtrinsicHash = Hash; type NetworkProtocol = PolkadotProtocol; type RuntimeDispatch = polkadot_executor::Executor; - type FullExtrinsicPool = TransactionPoolAdapter< - service::FullBackend<Self>, - service::FullExecutor<Self>, - service::FullClient<Self> - >; - type LightExtrinsicPool = TransactionPoolAdapter< - service::LightBackend<Self>, - service::LightExecutor<Self>, + type FullExtrinsicPoolApi = transaction_pool::ChainApi<service::FullClient<Self>>; + type LightExtrinsicPoolApi = transaction_pool::ChainApi< RemotePolkadotApiWrapper<service::LightBackend<Self>, service::LightExecutor<Self>> >; type Genesis = GenesisConfig; @@ -124,25 +116,17 @@ impl service::ServiceFactory for Factory { const NETWORK_PROTOCOL_ID: network::ProtocolId = ::polkadot_network::DOT_PROTOCOL_ID; fn build_full_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc<service::FullClient<Self>>) - -> Result<Self::FullExtrinsicPool, Error> + -> Result<TransactionPool<service::FullClient<Self>>, Error> { let api = client.clone(); - Ok(TransactionPoolAdapter { - pool: Arc::new(TransactionPool::new(config, api)), - client: client, - imports_external_transactions: true, - }) + Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(api))) } fn build_light_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc<service::LightClient<Self>>) - -> Result<Self::LightExtrinsicPool, Error> + -> Result<TransactionPool<RemotePolkadotApiWrapper<service::LightBackend<Self>, service::LightExecutor<Self>>>, Error> { let api = Arc::new(RemotePolkadotApiWrapper(client.clone())); - Ok(TransactionPoolAdapter { - pool: Arc::new(TransactionPool::new(config, api)), - client: client, - imports_external_transactions: false, - }) + Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(api))) } fn build_network_protocol(config: &Configuration) @@ -182,8 +166,18 @@ impl <C: Components> Service<C> { pub fn new_light(config: Configuration, executor: TaskExecutor) -> Result<Service<LightComponents<Factory>>, Error> { - let service = service::Service::<LightComponents<Factory>>::new(config, executor)?; + let service = service::Service::<LightComponents<Factory>>::new(config, executor.clone())?; let api = Arc::new(RemotePolkadotApiWrapper(service.client())); + let pool = service.extrinsic_pool(); + let events = service.client().import_notification_stream() + .for_each(move |notification| { + // re-verify all transactions without the sender. + pool.retry_verification(&BlockId::hash(notification.hash), None) + .map_err(|e| warn!("Error re-verifying transactions: {:?}", e))?; + Ok(()) + }) + .then(|_| Ok(())); + executor.spawn(events); Ok(Service { client: service.client(), network: service.network(), @@ -212,7 +206,16 @@ pub fn new_full(config: Configuration, executor: TaskExecutor) let is_validator = (config.roles & Roles::AUTHORITY) == Roles::AUTHORITY; let service = service::Service::<FullComponents<Factory>>::new(config, executor.clone())?; - + let pool = service.extrinsic_pool(); + let events = service.client().import_notification_stream() + .for_each(move |notification| { + // re-verify all transactions without the sender. + pool.retry_verification(&BlockId::hash(notification.hash), None) + .map_err(|e| warn!("Error re-verifying transactions: {:?}", e))?; + Ok(()) + }) + .then(|_| Ok(())); + executor.spawn(events); // Spin consensus service if configured let consensus = if is_validator { // Load the first available key @@ -261,103 +264,3 @@ impl<C: Components> ::std::ops::Deref for Service<C> { &self.inner } } - -/// Transaction pool adapter. -pub struct TransactionPoolAdapter<B, E, A> where A: Send + Sync, E: Send + Sync { - imports_external_transactions: bool, - pool: Arc<TransactionPool<A>>, - client: Arc<Client<B, E, Block>>, -} - -impl<B, E, A> TransactionPoolAdapter<B, E, A> - where - A: Send + Sync, - B: client::backend::Backend<Block, KeccakHasher, RlpCodec> + Send + Sync, - E: client::CallExecutor<Block, KeccakHasher, RlpCodec> + Send + Sync, -{ - fn best_block_id(&self) -> Option<BlockId> { - self.client.info() - .map(|info| BlockId::hash(info.chain.best_hash)) - .map_err(|e| { - debug!("Error getting best block: {:?}", e); - }) - .ok() - } -} - -impl<B, E, A> network::TransactionPool<Block> for TransactionPoolAdapter<B, E, A> - where - B: client::backend::Backend<Block, KeccakHasher, RlpCodec> + Send + Sync, - E: client::CallExecutor<Block, KeccakHasher, RlpCodec> + Send + Sync, - A: polkadot_api::PolkadotApi + Send + Sync, -{ - fn transactions(&self) -> Vec<(Hash, Vec<u8>)> { - let best_block_id = match self.best_block_id() { - Some(id) => id, - None => return vec![], - }; - self.pool.cull_and_get_pending(best_block_id, |pending| pending - .map(|t| { - let hash = t.hash().clone(); - (hash, t.primitive_extrinsic()) - }) - .collect() - ).unwrap_or_else(|e| { - warn!("Error retrieving pending set: {}", e); - vec![] - }) - } - - fn import(&self, transaction: &Vec<u8>) -> Option<Hash> { - if !self.imports_external_transactions { - return None; - } - - let encoded = transaction.encode(); - if let Some(uxt) = Decode::decode(&mut &encoded[..]) { - let best_block_id = self.best_block_id()?; - match self.pool.import_unchecked_extrinsic(best_block_id, uxt) { - Ok(xt) => Some(*xt.hash()), - Err(e) => match *e.kind() { - transaction_pool::ErrorKind::AlreadyImported(hash) => Some(hash[..].into()), - _ => { - debug!(target: "txpool", "Error adding transaction to the pool: {:?}", e); - None - }, - } - } - } else { - debug!(target: "txpool", "Error decoding transaction"); - None - } - } - - fn on_broadcasted(&self, propagations: HashMap<Hash, Vec<String>>) { - self.pool.on_broadcasted(propagations) - } -} - -impl<B, E, A> service::ExtrinsicPool<Block> for TransactionPoolAdapter<B, E, A> - where - B: client::backend::Backend<Block, KeccakHasher, RlpCodec> + Send + Sync + 'static, - E: client::CallExecutor<Block, KeccakHasher, RlpCodec> + Send + Sync + 'static, - A: polkadot_api::PolkadotApi + Send + Sync + 'static, -{ - type Api = TransactionPool<A>; - - fn prune_imported(&self, hash: &Hash) { - let block = BlockId::hash(*hash); - if let Err(e) = self.pool.cull(block) { - warn!("Culling error: {:?}", e); - } - - if let Err(e) = self.pool.retry_verification(block) { - warn!("Re-verifying error: {:?}", e); - } - } - - fn api(&self) -> Arc<Self::Api> { - self.pool.clone() - } -} - diff --git a/polkadot/transaction-pool/src/error.rs b/polkadot/transaction-pool/src/error.rs index 99281e8d7864174bdd43c71d0141cae90fb52377..66876bc6100ad882c0debaddab301b431ccd496e 100644 --- a/polkadot/transaction-pool/src/error.rs +++ b/polkadot/transaction-pool/src/error.rs @@ -14,14 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see <http://www.gnu.org/licenses/>. -use extrinsic_pool::{self, txpool}; +use extrinsic_pool; use polkadot_api; use primitives::Hash; use runtime::{Address, UncheckedExtrinsic}; error_chain! { links { - Pool(txpool::Error, txpool::ErrorKind); + Pool(extrinsic_pool::Error, extrinsic_pool::ErrorKind); Api(polkadot_api::Error, polkadot_api::ErrorKind); } errors { @@ -33,7 +33,7 @@ error_chain! { /// Attempted to queue an inherent transaction. IsInherent(xt: UncheckedExtrinsic) { description("Inherent transactions cannot be queued."), - display("Inehrent transactions cannot be queued."), + display("Inherent transactions cannot be queued."), } /// Attempted to queue a transaction with bad signature. BadSignature(e: &'static str) { @@ -63,10 +63,10 @@ error_chain! { } } -impl extrinsic_pool::api::Error for Error { - fn into_pool_error(self) -> ::std::result::Result<txpool::Error, Self> { +impl extrinsic_pool::IntoPoolError for Error { + fn into_pool_error(self) -> ::std::result::Result<extrinsic_pool::Error, Self> { match self { - Error(ErrorKind::Pool(e), c) => Ok(txpool::Error(e, c)), + Error(ErrorKind::Pool(e), c) => Ok(extrinsic_pool::Error(e, c)), e => Err(e), } } diff --git a/polkadot/transaction-pool/src/lib.rs b/polkadot/transaction-pool/src/lib.rs index 3ba340921ac8a7df9e1d0999ef4585452026809b..eb048518af40545ff973f5d153093fb40c89cb44 100644 --- a/polkadot/transaction-pool/src/lib.rs +++ b/polkadot/transaction-pool/src/lib.rs @@ -38,26 +38,18 @@ mod error; use std::{ cmp::Ordering, - collections::{BTreeMap, HashMap}, - ops::Deref, + collections::HashMap, sync::Arc, }; use codec::{Decode, Encode}; -use extrinsic_pool::{ - api::{ExtrinsicPool, EventStream}, - txpool::{self, Readiness, scoring::{Change, Choice}}, - watcher::Watcher, - Pool, - Listener, -}; +use extrinsic_pool::{Readiness, scoring::{Change, Choice}, VerifiedFor, ExtrinsicFor}; use polkadot_api::PolkadotApi; -use primitives::{AccountId, BlockId, Hash, Index, UncheckedExtrinsic as FutureProofUncheckedExtrinsic}; +use primitives::{AccountId, BlockId, Block, Hash, Index}; use runtime::{Address, UncheckedExtrinsic}; -use substrate_primitives::Bytes; use substrate_runtime_primitives::traits::{Bounded, Checkable, Hash as HashT, BlakeTwo256}; -pub use extrinsic_pool::txpool::{Options, Status, LightStatus, VerifiedTransaction as VerifiedTransactionOps}; +pub use extrinsic_pool::{Options, Status, LightStatus, VerifiedTransaction as VerifiedTransactionOps}; pub use error::{Error, ErrorKind, Result}; /// Maximal size of a single encoded extrinsic. @@ -68,28 +60,20 @@ const MAX_TRANSACTION_SIZE: usize = 4 * 1024 * 1024; /// Type alias for convenience. pub type CheckedExtrinsic = <UncheckedExtrinsic as Checkable<fn(Address) -> std::result::Result<AccountId, &'static str>>>::Checked; +/// Type alias for polkadot transaction pool. +pub type TransactionPool<A> = extrinsic_pool::Pool<ChainApi<A>>; + /// A verified transaction which should be includable and non-inherent. #[derive(Clone, Debug)] pub struct VerifiedTransaction { - original: UncheckedExtrinsic, inner: Option<CheckedExtrinsic>, sender: Option<AccountId>, hash: Hash, encoded_size: usize, + index: Index, } impl VerifiedTransaction { - /// Access the underlying transaction. - pub fn as_transaction(&self) -> &UncheckedExtrinsic { - &self.original - } - - /// Convert to primitive unchecked extrinsic. - pub fn primitive_extrinsic(&self) -> ::primitives::UncheckedExtrinsic { - Decode::decode(&mut self.as_transaction().encode().as_slice()) - .expect("UncheckedExtrinsic shares repr with Vec<u8>; qed") - } - /// Consume the verified transaction, yielding the checked counterpart. pub fn into_inner(self) -> Option<CheckedExtrinsic> { self.inner @@ -107,7 +91,7 @@ impl VerifiedTransaction { /// Get the account ID of the sender of this transaction. pub fn index(&self) -> Index { - self.original.extrinsic.index + self.index } /// Get encoded size of the transaction. @@ -121,7 +105,7 @@ impl VerifiedTransaction { } } -impl txpool::VerifiedTransaction for VerifiedTransaction { +impl extrinsic_pool::VerifiedTransaction for VerifiedTransaction { type Hash = Hash; type Sender = Option<AccountId>; @@ -138,139 +122,25 @@ impl txpool::VerifiedTransaction for VerifiedTransaction { } } -/// Scoring implementation for polkadot transactions. -#[derive(Debug)] -pub struct Scoring; - -impl txpool::Scoring<VerifiedTransaction> for Scoring { - type Score = u64; - type Event = (); - - fn compare(&self, old: &VerifiedTransaction, other: &VerifiedTransaction) -> Ordering { - old.index().cmp(&other.index()) - } - - fn choose(&self, old: &VerifiedTransaction, new: &VerifiedTransaction) -> Choice { - if old.is_fully_verified() { - assert!(new.is_fully_verified(), "Scoring::choose called with transactions from different senders"); - if old.index() == new.index() { - // TODO [ToDr] Do we allow replacement? If yes then it should be Choice::ReplaceOld - return Choice::RejectNew; - } - } - - // This will keep both transactions, even though they have the same indices. - // It's fine for not fully verified transactions, we might also allow it for - // verified transactions but it would mean that only one of the two is actually valid - // (most likely the first to be included in the block). - Choice::InsertNew - } - - fn update_scores( - &self, - xts: &[txpool::Transaction<VerifiedTransaction>], - scores: &mut [Self::Score], - _change: Change<()> - ) { - for i in 0..xts.len() { - if !xts[i].is_fully_verified() { - scores[i] = 0; - } else { - // all the same score since there are no fees. - // TODO: prioritize things like misbehavior or fishermen reports - scores[i] = 1; - } - } - } - - fn should_replace(&self, old: &VerifiedTransaction, _new: &VerifiedTransaction) -> Choice { - // Always replace not fully verified transactions. - match old.is_fully_verified() { - true => Choice::RejectNew, - false => Choice::ReplaceOld - } - } -} - -/// Readiness evaluator for polkadot transactions. -pub struct Ready<'a, A: 'a + PolkadotApi> { - at_block: BlockId, - api: &'a A, - known_nonces: HashMap<AccountId, ::primitives::Index>, +/// The polkadot transaction pool logic. +pub struct ChainApi<A> { + api: Arc<A>, } -impl<'a, A: 'a + PolkadotApi> Ready<'a, A> { - /// Create a new readiness evaluator at the given block. Requires that - /// the ID has already been checked for local corresponding and available state. - fn create(at: BlockId, api: &'a A) -> Self { - Ready { - at_block: at, +impl<A> ChainApi<A> where + A: PolkadotApi, +{ + const NO_ACCOUNT: &'static str = "Account not found."; + /// Create a new instance. + pub fn new(api: Arc<A>) -> Self { + ChainApi { api, - known_nonces: HashMap::new(), } } -} - -impl<'a, T: 'a + PolkadotApi> Clone for Ready<'a, T> { - fn clone(&self) -> Self { - Ready { - at_block: self.at_block.clone(), - api: self.api, - known_nonces: self.known_nonces.clone(), - } - } -} - -impl<'a, A: 'a + PolkadotApi> txpool::Ready<VerifiedTransaction> for Ready<'a, A> -{ - fn is_ready(&mut self, xt: &VerifiedTransaction) -> Readiness { - let sender = match xt.sender() { - Some(sender) => sender, - None => return Readiness::Future - }; - - trace!(target: "transaction-pool", "Checking readiness of {} (from {})", xt.hash, Hash::from(sender)); - - // TODO: find a way to handle index error properly -- will need changes to - // transaction-pool trait. - let (api, at_block) = (&self.api, &self.at_block); - let next_index = self.known_nonces.entry(sender) - .or_insert_with(|| api.index(at_block, sender).ok().unwrap_or_else(Bounded::max_value)); - - trace!(target: "transaction-pool", "Next index for sender is {}; xt index is {}", next_index, xt.original.extrinsic.index); - - let result = match xt.original.extrinsic.index.cmp(&next_index) { - // TODO: this won't work perfectly since accounts can now be killed, returning the nonce - // to zero. - // We should detect if the index was reset and mark all transactions as `Stale` for cull to work correctly. - // Otherwise those transactions will keep occupying the queue. - // Perhaps we could mark as stale if `index - state_index` > X? - Ordering::Greater => Readiness::Future, - Ordering::Equal => Readiness::Ready, - // TODO [ToDr] Should mark transactions referrencing too old blockhash as `Stale` as well. - Ordering::Less => Readiness::Stale, - }; - - // remember to increment `next_index` - *next_index = next_index.saturating_add(1); - - result - } -} - -pub struct Verifier<'a, A: 'a> { - api: &'a A, - at_block: BlockId, -} -impl<'a, A> Verifier<'a, A> where - A: 'a + PolkadotApi, -{ - const NO_ACCOUNT: &'static str = "Account not found."; - - fn lookup(&self, address: Address) -> ::std::result::Result<AccountId, &'static str> { + fn lookup(&self, at: &BlockId, address: Address) -> ::std::result::Result<AccountId, &'static str> { // TODO [ToDr] Consider introducing a cache for this. - match self.api.lookup(&self.at_block, address.clone()) { + match self.api.lookup(at, address.clone()) { Ok(Some(address)) => Ok(address), Ok(None) => Err(Self::NO_ACCOUNT.into()), Err(e) => { @@ -281,28 +151,32 @@ impl<'a, A> Verifier<'a, A> where } } -impl<'a, A> txpool::Verifier<UncheckedExtrinsic> for Verifier<'a, A> where - A: 'a + PolkadotApi, +impl<A> extrinsic_pool::ChainApi for ChainApi<A> where + A: PolkadotApi + Send + Sync, { - type VerifiedTransaction = VerifiedTransaction; + type Block = Block; + type Hash = Hash; + type Sender = Option<AccountId>; + type VEx = VerifiedTransaction; + type Ready = HashMap<AccountId, u32>; type Error = Error; + type Score = u64; + type Event = (); - fn verify_transaction(&self, uxt: UncheckedExtrinsic) -> Result<Self::VerifiedTransaction> { + fn verify_transaction(&self, at: &BlockId, xt: &ExtrinsicFor<Self>) -> Result<Self::VEx> { + let encoded = xt.encode(); + let uxt = UncheckedExtrinsic::decode(&mut encoded.as_slice()).ok_or_else(|| ErrorKind::InvalidExtrinsicFormat)?; if !uxt.is_signed() { bail!(ErrorKind::IsInherent(uxt)) } - let encoded = uxt.encode(); - let encoded_size = encoded.len(); - + let (encoded_size, hash) = (encoded.len(), BlakeTwo256::hash(&encoded)); if encoded_size > MAX_TRANSACTION_SIZE { bail!(ErrorKind::TooLarge(encoded_size, MAX_TRANSACTION_SIZE)); } - let hash = BlakeTwo256::hash(&encoded); debug!(target: "transaction-pool", "Transaction submitted: {}", ::substrate_primitives::hexdisplay::HexDisplay::from(&encoded)); - - let inner = match uxt.clone().check_with(|a| self.lookup(a)) { + let inner = match uxt.clone().check_with(|a| self.lookup(at, a)) { Ok(xt) => Some(xt), // keep the transaction around in the future pool and attempt to promote it later. Err(Self::NO_ACCOUNT) => None, @@ -317,157 +191,101 @@ impl<'a, A> txpool::Verifier<UncheckedExtrinsic> for Verifier<'a, A> where } Ok(VerifiedTransaction { - original: uxt, + index: uxt.extrinsic.index, inner, sender, hash, - encoded_size + encoded_size, }) } -} - -/// The polkadot transaction pool. -/// -/// Wraps a `extrinsic_pool::Pool`. -pub struct TransactionPool<A> { - inner: Pool<Hash, VerifiedTransaction, Scoring, Error>, - api: Arc<A>, -} -impl<A> TransactionPool<A> where - A: PolkadotApi, -{ - /// Create a new transaction pool. - pub fn new(options: Options, api: Arc<A>) -> Self { - TransactionPool { - inner: Pool::new(options, Scoring), - api, - } + fn ready(&self) -> Self::Ready { + HashMap::default() } - /// Attempt to directly import `UncheckedExtrinsic` without going through serialization. - pub fn import_unchecked_extrinsic(&self, block: BlockId, uxt: UncheckedExtrinsic) -> Result<Arc<VerifiedTransaction>> { - let verifier = Verifier { - api: &*self.api, - at_block: block, - }; - self.inner.submit(verifier, vec![uxt]).map(|mut v| v.swap_remove(0)) - } - - /// Retry to import all semi-verified transactions (unknown account indices) - pub fn retry_verification(&self, block: BlockId) -> Result<()> { - let to_reverify = self.inner.remove_sender(None); - let verifier = Verifier { - api: &*self.api, - at_block: block, + fn is_ready(&self, at: &BlockId, known_nonces: &mut Self::Ready, xt: &VerifiedFor<Self>) -> Readiness { + let sender = match xt.verified.sender() { + Some(sender) => sender, + None => return Readiness::Future }; - self.inner.submit(verifier, to_reverify.into_iter().map(|tx| tx.original.clone()))?; - Ok(()) - } - - /// Reverify transaction that has been reported incorrect. - /// - /// Returns `Ok(None)` in case the hash is missing, `Err(e)` in case of verification error and new transaction - /// reference otherwise. - /// - /// TODO [ToDr] That method is currently unused, should be used together with BlockBuilder - /// when we detect that particular transaction has failed. - /// In such case we will attempt to remove or re-verify it. - pub fn reverify_transaction(&self, block: BlockId, hash: Hash) -> Result<Option<Arc<VerifiedTransaction>>> { - let result = self.inner.remove(&[hash], false).pop().expect("One hash passed; one result received; qed"); - if let Some(tx) = result { - self.import_unchecked_extrinsic(block, tx.original.clone()).map(Some) - } else { - Ok(None) - } - } + trace!(target: "transaction-pool", "Checking readiness of {} (from {})", xt.verified.hash, Hash::from(sender)); - /// Cull old transactions from the queue. - pub fn cull(&self, block: BlockId) -> Result<usize> { - let ready = Ready::create(block, &*self.api); - Ok(self.inner.cull(None, ready)) - } + // TODO: find a way to handle index error properly -- will need changes to + // transaction-pool trait. + let api = &self.api; + let next_index = known_nonces.entry(sender) + .or_insert_with(|| api.index(at, sender).ok().unwrap_or_else(Bounded::max_value)); - /// Cull transactions from the queue and then compute the pending set. - pub fn cull_and_get_pending<F, T>(&self, block: BlockId, f: F) -> Result<T> where - F: FnOnce(txpool::PendingIterator<VerifiedTransaction, Ready<A>, Scoring, Listener<Hash>>) -> T, - { - let ready = Ready::create(block, &*self.api); - self.inner.cull(None, ready.clone()); - Ok(self.inner.pending(ready, f)) - } + trace!(target: "transaction-pool", "Next index for sender is {}; xt index is {}", next_index, xt.verified.index); - /// Remove a set of transactions idenitified by hashes. - pub fn remove(&self, hashes: &[Hash], is_valid: bool) -> Vec<Option<Arc<VerifiedTransaction>>> { - self.inner.remove(hashes, is_valid) - } -} + let result = match xt.verified.index.cmp(&next_index) { + // TODO: this won't work perfectly since accounts can now be killed, returning the nonce + // to zero. + // We should detect if the index was reset and mark all transactions as `Stale` for cull to work correctly. + // Otherwise those transactions will keep occupying the queue. + // Perhaps we could mark as stale if `index - state_index` > X? + Ordering::Greater => Readiness::Future, + Ordering::Equal => Readiness::Ready, + // TODO [ToDr] Should mark transactions referencing too old blockhash as `Stale` as well. + Ordering::Less => Readiness::Stale, + }; -impl<A> Deref for TransactionPool<A> { - type Target = Pool<Hash, VerifiedTransaction, Scoring, Error>; + // remember to increment `next_index` + *next_index = next_index.saturating_add(1); - fn deref(&self) -> &Self::Target { - &self.inner + result } -} -// TODO: more general transaction pool, which can handle more kinds of vec-encoded transactions, -// even when runtime is out of date. -impl<A> ExtrinsicPool<FutureProofUncheckedExtrinsic, BlockId, Hash> for TransactionPool<A> where - A: Send + Sync + 'static, - A: PolkadotApi, -{ - type Error = Error; - type InPool = BTreeMap<AccountId, Vec<Bytes>>; - - fn submit(&self, block: BlockId, xts: Vec<FutureProofUncheckedExtrinsic>) -> Result<Vec<Hash>> { - xts.into_iter() - .map(|xt| xt.encode()) - .map(|encoded| { - let decoded = UncheckedExtrinsic::decode(&mut &encoded[..]).ok_or(ErrorKind::InvalidExtrinsicFormat)?; - let tx = self.import_unchecked_extrinsic(block, decoded)?; - Ok(*tx.hash()) - }) - .collect() + fn compare(old: &VerifiedFor<Self>, other: &VerifiedFor<Self>) -> Ordering { + old.verified.index().cmp(&other.verified.index()) } - fn submit_and_watch(&self, block: BlockId, xt: FutureProofUncheckedExtrinsic) -> Result<Watcher<Hash>> { - let encoded = xt.encode(); - let decoded = UncheckedExtrinsic::decode(&mut &encoded[..]).ok_or(ErrorKind::InvalidExtrinsicFormat)?; - - let verifier = Verifier { - api: &*self.api, - at_block: block, - }; - - self.inner.submit_and_watch(verifier, decoded) - } + fn choose(old: &VerifiedFor<Self>, new: &VerifiedFor<Self>) -> Choice { + if old.verified.is_fully_verified() { + assert!(new.verified.is_fully_verified(), "Scoring::choose called with transactions from different senders"); + if old.verified.index() == new.verified.index() { + return Choice::ReplaceOld; + } + } - fn light_status(&self) -> LightStatus { - self.inner.light_status() + // This will keep both transactions, even though they have the same indices. + // It's fine for not fully verified transactions, we might also allow it for + // verified transactions but it would mean that only one of the two is actually valid + // (most likely the first to be included in the block). + Choice::InsertNew } - fn import_notification_stream(&self) -> EventStream { - self.inner.import_notification_stream() + fn update_scores( + xts: &[extrinsic_pool::Transaction<VerifiedFor<Self>>], + scores: &mut [Self::Score], + _change: Change<()> + ) { + for i in 0..xts.len() { + if !xts[i].verified.is_fully_verified() { + scores[i] = 0; + } else { + // all the same score since there are no fees. + // TODO: prioritize things like misbehavior or fishermen reports + scores[i] = 1; + } + } } - fn all(&self) -> Self::InPool { - self.inner.all(|it| it.fold(Default::default(), |mut map: Self::InPool, tx| { - // Map with `null` key is not serializable, so we fallback to default accountId. - map.entry(tx.sender().unwrap_or_default()) - .or_insert_with(Vec::new) - // use bytes type to make it serialize nicer. - .push(Bytes(tx.primitive_extrinsic())); - map - })) + fn should_replace(old: &VerifiedFor<Self>, _new: &VerifiedFor<Self>) -> Choice { + if old.verified.is_fully_verified() { + // Don't allow new transactions if we are reaching the limit. + Choice::RejectNew + } else { + // Always replace not fully verified transactions. + Choice::ReplaceOld + } } } #[cfg(test)] mod tests { use std::sync::{atomic::{self, AtomicBool}, Arc}; - use super::TransactionPool; use substrate_keyring::Keyring::{self, *}; use codec::{Decode, Encode}; use polkadot_api::{PolkadotApi, BlockBuilder, Result}; @@ -476,6 +294,8 @@ mod tests { use runtime::{RawAddress, Call, TimestampCall, BareExtrinsic, Extrinsic, UncheckedExtrinsic}; use primitives::parachain::{DutyRoster, Id as ParaId}; use substrate_runtime_primitives::{MaybeUnsigned, generic}; + use extrinsic_pool::Pool; + use super::ChainApi; struct TestBlockBuilder; impl BlockBuilder for TestBlockBuilder { @@ -545,7 +365,7 @@ mod tests { } } - fn uxt(who: Keyring, nonce: Index, use_id: bool) -> UncheckedExtrinsic { + fn uxt(who: Keyring, nonce: Index, use_id: bool) -> FutureProofUncheckedExtrinsic { let sxt = BareExtrinsic { signed: who.to_raw_public().into(), index: nonce, @@ -567,20 +387,20 @@ mod tests { )}, index: sxt.index, function: sxt.function, - }, MaybeUnsigned(sig.into())).using_encoded(|e| UncheckedExtrinsic::decode(&mut &e[..])).unwrap() + }, MaybeUnsigned(sig.into())).using_encoded(|e| FutureProofUncheckedExtrinsic::decode(&mut &e[..])).unwrap() } - fn pool(api: &TestPolkadotApi) -> TransactionPool<TestPolkadotApi> { - TransactionPool::new(Default::default(), Arc::new(api.clone())) + fn pool(api: &TestPolkadotApi) -> Pool<ChainApi<TestPolkadotApi>> { + Pool::new(Default::default(), ChainApi { api: Arc::new(api.clone()) }) } #[test] fn id_submission_should_work() { let api = TestPolkadotApi::default(); let pool = pool(&api); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, true)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 209, true)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![(Some(Alice.to_raw_public().into()), 209)]); } @@ -588,9 +408,9 @@ mod tests { fn index_submission_should_work() { let api = TestPolkadotApi::default(); let pool = pool(&api); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, false)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 209, false)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![(Some(Alice.to_raw_public().into()), 209)]); } @@ -598,10 +418,10 @@ mod tests { fn multiple_id_submission_should_work() { let api = TestPolkadotApi::default(); let pool = pool(&api); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, true)).unwrap(); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, true)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 209, true)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 210, true)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![(Some(Alice.to_raw_public().into()), 209), (Some(Alice.to_raw_public().into()), 210)]); } @@ -609,10 +429,10 @@ mod tests { fn multiple_index_submission_should_work() { let api = TestPolkadotApi::default(); let pool = pool(&api); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, false)).unwrap(); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, false)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 209, false)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 210, false)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![(Some(Alice.to_raw_public().into()), 209), (Some(Alice.to_raw_public().into()), 210)]); } @@ -620,9 +440,9 @@ mod tests { fn id_based_early_nonce_should_be_culled() { let api = TestPolkadotApi::default(); let pool = pool(&api); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 208, true)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 208, true)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![]); } @@ -630,9 +450,9 @@ mod tests { fn index_based_early_nonce_should_be_culled() { let api = TestPolkadotApi::default(); let pool = pool(&api); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 208, false)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 208, false)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![]); } @@ -641,12 +461,12 @@ mod tests { let api = TestPolkadotApi::default(); let pool = pool(&api); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, true)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 210, true)).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![]); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, true)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 209, true)).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![(Some(Alice.to_raw_public().into()), 209), (Some(Alice.to_raw_public().into()), 210)]); } @@ -655,12 +475,12 @@ mod tests { let api = TestPolkadotApi::default(); let pool = pool(&api); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, false)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 210, false)).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![]); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, false)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 209, false)).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![(Some(Alice.to_raw_public().into()), 209), (Some(Alice.to_raw_public().into()), 210)]); } @@ -668,16 +488,16 @@ mod tests { fn index_then_id_submission_should_make_progress() { let api = TestPolkadotApi::without_lookup(); let pool = pool(&api); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, false)).unwrap(); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, true)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 209, false)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 210, true)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![]); api.enable_lookup(); - pool.retry_verification(BlockId::number(0)).unwrap(); + pool.retry_verification(&BlockId::number(0), None).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![ (Some(Alice.to_raw_public().into()), 209), (Some(Alice.to_raw_public().into()), 210) @@ -688,15 +508,15 @@ mod tests { fn retrying_verification_might_not_change_anything() { let api = TestPolkadotApi::without_lookup(); let pool = pool(&api); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, false)).unwrap(); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, true)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 209, false)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 210, true)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![]); - pool.retry_verification(BlockId::number(1)).unwrap(); + pool.retry_verification(&BlockId::number(1), None).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![]); } @@ -704,19 +524,19 @@ mod tests { fn id_then_index_submission_should_make_progress() { let api = TestPolkadotApi::without_lookup(); let pool = pool(&api); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, true)).unwrap(); - pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, false)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 209, true)).unwrap(); + pool.submit_one(&BlockId::number(0), uxt(Alice, 210, false)).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![ (Some(Alice.to_raw_public().into()), 209) ]); // when api.enable_lookup(); - pool.retry_verification(BlockId::number(0)).unwrap(); + pool.retry_verification(&BlockId::number(0), None).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(0), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![ (Some(Alice.to_raw_public().into()), 209), (Some(Alice.to_raw_public().into()), 210) @@ -728,10 +548,10 @@ mod tests { let api = TestPolkadotApi::default(); let pool = pool(&api); let block = BlockId::number(0); - pool.import_unchecked_extrinsic(block, uxt(Alice, 209, false)).unwrap(); - let hash = *pool.import_unchecked_extrinsic(block, uxt(Alice, 210, false)).unwrap().hash(); + pool.submit_one(&block, uxt(Alice, 209, false)).unwrap(); + let hash = *pool.submit_one(&block, uxt(Alice, 210, false)).unwrap().verified.hash(); - let pending: Vec<_> = pool.cull_and_get_pending(block, |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&block, |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![ (Some(Alice.to_raw_public().into()), 209), (Some(Alice.to_raw_public().into()), 210) @@ -745,13 +565,13 @@ mod tests { // after this, a re-evaluation of the second's readiness should result in it being thrown // out (or maybe placed in future queue). - let err = pool.reverify_transaction(BlockId::number(1), hash).unwrap_err(); + let err = pool.reverify_transaction(&BlockId::number(1), hash).unwrap_err(); match *err.kind() { ::error::ErrorKind::Msg(ref m) if m == "bad signature in extrinsic" => {}, ref e => assert!(false, "The transaction should be rejected with BadSignature error, got: {:?}", e), } - let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(1), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(&BlockId::number(1), |p| p.map(|a| (a.verified.sender(), a.verified.index())).collect()).unwrap(); assert_eq!(pending, vec![]); }