From 189d0791765d3205690e28333106b49fb1f68bea Mon Sep 17 00:00:00 2001 From: Seun Lanlege Date: Wed, 24 Mar 2021 11:28:26 +0100 Subject: [PATCH] test runner (#7665) --- Cargo.lock | 425 +++++++++++------ Cargo.toml | 2 + bin/node/test-runner-example/Cargo.toml | 40 ++ bin/node/test-runner-example/src/lib.rs | 202 ++++++++ client/executor/src/native_executor.rs | 14 +- frame/babe/src/tests.rs | 1 - test-utils/test-runner/Cargo.toml | 61 +++ test-utils/test-runner/src/host_functions.rs | 70 +++ test-utils/test-runner/src/lib.rs | 312 ++++++++++++ test-utils/test-runner/src/node.rs | 476 +++++++++++++++++++ test-utils/test-runner/src/utils.rs | 56 +++ 11 files changed, 1502 insertions(+), 157 deletions(-) create mode 100644 bin/node/test-runner-example/Cargo.toml create mode 100644 bin/node/test-runner-example/src/lib.rs create mode 100644 test-utils/test-runner/Cargo.toml create mode 100644 test-utils/test-runner/src/host_functions.rs create mode 100644 test-utils/test-runner/src/lib.rs create mode 100644 test-utils/test-runner/src/node.rs create mode 100644 test-utils/test-runner/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 045b2780c4bf6..cd3d3b6608619 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -482,6 +482,16 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bitvec" +version = "0.17.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" +dependencies = [ + "either", + "radium 0.3.0", +] + [[package]] name = "bitvec" version = "0.20.2" @@ -489,7 +499,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f682656975d3a682daff957be4ddeb65d6ad656737cd821f2d00685ae466af1" dependencies = [ "funty", - "radium", + "radium 0.6.2", "tap", "wyz", ] @@ -645,6 +655,12 @@ version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" +[[package]] +name = "byte-slice-cast" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" + [[package]] name = "byte-slice-cast" version = "1.0.0" @@ -1618,7 +1634,7 @@ dependencies = [ "futures-timer 3.0.2", "log", "num-traits", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "rand 0.8.3", ] @@ -1664,7 +1680,7 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" name = "fork-tree" version = "3.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", ] [[package]] @@ -1686,7 +1702,7 @@ dependencies = [ "hex-literal", "linregress", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "paste 1.0.4", "serde", "sp-api", @@ -1705,7 +1721,7 @@ dependencies = [ "chrono", "frame-benchmarking", "handlebars", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sc-cli", "sc-client-db", "sc-executor", @@ -1725,7 +1741,7 @@ version = "3.0.0" dependencies = [ "frame-support", "frame-system", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-arithmetic", "sp-npos-elections", "sp-runtime", @@ -1742,7 +1758,7 @@ dependencies = [ "pallet-balances", "pallet-indices", "pallet-transaction-payment", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -1756,7 +1772,7 @@ dependencies = [ name = "frame-metadata" version = "13.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-std", @@ -1773,7 +1789,7 @@ dependencies = [ "impl-trait-for-tuples", "log", "once_cell", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-util-mem", "paste 1.0.4", "pretty_assertions", @@ -1828,7 +1844,7 @@ dependencies = [ "frame-metadata", "frame-support", "frame-system", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "pretty_assertions", "rustversion", "serde", @@ -1849,7 +1865,7 @@ dependencies = [ "frame-support", "impl-trait-for-tuples", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-externalities", @@ -1867,7 +1883,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -1879,7 +1895,7 @@ dependencies = [ name = "frame-system-rpc-runtime-api" version = "3.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-api", ] @@ -1888,7 +1904,7 @@ name = "frame-try-runtime" version = "0.9.0" dependencies = [ "frame-support", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-api", "sp-runtime", "sp-std", @@ -2599,7 +2615,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df170efa359aebdd5cb7fe78edcc67107748e4737bdca8a8fb40d15ea7a877ed" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", ] [[package]] @@ -4004,7 +4020,7 @@ dependencies = [ "pallet-staking", "pallet-timestamp", "pallet-transaction-payment", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "platforms", "rand 0.7.3", @@ -4076,7 +4092,7 @@ dependencies = [ "pallet-timestamp", "pallet-transaction-payment", "pallet-treasury", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sc-executor", "sp-application-crypto", "sp-consensus-babe", @@ -4098,7 +4114,7 @@ version = "0.8.0" dependencies = [ "derive_more", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sc-cli", "sc-client-api", "sc-service", @@ -4113,7 +4129,7 @@ name = "node-primitives" version = "2.0.0" dependencies = [ "frame-system", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "pretty_assertions", "sp-application-crypto", "sp-core", @@ -4221,7 +4237,7 @@ dependencies = [ "pallet-treasury", "pallet-utility", "pallet-vesting", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-api", "sp-authority-discovery", @@ -4299,7 +4315,7 @@ dependencies = [ "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-api", "sp-block-builder", @@ -4338,7 +4354,7 @@ dependencies = [ "pallet-timestamp", "pallet-transaction-payment", "pallet-treasury", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sc-block-builder", "sc-cli", "sc-client-api", @@ -4519,7 +4535,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -4534,7 +4550,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -4551,7 +4567,7 @@ dependencies = [ "lazy_static", "pallet-session", "pallet-timestamp", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "serde", "sp-application-crypto", @@ -4569,7 +4585,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-session", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-application-crypto", "sp-authority-discovery", @@ -4587,7 +4603,7 @@ dependencies = [ "frame-support", "frame-system", "impl-trait-for-tuples", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-authorship", "sp-core", @@ -4613,7 +4629,7 @@ dependencies = [ "pallet-staking", "pallet-staking-reward-curve", "pallet-timestamp", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-application-crypto", "sp-consensus-babe", @@ -4635,7 +4651,7 @@ dependencies = [ "frame-system", "log", "pallet-transaction-payment", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -4652,7 +4668,7 @@ dependencies = [ "frame-system", "pallet-balances", "pallet-treasury", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -4671,7 +4687,7 @@ dependencies = [ "hex-literal", "log", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -4694,7 +4710,7 @@ dependencies = [ "pallet-contracts-proc-macro", "pallet-randomness-collective-flip", "pallet-timestamp", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-wasm 0.41.0", "paste 1.0.4", "pretty_assertions", @@ -4716,7 +4732,7 @@ name = "pallet-contracts-primitives" version = "3.0.0" dependencies = [ "bitflags", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-runtime", "sp-std", ] @@ -4739,7 +4755,7 @@ dependencies = [ "jsonrpc-derive", "pallet-contracts-primitives", "pallet-contracts-rpc-runtime-api", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "serde_json", "sp-api", @@ -4754,7 +4770,7 @@ name = "pallet-contracts-rpc-runtime-api" version = "3.0.0" dependencies = [ "pallet-contracts-primitives", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-api", "sp-runtime", "sp-std", @@ -4770,7 +4786,7 @@ dependencies = [ "hex-literal", "pallet-balances", "pallet-scheduler", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -4791,7 +4807,7 @@ dependencies = [ "hex-literal", "log", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "paste 1.0.4", "rand 0.7.3", @@ -4815,7 +4831,7 @@ dependencies = [ "frame-system", "hex-literal", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -4833,7 +4849,7 @@ dependencies = [ "hex-literal", "log", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -4851,7 +4867,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -4867,7 +4883,7 @@ dependencies = [ "frame-system", "lite-json", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -4882,7 +4898,7 @@ version = "2.0.1" dependencies = [ "frame-support", "frame-system", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -4899,7 +4915,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-arithmetic", "sp-core", @@ -4925,7 +4941,7 @@ dependencies = [ "pallet-staking", "pallet-staking-reward-curve", "pallet-timestamp", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-application-crypto", "sp-core", @@ -4947,7 +4963,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -4965,7 +4981,7 @@ dependencies = [ "log", "pallet-authorship", "pallet-session", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-application-crypto", "sp-core", @@ -4983,7 +4999,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5001,7 +5017,7 @@ dependencies = [ "frame-support-test", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5015,7 +5031,7 @@ version = "3.0.0" dependencies = [ "frame-support", "frame-system", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5034,7 +5050,7 @@ dependencies = [ "frame-system", "hex-literal", "pallet-mmr-primitives", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5050,7 +5066,7 @@ dependencies = [ "frame-system", "hex-literal", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-api", "sp-core", @@ -5066,7 +5082,7 @@ dependencies = [ "jsonrpc-core-client", "jsonrpc-derive", "pallet-mmr-primitives", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "serde_json", "sp-api", @@ -5084,7 +5100,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5099,7 +5115,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5114,7 +5130,7 @@ dependencies = [ "frame-support", "frame-system", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5130,7 +5146,7 @@ dependencies = [ "frame-system", "log", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5156,7 +5172,7 @@ dependencies = [ "pallet-staking", "pallet-staking-reward-curve", "pallet-timestamp", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5174,7 +5190,7 @@ dependencies = [ "frame-system", "pallet-balances", "pallet-utility", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5188,7 +5204,7 @@ version = "3.0.0" dependencies = [ "frame-support", "frame-system", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "safe-mix", "serde", "sp-core", @@ -5205,7 +5221,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5221,7 +5237,7 @@ dependencies = [ "frame-support", "frame-system", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5237,7 +5253,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5254,7 +5270,7 @@ dependencies = [ "impl-trait-for-tuples", "lazy_static", "pallet-timestamp", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-application-crypto", "sp-core", @@ -5279,7 +5295,7 @@ dependencies = [ "pallet-staking", "pallet-staking-reward-curve", "pallet-timestamp", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "rand 0.7.3", "serde", "sp-core", @@ -5297,7 +5313,7 @@ dependencies = [ "frame-support-test", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "rand_chacha 0.2.2", "serde", "sp-core", @@ -5321,7 +5337,7 @@ dependencies = [ "pallet-session", "pallet-staking-reward-curve", "pallet-timestamp", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "paste 1.0.4", "rand_chacha 0.2.2", @@ -5364,7 +5380,7 @@ version = "3.0.0" dependencies = [ "frame-support", "frame-system", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5379,7 +5395,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5395,7 +5411,7 @@ dependencies = [ "frame-system", "impl-trait-for-tuples", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-inherents", @@ -5414,7 +5430,7 @@ dependencies = [ "frame-system", "pallet-balances", "pallet-treasury", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5430,7 +5446,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "serde_json", "smallvec 1.6.1", @@ -5449,7 +5465,7 @@ dependencies = [ "jsonrpc-core-client", "jsonrpc-derive", "pallet-transaction-payment-rpc-runtime-api", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-api", "sp-blockchain", "sp-core", @@ -5462,7 +5478,7 @@ name = "pallet-transaction-payment-rpc-runtime-api" version = "3.0.0" dependencies = [ "pallet-transaction-payment", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-api", "sp-runtime", ] @@ -5476,7 +5492,7 @@ dependencies = [ "frame-system", "impl-trait-for-tuples", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5493,7 +5509,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5511,7 +5527,7 @@ dependencies = [ "frame-system", "hex-literal", "pallet-balances", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -5555,6 +5571,18 @@ dependencies = [ "url 2.2.1", ] +[[package]] +name = "parity-scale-codec" +version = "1.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b26b16c7687c3075982af47719e481815df30bc544f7a6690763a25ca16e9d" +dependencies = [ + "arrayvec 0.5.2", + "bitvec 0.17.4", + "byte-slice-cast 0.3.5", + "serde", +] + [[package]] name = "parity-scale-codec" version = "2.0.1" @@ -5562,8 +5590,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cd3dab59b5cf4bc81069ade0fc470341a1ef3ad5fa73e5a8943bed2ec12b2e8" dependencies = [ "arrayvec 0.5.2", - "bitvec", - "byte-slice-cast", + "bitvec 0.20.2", + "byte-slice-cast 1.0.0", "parity-scale-codec-derive", "serde", ] @@ -6258,6 +6286,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" + [[package]] name = "radium" version = "0.6.2" @@ -6570,7 +6604,7 @@ dependencies = [ "jsonrpsee-proc-macros", "jsonrpsee-types", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-core", "sp-io", "sp-runtime", @@ -6765,7 +6799,7 @@ dependencies = [ "futures-timer 3.0.2", "libp2p", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "prost", "prost-build", "quickcheck", @@ -6792,7 +6826,7 @@ dependencies = [ "futures 0.3.13", "futures-timer 3.0.2", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sc-block-builder", "sc-client-api", @@ -6814,7 +6848,7 @@ dependencies = [ name = "sc-block-builder" version = "0.9.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sc-client-api", "sp-api", "sp-block-builder", @@ -6832,7 +6866,7 @@ name = "sc-chain-spec" version = "3.0.0" dependencies = [ "impl-trait-for-tuples", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sc-chain-spec-derive", "sc-consensus-babe", "sc-consensus-epochs", @@ -6868,7 +6902,7 @@ dependencies = [ "libp2p", "log", "names", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "rand 0.7.3", "regex", "rpassword", @@ -6907,7 +6941,7 @@ dependencies = [ "kvdb-memorydb", "lazy_static", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sc-executor", "sp-api", @@ -6944,7 +6978,7 @@ dependencies = [ "linked-hash-map", "log", "parity-db", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-util-mem", "parking_lot 0.11.1", "quickcheck", @@ -6985,7 +7019,7 @@ dependencies = [ "futures-timer 3.0.2", "getrandom 0.2.2", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sc-block-builder", "sc-client-api", @@ -7030,7 +7064,7 @@ dependencies = [ "num-bigint", "num-rational", "num-traits", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "pdqselect", "rand 0.7.3", @@ -7106,7 +7140,7 @@ name = "sc-consensus-epochs" version = "0.9.0" dependencies = [ "fork-tree", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sc-client-api", "sp-blockchain", @@ -7124,7 +7158,7 @@ dependencies = [ "jsonrpc-core-client", "jsonrpc-derive", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sc-basic-authorship", "sc-client-api", @@ -7159,7 +7193,7 @@ dependencies = [ "futures 0.3.13", "futures-timer 3.0.2", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sc-client-api", "sp-api", @@ -7181,7 +7215,7 @@ dependencies = [ "futures 0.3.13", "futures-timer 3.0.2", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sc-client-api", "sc-telemetry", @@ -7224,7 +7258,7 @@ dependencies = [ "lazy_static", "libsecp256k1", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-wasm 0.41.0", "parking_lot 0.11.1", "paste 1.0.4", @@ -7259,7 +7293,7 @@ name = "sc-executor-common" version = "0.9.0" dependencies = [ "derive_more", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-wasm 0.41.0", "sp-allocator", "sp-core", @@ -7274,7 +7308,7 @@ name = "sc-executor-wasmi" version = "0.9.0" dependencies = [ "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sc-executor-common", "sp-allocator", "sp-core", @@ -7289,7 +7323,7 @@ version = "0.9.0" dependencies = [ "assert_matches", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-wasm 0.41.0", "pwasm-utils 0.14.0", "sc-executor-common", @@ -7314,7 +7348,7 @@ dependencies = [ "futures-timer 3.0.2", "linked-hash-map", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "pin-project 1.0.5", "rand 0.7.3", @@ -7361,7 +7395,7 @@ dependencies = [ "jsonrpc-pubsub", "lazy_static", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sc-block-builder", "sc-client-api", "sc-finality-grandpa", @@ -7387,7 +7421,7 @@ dependencies = [ "futures 0.3.13", "log", "num-traits", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "prost", "rand 0.8.3", @@ -7447,7 +7481,7 @@ version = "3.0.0" dependencies = [ "hash-db", "lazy_static", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sc-client-api", "sc-executor", @@ -7486,7 +7520,7 @@ dependencies = [ "log", "lru", "nohash-hasher", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "pin-project 1.0.5", "prost", @@ -7580,7 +7614,7 @@ dependencies = [ "lazy_static", "log", "num_cpus", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "rand 0.7.3", "sc-block-builder", @@ -7635,7 +7669,7 @@ dependencies = [ "jsonrpc-pubsub", "lazy_static", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sc-block-builder", "sc-cli", @@ -7676,7 +7710,7 @@ dependencies = [ "jsonrpc-derive", "jsonrpc-pubsub", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "serde", "serde_json", @@ -7734,7 +7768,7 @@ dependencies = [ "jsonrpc-pubsub", "lazy_static", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-util-mem", "parking_lot 0.11.1", "pin-project 1.0.5", @@ -7797,7 +7831,7 @@ dependencies = [ "futures 0.3.13", "hex-literal", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sc-block-builder", "sc-client-api", @@ -7829,7 +7863,7 @@ name = "sc-state-db" version = "0.9.0" dependencies = [ "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-util-mem", "parity-util-mem-derive", "parking_lot 0.11.1", @@ -7922,7 +7956,7 @@ dependencies = [ "futures 0.3.13", "linked-hash-map", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-util-mem", "parking_lot 0.11.1", "retain_mut", @@ -7947,7 +7981,7 @@ dependencies = [ "hex", "intervalier", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-util-mem", "parking_lot 0.11.1", "sc-block-builder", @@ -8365,7 +8399,7 @@ version = "3.0.0" dependencies = [ "hash-db", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-api-proc-macro", "sp-core", "sp-runtime", @@ -8393,7 +8427,7 @@ version = "2.0.1" dependencies = [ "criterion", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "rustversion", "sc-block-builder", "sp-api", @@ -8412,7 +8446,7 @@ dependencies = [ name = "sp-application-crypto" version = "3.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-core", "sp-io", @@ -8438,7 +8472,7 @@ dependencies = [ "criterion", "integer-sqrt", "num-traits", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "primitive-types", "rand 0.7.3", "serde", @@ -8462,7 +8496,7 @@ dependencies = [ name = "sp-authority-discovery" version = "3.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-api", "sp-application-crypto", "sp-runtime", @@ -8473,7 +8507,7 @@ dependencies = [ name = "sp-authorship" version = "3.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-inherents", "sp-runtime", "sp-std", @@ -8483,7 +8517,7 @@ dependencies = [ name = "sp-block-builder" version = "3.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-api", "sp-inherents", "sp-runtime", @@ -8497,7 +8531,7 @@ dependencies = [ "futures 0.3.13", "log", "lru", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sp-api", "sp-consensus", @@ -8523,7 +8557,7 @@ dependencies = [ "futures-timer 3.0.2", "libp2p", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "serde", "sp-api", @@ -8545,7 +8579,7 @@ dependencies = [ name = "sp-consensus-aura" version = "0.9.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-api", "sp-application-crypto", "sp-consensus", @@ -8561,7 +8595,7 @@ name = "sp-consensus-babe" version = "0.9.0" dependencies = [ "merlin", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-api", "sp-application-crypto", @@ -8580,7 +8614,7 @@ dependencies = [ name = "sp-consensus-pow" version = "0.9.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-api", "sp-core", "sp-runtime", @@ -8591,7 +8625,7 @@ dependencies = [ name = "sp-consensus-slots" version = "0.9.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-arithmetic", "sp-runtime", ] @@ -8600,7 +8634,7 @@ dependencies = [ name = "sp-consensus-vrf" version = "0.9.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "schnorrkel", "sp-core", "sp-runtime", @@ -8628,7 +8662,7 @@ dependencies = [ "log", "merlin", "num-traits", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-util-mem", "parking_lot 0.11.1", "pretty_assertions", @@ -8678,7 +8712,7 @@ name = "sp-externalities" version = "0.9.0" dependencies = [ "environmental", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-std", "sp-storage", ] @@ -8689,7 +8723,7 @@ version = "3.0.0" dependencies = [ "finality-grandpa", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-api", "sp-application-crypto", @@ -8703,7 +8737,7 @@ dependencies = [ name = "sp-inherents" version = "3.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sp-core", "sp-std", @@ -8718,7 +8752,7 @@ dependencies = [ "hash-db", "libsecp256k1", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sp-core", "sp-externalities", @@ -8751,7 +8785,7 @@ dependencies = [ "derive_more", "futures 0.3.13", "merlin", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "rand 0.7.3", "rand_chacha 0.2.2", @@ -8765,7 +8799,7 @@ dependencies = [ name = "sp-npos-elections" version = "3.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "rand 0.7.3", "serde", "sp-arithmetic", @@ -8791,7 +8825,7 @@ name = "sp-npos-elections-fuzzer" version = "2.0.0-alpha.5" dependencies = [ "honggfuzz", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "rand 0.7.3", "sp-arithmetic", "sp-npos-elections", @@ -8834,7 +8868,7 @@ dependencies = [ "hash256-std-hasher", "impl-trait-for-tuples", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-util-mem", "paste 1.0.4", "rand 0.7.3", @@ -8856,7 +8890,7 @@ name = "sp-runtime-interface" version = "3.0.0" dependencies = [ "impl-trait-for-tuples", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "primitive-types", "rustversion", "sp-core", @@ -8927,7 +8961,7 @@ name = "sp-sandbox" version = "0.9.0" dependencies = [ "assert_matches", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-core", "sp-io", "sp-std", @@ -8948,7 +8982,7 @@ dependencies = [ name = "sp-session" version = "3.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-api", "sp-core", "sp-runtime", @@ -8960,7 +8994,7 @@ dependencies = [ name = "sp-staking" version = "3.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-runtime", "sp-std", ] @@ -8973,7 +9007,7 @@ dependencies = [ "hex-literal", "log", "num-traits", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "pretty_assertions", "rand 0.7.3", @@ -8998,7 +9032,7 @@ name = "sp-storage" version = "3.0.0" dependencies = [ "impl-serde", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "ref-cast", "serde", "sp-debug-derive", @@ -9010,7 +9044,7 @@ name = "sp-tasks" version = "3.0.0" dependencies = [ "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-core", "sp-externalities", "sp-io", @@ -9022,7 +9056,7 @@ dependencies = [ name = "sp-test-primitives" version = "2.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-util-mem", "serde", "sp-application-crypto", @@ -9034,7 +9068,7 @@ dependencies = [ name = "sp-timestamp" version = "3.0.0" dependencies = [ - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-api", "sp-inherents", "sp-runtime", @@ -9047,7 +9081,7 @@ name = "sp-tracing" version = "3.0.0" dependencies = [ "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-std", "tracing", "tracing-core", @@ -9061,7 +9095,7 @@ dependencies = [ "derive_more", "futures 0.3.13", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-api", "sp-blockchain", @@ -9077,7 +9111,7 @@ dependencies = [ "hash-db", "hex-literal", "memory-db", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-core", "sp-runtime", "sp-std", @@ -9103,7 +9137,7 @@ name = "sp-version" version = "3.0.0" dependencies = [ "impl-serde", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "serde", "sp-runtime", "sp-std", @@ -9114,7 +9148,7 @@ name = "sp-wasm-interface" version = "3.0.0" dependencies = [ "impl-trait-for-tuples", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sp-std", "wasmi", ] @@ -9289,7 +9323,7 @@ dependencies = [ "futures 0.3.13", "jsonrpc-client-transports", "jsonrpc-core", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sc-rpc-api", "serde", "sp-storage", @@ -9306,7 +9340,7 @@ dependencies = [ "jsonrpc-core-client", "jsonrpc-derive", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sc-client-api", "sc-rpc-api", "sc-transaction-pool", @@ -9342,7 +9376,7 @@ dependencies = [ "futures 0.3.13", "hash-db", "hex", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sc-client-api", "sc-client-db", "sc-consensus", @@ -9373,7 +9407,7 @@ dependencies = [ "memory-db", "pallet-babe", "pallet-timestamp", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parity-util-mem", "sc-block-builder", "sc-executor", @@ -9409,7 +9443,7 @@ name = "substrate-test-runtime-client" version = "2.0.0" dependencies = [ "futures 0.3.13", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "sc-block-builder", "sc-client-api", "sc-consensus", @@ -9430,7 +9464,7 @@ version = "2.0.0" dependencies = [ "derive_more", "futures 0.3.13", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "parking_lot 0.11.1", "sc-transaction-graph", "sp-blockchain", @@ -9558,6 +9592,88 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "test-runner" +version = "0.9.0" +dependencies = [ + "env_logger 0.7.1", + "frame-system", + "futures 0.1.31", + "futures 0.3.13", + "jsonrpc-core", + "libp2p", + "log", + "node-cli", + "parity-scale-codec 1.3.7", + "rand 0.7.3", + "sc-basic-authorship", + "sc-cli", + "sc-client-api", + "sc-consensus-babe", + "sc-consensus-manual-seal", + "sc-executor", + "sc-finality-grandpa", + "sc-informant", + "sc-network", + "sc-rpc", + "sc-rpc-server", + "sc-service", + "sc-transaction-graph", + "sc-transaction-pool", + "sp-api", + "sp-block-builder", + "sp-blockchain", + "sp-consensus", + "sp-consensus-babe", + "sp-core", + "sp-externalities", + "sp-inherents", + "sp-io", + "sp-keyring", + "sp-keystore", + "sp-offchain", + "sp-runtime", + "sp-runtime-interface", + "sp-session", + "sp-state-machine", + "sp-transaction-pool", + "sp-wasm-interface", + "tokio 0.2.25", +] + +[[package]] +name = "test-runner-example" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "node-cli", + "node-primitives", + "node-runtime", + "pallet-balances", + "pallet-sudo", + "pallet-transaction-payment", + "rand 0.8.3", + "sc-client-api", + "sc-consensus", + "sc-consensus-babe", + "sc-consensus-manual-seal", + "sc-executor", + "sc-finality-grandpa", + "sc-informant", + "sc-network", + "sc-service", + "sp-api", + "sp-consensus-babe", + "sp-inherents", + "sp-keyring", + "sp-keystore", + "sp-runtime", + "test-runner", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -9706,6 +9822,7 @@ dependencies = [ "libc", "memchr", "mio", + "mio-named-pipes", "mio-uds", "num_cpus", "pin-project-lite 0.1.12", @@ -10060,7 +10177,7 @@ dependencies = [ "hash-db", "keccak-hasher", "memory-db", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "trie-db", "trie-root", "trie-standardmap", @@ -10110,7 +10227,7 @@ version = "0.9.0" dependencies = [ "frame-try-runtime", "log", - "parity-scale-codec", + "parity-scale-codec 2.0.1", "remote-externalities", "sc-cli", "sc-client-api", diff --git a/Cargo.toml b/Cargo.toml index 9675070a516fb..57052a8d38e05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "bin/node/bench", "bin/node/browser-testing", "bin/node/cli", + "bin/node/test-runner-example", "bin/node/executor", "bin/node/primitives", "bin/node/rpc", @@ -184,6 +185,7 @@ members = [ "test-utils/runtime", "test-utils/runtime/client", "test-utils/runtime/transaction-pool", + "test-utils/test-runner", "test-utils/test-crate", "utils/browser", "utils/build-script-utils", diff --git a/bin/node/test-runner-example/Cargo.toml b/bin/node/test-runner-example/Cargo.toml new file mode 100644 index 0000000000000..f94575e8e621b --- /dev/null +++ b/bin/node/test-runner-example/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "test-runner-example" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +publish = false + +[dependencies] +test-runner = { path = "../../../test-utils/test-runner", version = "0.9.0" } + +frame-system = { version = "3.0.0", path = "../../../frame/system" } +frame-support = { path = "../../../frame/support", version = "3.0.0" } +frame-benchmarking = { path = "../../../frame/benchmarking", version = "3.0.0" } +pallet-balances = { path = "../../../frame/balances", version = "3.0.0" } +pallet-sudo = { path = "../../../frame/sudo", version = "3.0.0" } +pallet-transaction-payment = { version = "3.0.0", path = "../../../frame/transaction-payment" } + +node-runtime = { path = "../runtime", version = "2.0.1" } +node-primitives = { version = "2.0.0", path = "../primitives" } +node-cli = { path = "../cli", version = "2.0.0" } + +grandpa = { version = "0.9.0", package = "sc-finality-grandpa", path = "../../../client/finality-grandpa" } +sp-consensus-babe = { version = "0.9.0", path = "../../../primitives/consensus/babe" } +sc-consensus-babe = { version = "0.9.0", path = "../../../client/consensus/babe" } +sc-consensus-manual-seal = { version = "0.9.0", path = "../../../client/consensus/manual-seal" } +sc-service = { version = "0.9.0", default-features = false, path = "../../../client/service" } +sc-executor = { version = "0.9.0", path = "../../../client/executor" } +sc-client-api = { version = "3.0.0", path = "../../../client/api" } +sc-network = { version = "0.9.0", path = "../../../client/network" } +sc-informant = { version = "0.9.0", path = "../../../client/informant" } +sc-consensus = { version = "0.9.0", path = "../../../client/consensus/common" } + +sp-runtime = { path = "../../../primitives/runtime", version = "3.0.0" } +sp-keyring = { version = "3.0.0", path = "../../../primitives/keyring" } +sp-api = { version = "3.0.0", path = "../../../primitives/api" } +sp-inherents = { version = "3.0.0", path = "../../../primitives/inherents" } +sp-keystore = { version = "0.9.0", path = "../../../primitives/keystore" } + +rand = "0.8.3" +log = "0.4.14" diff --git a/bin/node/test-runner-example/src/lib.rs b/bin/node/test-runner-example/src/lib.rs new file mode 100644 index 0000000000000..22cfffa7f23a7 --- /dev/null +++ b/bin/node/test-runner-example/src/lib.rs @@ -0,0 +1,202 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Basic example of end to end runtime tests. + +use test_runner::{Node, ChainInfo, SignatureVerificationOverride}; +use grandpa::GrandpaBlockImport; +use sc_service::{TFullBackend, TFullClient, Configuration, TaskManager, new_full_parts}; +use std::sync::Arc; +use sp_inherents::InherentDataProviders; +use sc_consensus_babe::BabeBlockImport; +use sp_keystore::SyncCryptoStorePtr; +use sp_keyring::sr25519::Keyring::Alice; +use sp_consensus_babe::AuthorityId; +use sc_consensus_manual_seal::{ConsensusDataProvider, consensus::babe::BabeConsensusDataProvider}; +use sp_runtime::{traits::IdentifyAccount, MultiSigner, generic::Era}; + +type BlockImport = BabeBlockImport>; + +sc_executor::native_executor_instance!( + pub Executor, + node_runtime::api::dispatch, + node_runtime::native_version, + ( + frame_benchmarking::benchmarking::HostFunctions, + SignatureVerificationOverride, + ) +); + +/// ChainInfo implementation. +struct NodeTemplateChainInfo; + +impl ChainInfo for NodeTemplateChainInfo { + type Block = node_primitives::Block; + type Executor = Executor; + type Runtime = node_runtime::Runtime; + type RuntimeApi = node_runtime::RuntimeApi; + type SelectChain = sc_consensus::LongestChain, Self::Block>; + type BlockImport = BlockImport< + Self::Block, + TFullBackend, + TFullClient, + Self::SelectChain, + >; + type SignedExtras = node_runtime::SignedExtra; + + fn signed_extras(from: ::AccountId) -> Self::SignedExtras { + ( + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckMortality::::from(Era::Immortal), + frame_system::CheckNonce::::from(frame_system::Pallet::::account_nonce(from)), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + ) + } + + fn create_client_parts( + config: &Configuration, + ) -> Result< + ( + Arc>, + Arc>, + SyncCryptoStorePtr, + TaskManager, + InherentDataProviders, + Option< + Box< + dyn ConsensusDataProvider< + Self::Block, + Transaction = sp_api::TransactionFor< + TFullClient, + Self::Block, + >, + >, + >, + >, + Self::SelectChain, + Self::BlockImport, + ), + sc_service::Error, + > { + let (client, backend, keystore, task_manager) = + new_full_parts::(config, None)?; + let client = Arc::new(client); + + let inherent_providers = InherentDataProviders::new(); + let select_chain = sc_consensus::LongestChain::new(backend.clone()); + + let (grandpa_block_import, ..) = + grandpa::block_import( + client.clone(), + &(client.clone() as Arc<_>), + select_chain.clone(), + None + )?; + + let (block_import, babe_link) = sc_consensus_babe::block_import( + sc_consensus_babe::Config::get_or_compute(&*client)?, + grandpa_block_import, + client.clone(), + )?; + + let consensus_data_provider = BabeConsensusDataProvider::new( + client.clone(), + keystore.sync_keystore(), + &inherent_providers, + babe_link.epoch_changes().clone(), + vec![(AuthorityId::from(Alice.public()), 1000)], + ) + .expect("failed to create ConsensusDataProvider"); + + Ok(( + client, + backend, + keystore.sync_keystore(), + task_manager, + inherent_providers, + Some(Box::new(consensus_data_provider)), + select_chain, + block_import, + )) + } + + fn dispatch_with_root(call: ::Call, node: &mut Node) { + let alice = MultiSigner::from(Alice.public()).into_account(); + let call = pallet_sudo::Call::sudo(Box::new(call)); + node.submit_extrinsic(call, alice); + node.seal_blocks(1); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use test_runner::NodeConfig; + use log::LevelFilter; + use sc_client_api::execution_extensions::ExecutionStrategies; + use node_cli::chain_spec::development_config; + + #[test] + fn test_runner() { + let config = NodeConfig { + execution_strategies: ExecutionStrategies { + syncing: sc_client_api::ExecutionStrategy::AlwaysWasm, + importing: sc_client_api::ExecutionStrategy::AlwaysWasm, + block_construction: sc_client_api::ExecutionStrategy::AlwaysWasm, + offchain_worker: sc_client_api::ExecutionStrategy::AlwaysWasm, + other: sc_client_api::ExecutionStrategy::AlwaysWasm, + }, + chain_spec: Box::new(development_config()), + log_targets: vec![ + ("yamux", LevelFilter::Off), + ("multistream_select", LevelFilter::Off), + ("libp2p", LevelFilter::Off), + ("jsonrpc_client_transports", LevelFilter::Off), + ("sc_network", LevelFilter::Off), + ("tokio_reactor", LevelFilter::Off), + ("parity-db", LevelFilter::Off), + ("sub-libp2p", LevelFilter::Off), + ("sync", LevelFilter::Off), + ("peerset", LevelFilter::Off), + ("ws", LevelFilter::Off), + ("sc_network", LevelFilter::Off), + ("sc_service", LevelFilter::Off), + ("sc_basic_authorship", LevelFilter::Off), + ("telemetry-logger", LevelFilter::Off), + ("sc_peerset", LevelFilter::Off), + ("rpc", LevelFilter::Off), + ("runtime", LevelFilter::Trace), + ("babe", LevelFilter::Debug) + ], + }; + let mut node = Node::::new(config).unwrap(); + // seals blocks + node.seal_blocks(1); + // submit extrinsics + let alice = MultiSigner::from(Alice.public()).into_account(); + node.submit_extrinsic(frame_system::Call::remark((b"hello world").to_vec()), alice); + + // look ma, I can read state. + let _events = node.with_state(|| frame_system::Pallet::::events()); + // get access to the underlying client. + let _client = node.client(); + } +} diff --git a/client/executor/src/native_executor.rs b/client/executor/src/native_executor.rs index 42a7950593ccf..6df651e1b776c 100644 --- a/client/executor/src/native_executor.rs +++ b/client/executor/src/native_executor.rs @@ -274,10 +274,20 @@ impl NativeExecutor { default_heap_pages: Option, max_runtime_instances: usize, ) -> Self { - let mut host_functions = D::ExtendHostFunctions::host_functions(); + let extended = D::ExtendHostFunctions::host_functions(); + let mut host_functions = sp_io::SubstrateHostFunctions::host_functions() + .into_iter() + // filter out any host function overrides provided. + .filter(|host_fn| { + extended.iter() + .find(|ext_host_fn| host_fn.name() == ext_host_fn.name()) + .is_none() + }) + .collect::>(); + // Add the custom host functions provided by the user. - host_functions.extend(sp_io::SubstrateHostFunctions::host_functions()); + host_functions.extend(extended); let wasm_executor = WasmExecutor::new( fallback_method, default_heap_pages, diff --git a/frame/babe/src/tests.rs b/frame/babe/src/tests.rs index e9966ddb75dd0..6aa80e9697339 100644 --- a/frame/babe/src/tests.rs +++ b/frame/babe/src/tests.rs @@ -356,7 +356,6 @@ fn can_fetch_current_and_next_epoch_data() { Babe::current_epoch().authorities, Babe::next_epoch().authorities, ); - // 1 era = 3 epochs // 1 epoch = 3 slots // Eras start from 0. diff --git a/test-utils/test-runner/Cargo.toml b/test-utils/test-runner/Cargo.toml new file mode 100644 index 0000000000000..cac699854f828 --- /dev/null +++ b/test-utils/test-runner/Cargo.toml @@ -0,0 +1,61 @@ +[package] +name = "test-runner" +version = "0.9.0" +authors = ["Parity Technologies "] +edition = "2018" +publish = false + +[dependencies] +# client deps +sc-executor = { version = "0.9.0", path = "../../client/executor" } +sc-service = { version = "0.9.0", path = "../../client/service" } +sc-informant = { version = "0.9.0", path = "../../client/informant" } +sc-network = { version = "0.9.0", path = "../../client/network" } +sc-cli = { version = "0.9.0", path = "../../client/cli" } +sc-basic-authorship = { version = "0.9.0", path = "../../client/basic-authorship" } +sc-rpc = { version = "3.0.0", path = "../../client/rpc" } +sc-transaction-pool = { version = "3.0.0", path = "../../client/transaction-pool" } +sc-transaction-graph = { version = "3.0.0", path = "../../client/transaction-pool/graph" } +sc-client-api = { version = "3.0.0", path = "../../client/api" } +sc-rpc-server = { version = "3.0.0", path = "../../client/rpc-servers" } +manual-seal = { package = "sc-consensus-manual-seal", version = "0.9.0", path = "../../client/consensus/manual-seal" } + +# primitive deps +sp-core = { version = "3.0.0", path = "../../primitives/core" } +sp-blockchain = { version = "3.0.0", path = "../../primitives/blockchain" } +sp-block-builder = { version = "3.0.0", path = "../../primitives/block-builder" } +sp-api = { version = "3.0.0", path = "../../primitives/api" } +sp-io = { version = "3.0.0", path = "../../primitives/io" } +sp-transaction-pool = { version = "3.0.0", path = "../../primitives/transaction-pool" } +sp-consensus = { version = "0.9.0", path = "../../primitives/consensus/common" } +sp-keystore = { version = "0.9.0", path = "../../primitives/keystore" } +sp-runtime = { version = "3.0.0", path = "../../primitives/runtime" } +sp-session = { version = "3.0.0", path = "../../primitives/session" } +sp-offchain = { version = "3.0.0", path = "../../primitives/offchain" } +sp-inherents = { version = "3.0.0", path = "../../primitives/inherents" } +sp-keyring = { version = "3.0.0", path = "../../primitives/keyring" } + +sp-externalities = { version = "0.9.0", path = "../../primitives/externalities" } +sp-state-machine = { version = "0.9.0", path = "../../primitives/state-machine" } +sp-wasm-interface = { version = "3.0.0", path = "../../primitives/wasm-interface" } +sp-runtime-interface = { version = "3.0.0", path = "../../primitives/runtime-interface" } + +# pallets +frame-system = { version = "3.0.0", path = "../../frame/system" } + +parity-scale-codec = "1.3.1" +env_logger = "0.7.1" +log = "0.4.8" +futures01 = { package = "futures", version = "0.1.29" } +futures = { package = "futures", version = "0.3", features = ["compat"] } +rand = "0.7" +tokio = { version = "0.2", features = ["full"] } +libp2p = "0.35.1" + +# Calling RPC +jsonrpc-core = "15.1" +[dev-dependencies] +sc-finality-grandpa = { version = "0.9.0", path = "../../client/finality-grandpa" } +sc-consensus-babe = { version = "0.9.0", path = "../../client/consensus/babe" } +sp-consensus-babe = { version = "0.9.0", path = "../../primitives/consensus/babe" } +node-cli = { version = "2.0.0", path = "../../bin/node/cli" } \ No newline at end of file diff --git a/test-utils/test-runner/src/host_functions.rs b/test-utils/test-runner/src/host_functions.rs new file mode 100644 index 0000000000000..ca8790683e6c4 --- /dev/null +++ b/test-utils/test-runner/src/host_functions.rs @@ -0,0 +1,70 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#[macro_export] +macro_rules! override_host_functions { + ($($fn_name:expr, $name:ident,)*) => {{ + let mut host_functions = vec![]; + $( + struct $name; + impl sp_wasm_interface::Function for $name { + fn name(&self) -> &str { + &$fn_name + } + + fn signature(&self) -> sp_wasm_interface::Signature { + sp_wasm_interface::Signature { + args: std::borrow::Cow::Owned(vec![ + sp_wasm_interface::ValueType::I32, + sp_wasm_interface::ValueType::I64, + sp_wasm_interface::ValueType::I32, + ]), + return_value: Some(sp_wasm_interface::ValueType::I32), + } + } + + fn execute( + &self, + context: &mut dyn sp_wasm_interface::FunctionContext, + _args: &mut dyn Iterator, + ) -> Result, String> { + ::into_ffi_value(true, context) + .map(sp_wasm_interface::IntoValue::into_value) + .map(Some) + } + } + host_functions.push(&$name as &'static dyn sp_wasm_interface::Function); + )* + host_functions + }}; +} + +/// Provides host functions that overrides runtime signature verification +/// to always return true. +pub struct SignatureVerificationOverride; + +impl sp_wasm_interface::HostFunctions for SignatureVerificationOverride { + fn host_functions() -> Vec<&'static dyn sp_wasm_interface::Function> { + override_host_functions!( + "ext_crypto_ecdsa_verify_version_1", EcdsaVerify, + "ext_crypto_ed25519_verify_version_1", Ed25519Verify, + "ext_crypto_sr25519_verify_version_1", Sr25519Verify, + "ext_crypto_sr25519_verify_version_2", Sr25519VerifyV2, + ) + } +} diff --git a/test-utils/test-runner/src/lib.rs b/test-utils/test-runner/src/lib.rs new file mode 100644 index 0000000000000..87ec4336d9523 --- /dev/null +++ b/test-utils/test-runner/src/lib.rs @@ -0,0 +1,312 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Test runner +//! # Substrate Test Runner +//! +//! Allows you to test +//!
+//! +//! - Migrations +//! - Runtime Upgrades +//! - Pallets and general runtime functionality. +//! +//! This works by running a full node with a Manual Seal-BABE™ hybrid consensus for block authoring. +//! +//!

Note

+//! The running node has no signature verification, which allows us author extrinsics for any account on chain. +//!
+//!
+//! +//!

How do I Use this?

+//! +//! +//! ```rust,ignore +//! use test_runner::{Node, ChainInfo, SignatureVerificationOverride, base_path, NodeConfig}; +//! use sc_finality_grandpa::GrandpaBlockImport; +//! use sc_service::{ +//! TFullBackend, TFullClient, Configuration, TaskManager, new_full_parts, BasePath, +//! DatabaseConfig, KeepBlocks, TransactionStorageMode, ChainSpec, Role, +//! config::{NetworkConfiguration, KeystoreConfig}, +//! }; +//! use std::sync::Arc; +//! use sp_inherents::InherentDataProviders; +//! use sc_consensus_babe::BabeBlockImport; +//! use sp_keystore::SyncCryptoStorePtr; +//! use sp_keyring::sr25519::Keyring::{Alice, Bob}; +//! use node_cli::chain_spec::development_config; +//! use sp_consensus_babe::AuthorityId; +//! use manual_seal::{ConsensusDataProvider, consensus::babe::BabeConsensusDataProvider}; +//! use sp_runtime::{traits::IdentifyAccount, MultiSigner, generic::Era}; +//! use sc_executor::WasmExecutionMethod; +//! use sc_network::{multiaddr, config::TransportConfig}; +//! use sc_client_api::execution_extensions::ExecutionStrategies; +//! use sc_informant::OutputFormat; +//! use sp_api::TransactionFor; +//! +//! type BlockImport = BabeBlockImport>; +//! +//! sc_executor::native_executor_instance!( +//! pub Executor, +//! node_runtime::api::dispatch, +//! node_runtime::native_version, +//! SignatureVerificationOverride, +//! ); +//! +//! struct Requirements; +//! +//! impl ChainInfo for Requirements { +//! /// Provide a Block type with an OpaqueExtrinsic +//! type Block = node_primitives::Block; +//! /// Provide an Executor type for the runtime +//! type Executor = Executor; +//! /// Provide the runtime itself +//! type Runtime = node_runtime::Runtime; +//! /// A touch of runtime api +//! type RuntimeApi = node_runtime::RuntimeApi; +//! /// A pinch of SelectChain implementation +//! type SelectChain = sc_consensus::LongestChain, Self::Block>; +//! /// A slice of concrete BlockImport type +//! type BlockImport = BlockImport< +//! Self::Block, +//! TFullBackend, +//! TFullClient, +//! Self::SelectChain, +//! >; +//! /// and a dash of SignedExtensions +//! type SignedExtras = node_runtime::SignedExtra; +//! +//! /// Create your signed extras here. +//! fn signed_extras( +//! from: ::AccountId, +//! ) -> Self::SignedExtension { +//! let nonce = frame_system::Pallet::::account_nonce(from); +//! +//! ( +//! frame_system::CheckSpecVersion::::new(), +//! frame_system::CheckTxVersion::::new(), +//! frame_system::CheckGenesis::::new(), +//! frame_system::CheckMortality::::from(Era::Immortal), +//! frame_system::CheckNonce::::from(nonce), +//! frame_system::CheckWeight::::new(), +//! pallet_transaction_payment::ChargeTransactionPayment::::from(0), +//! ) +//! } +//! +//! /// The function signature tells you all you need to know. ;) +//! fn create_client_parts(config: &Configuration) -> Result< +//! ( +//! Arc>, +//! Arc>, +//! KeyStorePtr, +//! TaskManager, +//! InherentDataProviders, +//! Option, +//! Self::Block +//! >, +//! > +//! >>, +//! Self::SelectChain, +//! Self::BlockImport +//! ), +//! sc_service::Error +//! > { +//! let ( +//! client, +//! backend, +//! keystore, +//! task_manager, +//! ) = new_full_parts::(config)?; +//! let client = Arc::new(client); +//! +//! let inherent_providers = InherentDataProviders::new(); +//! let select_chain = sc_consensus::LongestChain::new(backend.clone()); +//! +//! let (grandpa_block_import, ..) = +//! sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain.clone())?; +//! +//! let (block_import, babe_link) = sc_consensus_babe::block_import( +//! sc_consensus_babe::Config::get_or_compute(&*client)?, +//! grandpa_block_import, +//! client.clone(), +//! )?; +//! +//! let consensus_data_provider = BabeConsensusDataProvider::new( +//! client.clone(), +//! keystore.clone(), +//! &inherent_providers, +//! babe_link.epoch_changes().clone(), +//! vec![(AuthorityId::from(Alice.public()), 1000)] +//! ) +//! .expect("failed to create ConsensusDataProvider"); +//! +//! Ok(( +//! client, +//! backend, +//! keystore, +//! task_manager, +//! inherent_providers, +//! Some(Box::new(consensus_data_provider)), +//! select_chain, +//! block_import +//! )) +//! } +//! +//! fn dispatch_with_root(call: ::Call, node: &mut Node) { +//! let alice = MultiSigner::from(Alice.public()).into_account(); +//! // for chains that support sudo, otherwise, you'd have to use pallet-democracy here. +//! let call = pallet_sudo::Call::sudo(Box::new(call)); +//! node.submit_extrinsic(call, alice); +//! node.seal_blocks(1); +//! } +//! } +//! +//! /// And now for the most basic test +//! +//! #[test] +//! fn simple_balances_test() { +//! // given +//! let config = NodeConfig { +//! execution_strategies: ExecutionStrategies { +//! syncing: sc_client_api::ExecutionStrategy::NativeWhenPossible, +//! importing: sc_client_api::ExecutionStrategy::NativeWhenPossible, +//! block_construction: sc_client_api::ExecutionStrategy::NativeWhenPossible, +//! offchain_worker: sc_client_api::ExecutionStrategy::NativeWhenPossible, +//! other: sc_client_api::ExecutionStrategy::NativeWhenPossible, +//! }, +//! chain_spec: Box::new(development_config()), +//! log_targets: vec![], +//! }; +//! let mut node = Node::::new(config).unwrap(); +//! +//! type Balances = pallet_balances::Pallet; +//! +//! let (alice, bob) = (Alice.pair(), Bob.pair()); +//! let (alice_account_id, bob_acount_id) = ( +//! MultiSigner::from(alice.public()).into_account(), +//! MultiSigner::from(bob.public()).into_account() +//! ); +//! +//! /// the function with_state allows us to read state, pretty cool right? :D +//! let old_balance = node.with_state(|| Balances::free_balance(alice_account_id.clone())); +//! +//! // 70 dots +//! let amount = 70_000_000_000_000; +//! +//! /// Send extrinsic in action. +//! node.submit_extrinsic(BalancesCall::transfer(bob_acount_id.clone(), amount), alice_account_id.clone()); +//! +//! /// Produce blocks in action, Powered by manual-seal™. +//! node.seal_blocks(1); +//! +//! /// we can check the new state :D +//! let new_balance = node.with_state(|| Balances::free_balance(alice_account_id)); +//! +//! /// we can now make assertions on how state has changed. +//! assert_eq!(old_balance + amount, new_balance); +//! } +//! ``` + +use manual_seal::consensus::ConsensusDataProvider; +use sc_executor::NativeExecutionDispatch; +use sc_service::{Configuration, TFullBackend, TFullClient, TaskManager}; +use sp_api::{ConstructRuntimeApi, TransactionFor}; +use sp_consensus::{BlockImport, SelectChain}; +use sp_inherents::InherentDataProviders; +use sp_keystore::SyncCryptoStorePtr; +use sp_runtime::traits::{Block as BlockT, SignedExtension}; +use std::sync::Arc; + +mod node; +mod utils; +mod host_functions; + +pub use host_functions::*; +pub use node::*; + +/// Wrapper trait for concrete type required by this testing framework. +pub trait ChainInfo: Sized { + /// Opaque block type + type Block: BlockT; + + /// Executor type + type Executor: NativeExecutionDispatch + 'static; + + /// Runtime + type Runtime: frame_system::Config; + + /// RuntimeApi + type RuntimeApi: Send + + Sync + + 'static + + ConstructRuntimeApi>; + + /// select chain type. + type SelectChain: SelectChain + 'static; + + /// Block import type. + type BlockImport: Send + + Sync + + Clone + + BlockImport< + Self::Block, + Error = sp_consensus::Error, + Transaction = TransactionFor, Self::Block>, + > + 'static; + + /// The signed extras required by the runtime + type SignedExtras: SignedExtension; + + /// Signed extras, this function is caled in an externalities provided environment. + fn signed_extras(from: ::AccountId) -> Self::SignedExtras; + + /// Attempt to create client parts, including block import, + /// select chain strategy and consensus data provider. + fn create_client_parts( + config: &Configuration, + ) -> Result< + ( + Arc>, + Arc>, + SyncCryptoStorePtr, + TaskManager, + InherentDataProviders, + Option< + Box< + dyn ConsensusDataProvider< + Self::Block, + Transaction = TransactionFor< + TFullClient, + Self::Block, + >, + >, + >, + >, + Self::SelectChain, + Self::BlockImport, + ), + sc_service::Error, + >; + + /// Given a call and a handle to the node, execute the call with root privileges. + fn dispatch_with_root(call: ::Call, node: &mut Node); +} diff --git a/test-utils/test-runner/src/node.rs b/test-utils/test-runner/src/node.rs new file mode 100644 index 0000000000000..6965c6a804dbe --- /dev/null +++ b/test-utils/test-runner/src/node.rs @@ -0,0 +1,476 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use std::sync::Arc; + +use futures::{FutureExt, SinkExt, channel::{mpsc, oneshot}}; +use jsonrpc_core::MetaIoHandler; +use manual_seal::{run_manual_seal, EngineCommand, ManualSealParams}; +use sc_cli::build_runtime; +use sc_client_api::{ + backend::{self, Backend}, CallExecutor, ExecutorProvider, + execution_extensions::ExecutionStrategies, +}; +use sc_service::{ + build_network, spawn_tasks, BuildNetworkParams, SpawnTasksParams, TFullBackend, + TFullCallExecutor, TFullClient, TaskManager, TaskType, ChainSpec, BasePath, + Configuration, DatabaseConfig, KeepBlocks, TransactionStorageMode, config::KeystoreConfig, +}; +use sc_transaction_pool::BasicPool; +use sp_api::{ApiExt, ConstructRuntimeApi, Core, Metadata, OverlayedChanges, StorageTransactionCache}; +use sp_block_builder::BlockBuilder; +use sp_blockchain::HeaderBackend; +use sp_core::ExecutionContext; +use sp_offchain::OffchainWorkerApi; +use sp_runtime::traits::{Block as BlockT, Extrinsic}; +use sp_runtime::{generic::BlockId, transaction_validity::TransactionSource, MultiSignature, MultiAddress}; +use sp_runtime::{generic::UncheckedExtrinsic, traits::NumberFor}; +use sp_session::SessionKeys; +use sp_state_machine::Ext; +use sp_transaction_pool::runtime_api::TaggedTransactionQueue; +use sp_transaction_pool::TransactionPool; + +pub use crate::utils::{logger, base_path}; +use crate::ChainInfo; +use log::LevelFilter; +use sp_keyring::sr25519::Keyring::Alice; +use sc_network::{multiaddr, config::{NetworkConfiguration, TransportConfig, Role}}; +use sc_informant::OutputFormat; +use sc_executor::WasmExecutionMethod; + +/// This holds a reference to a running node on another thread, +/// the node process is dropped when this struct is dropped +/// also holds logs from the process. +pub struct Node { + /// rpc handler for communicating with the node over rpc. + rpc_handler: Arc>, + /// Stream of log lines + log_stream: mpsc::UnboundedReceiver, + /// node tokio runtime + _runtime: tokio::runtime::Runtime, + /// handle to the running node. + _task_manager: Option, + /// client instance + client: Arc>, + /// transaction pool + pool: Arc< + dyn TransactionPool< + Block = T::Block, + Hash = ::Hash, + Error = sc_transaction_pool::error::Error, + InPoolTransaction = sc_transaction_graph::base_pool::Transaction< + ::Hash, + ::Extrinsic, + >, + >, + >, + /// channel to communicate with manual seal on. + manual_seal_command_sink: mpsc::Sender::Hash>>, + /// backend type. + backend: Arc>, + /// Block number at initialization of this Node. + initial_block_number: NumberFor +} + +/// Configuration options for the node. +pub struct NodeConfig { + /// A set of log targets you'd like to enable/disbale + pub log_targets: Vec<(&'static str, LevelFilter)>, + + /// ChainSpec for the runtime + pub chain_spec: Box, + + /// wasm execution strategies. + pub execution_strategies: ExecutionStrategies, +} + +type EventRecord = frame_system::EventRecord<::Event, ::Hash>; + +impl Node { + /// Starts a node with the manual-seal authorship. + pub fn new(node_config: NodeConfig) -> Result + where + >>::RuntimeApi: + Core + + Metadata + + OffchainWorkerApi + + SessionKeys + + TaggedTransactionQueue + + BlockBuilder + + ApiExt as Backend>::State>, + { + let NodeConfig { log_targets, mut chain_spec, execution_strategies } = node_config; + let tokio_runtime = build_runtime().unwrap(); + + // unbounded logs, should be fine, test is shortlived. + let (log_sink, log_stream) = mpsc::unbounded(); + + logger(log_targets, tokio_runtime.handle().clone(), log_sink); + let runtime_handle = tokio_runtime.handle().clone(); + + let task_executor = move |fut, task_type| match task_type { + TaskType::Async => runtime_handle.spawn(fut).map(drop), + TaskType::Blocking => runtime_handle + .spawn_blocking(move || futures::executor::block_on(fut)) + .map(drop), + }; + + let base_path = if let Some(base) = base_path() { + BasePath::new(base) + } else { + BasePath::new_temp_dir().expect("couldn't create a temp dir") + }; + let root_path = base_path.path().to_path_buf().join("chains").join(chain_spec.id()); + + let key_seed = Alice.to_seed(); + let storage = chain_spec + .as_storage_builder() + .build_storage() + .expect("could not build storage"); + + chain_spec.set_storage(storage); + + let mut network_config = NetworkConfiguration::new( + format!("Test Node for: {}", key_seed), + "network/test/0.1", + Default::default(), + None, + ); + let informant_output_format = OutputFormat { enable_color: false }; + + network_config.allow_non_globals_in_dht = true; + + network_config + .listen_addresses + .push(multiaddr::Protocol::Memory(rand::random()).into()); + + network_config.transport = TransportConfig::MemoryOnly; + + let config = Configuration { + impl_name: "test-node".to_string(), + impl_version: "0.1".to_string(), + role: Role::Authority, + task_executor: task_executor.into(), + transaction_pool: Default::default(), + network: network_config, + keystore: KeystoreConfig::Path { + path: root_path.join("key"), + password: None, + }, + database: DatabaseConfig::RocksDb { + path: root_path.join("db"), + cache_size: 128, + }, + state_cache_size: 16777216, + state_cache_child_ratio: None, + chain_spec, + wasm_method: WasmExecutionMethod::Interpreted, + execution_strategies, + rpc_http: None, + rpc_ws: None, + rpc_ipc: None, + rpc_ws_max_connections: None, + rpc_cors: None, + rpc_methods: Default::default(), + prometheus_config: None, + telemetry_endpoints: None, + telemetry_external_transport: None, + default_heap_pages: None, + offchain_worker: Default::default(), + force_authoring: false, + disable_grandpa: false, + dev_key_seed: Some(key_seed), + tracing_targets: None, + tracing_receiver: Default::default(), + max_runtime_instances: 8, + announce_block: true, + base_path: Some(base_path), + wasm_runtime_overrides: None, + informant_output_format, + disable_log_reloading: false, + keystore_remote: None, + keep_blocks: KeepBlocks::All, + state_pruning: Default::default(), + transaction_storage: TransactionStorageMode::BlockBody, + }; + + let ( + client, + backend, + keystore, + mut task_manager, + inherent_data_providers, + consensus_data_provider, + select_chain, + block_import, + ) = T::create_client_parts(&config)?; + + let import_queue = + manual_seal::import_queue(Box::new(block_import.clone()), &task_manager.spawn_essential_handle(), None); + + let transaction_pool = BasicPool::new_full( + config.transaction_pool.clone(), + true.into(), + config.prometheus_registry(), + task_manager.spawn_handle(), + client.clone(), + ); + + let (network, network_status_sinks, system_rpc_tx, network_starter) = { + let params = BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + on_demand: None, + block_announce_validator_builder: None, + }; + build_network(params)? + }; + + sc_service::build_offchain_workers( + &config, + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); + + // Proposer object for block authorship. + let env = sc_basic_authorship::ProposerFactory::new( + task_manager.spawn_handle(), + client.clone(), + transaction_pool.clone(), + config.prometheus_registry(), + None + ); + + // Channel for the rpc handler to communicate with the authorship task. + let (command_sink, commands_stream) = mpsc::channel(10); + + let rpc_handlers = { + let params = SpawnTasksParams { + config, + client: client.clone(), + backend: backend.clone(), + task_manager: &mut task_manager, + keystore, + on_demand: None, + transaction_pool: transaction_pool.clone(), + rpc_extensions_builder: Box::new(move |_, _| jsonrpc_core::IoHandler::default()), + remote_blockchain: None, + network, + network_status_sinks, + system_rpc_tx, + telemetry: None + }; + spawn_tasks(params)? + }; + + // Background authorship future. + let authorship_future = run_manual_seal(ManualSealParams { + block_import, + env, + client: client.clone(), + pool: transaction_pool.pool().clone(), + commands_stream, + select_chain, + consensus_data_provider, + inherent_data_providers, + }); + + // spawn the authorship task as an essential task. + task_manager + .spawn_essential_handle() + .spawn("manual-seal", authorship_future); + + network_starter.start_network(); + let rpc_handler = rpc_handlers.io_handler(); + let initial_number = client.info().best_number; + + Ok(Self { + rpc_handler, + _task_manager: Some(task_manager), + _runtime: tokio_runtime, + client, + pool: transaction_pool, + backend, + log_stream, + manual_seal_command_sink: command_sink, + initial_block_number: initial_number, + }) + } + + /// Returns a reference to the rpc handlers. + pub fn rpc_handler(&self) -> Arc> { + self.rpc_handler.clone() + } + + /// Return a reference to the Client + pub fn client(&self) -> Arc> { + self.client.clone() + } + + /// Executes closure in an externalities provided environment. + pub fn with_state(&self, closure: impl FnOnce() -> R) -> R + where + as CallExecutor>::Error: std::fmt::Debug, + { + let id = BlockId::Hash(self.client.info().best_hash); + let mut overlay = OverlayedChanges::default(); + let changes_trie = backend::changes_tries_state_at_block(&id, self.backend.changes_trie_storage()).unwrap(); + let mut cache = + StorageTransactionCache:: as Backend>::State>::default(); + let mut extensions = self + .client + .execution_extensions() + .extensions(&id, ExecutionContext::BlockConstruction); + let state_backend = self + .backend + .state_at(id.clone()) + .expect(&format!("State at block {} not found", id)); + + let mut ext = Ext::new( + &mut overlay, + &mut cache, + &state_backend, + changes_trie.clone(), + Some(&mut extensions), + ); + sp_externalities::set_and_run_with_externalities(&mut ext, closure) + } + + /// submit some extrinsic to the node, providing the sending account. + pub fn submit_extrinsic( + &mut self, + call: impl Into<::Call>, + from: ::AccountId, + ) -> ::Hash + where + ::Extrinsic: From< + UncheckedExtrinsic< + MultiAddress< + ::AccountId, + ::Index, + >, + ::Call, + MultiSignature, + T::SignedExtras, + >, + >, + { + let extra = self.with_state(|| T::signed_extras(from.clone())); + let signed_data = Some((from.into(), MultiSignature::Sr25519(Default::default()), extra)); + let ext = UncheckedExtrinsic::< + MultiAddress< + ::AccountId, + ::Index, + >, + ::Call, + MultiSignature, + T::SignedExtras, + >::new(call.into(), signed_data) + .expect("UncheckedExtrinsic::new() always returns Some"); + let at = self.client.info().best_hash; + + self._runtime + .block_on( + self.pool.submit_one(&BlockId::Hash(at), TransactionSource::Local, ext.into()), + ) + .unwrap() + } + + /// Get the events of the most recently produced block + pub fn events(&self) -> Vec> { + self.with_state(|| frame_system::Pallet::::events()) + } + + /// Checks the node logs for a specific entry. + pub fn assert_log_line(&mut self, content: &str) { + futures::executor::block_on(async { + use futures::StreamExt; + + while let Some(log_line) = self.log_stream.next().await { + if log_line.contains(content) { + return; + } + } + + panic!("Could not find {} in logs content", content); + }); + } + + /// Instructs manual seal to seal new, possibly empty blocks. + pub fn seal_blocks(&mut self, num: usize) { + let (tokio, sink) = (&mut self._runtime, &mut self.manual_seal_command_sink); + + for count in 0..num { + let (sender, future_block) = oneshot::channel(); + let future = sink.send(EngineCommand::SealNewBlock { + create_empty: true, + finalize: false, + parent_hash: None, + sender: Some(sender), + }); + + tokio.block_on(async { + const ERROR: &'static str = "manual-seal authorship task is shutting down"; + future.await.expect(ERROR); + + match future_block.await.expect(ERROR) { + Ok(block) => log::info!("sealed {} (hash: {}) of {} blocks", count + 1, block.hash, num), + Err(err) => log::error!("failed to seal block {} of {}, error: {:?}", count + 1, num, err), + } + }); + } + } + + /// Revert count number of blocks from the chain. + pub fn revert_blocks(&self, count: NumberFor) { + self.backend.revert(count, true).expect("Failed to revert blocks: "); + } + + /// Revert all blocks added since creation of the node. + pub fn clean(&self) { + // if a db path was specified, revert all blocks we've added + if let Some(_) = base_path() { + let diff = self.client.info().best_number - self.initial_block_number; + self.revert_blocks(diff); + } + } + + /// Performs a runtime upgrade given a wasm blob. + pub fn upgrade_runtime(&mut self, wasm: Vec) + where + ::Call: From> + { + let call = frame_system::Call::set_code(wasm); + T::dispatch_with_root(call.into(), self); + } +} + +impl Drop for Node { + fn drop(&mut self) { + self.clean(); + + if let Some(mut task_manager) = self._task_manager.take() { + // if this isn't called the node will live forever + task_manager.terminate() + } + } +} diff --git a/test-utils/test-runner/src/utils.rs b/test-utils/test-runner/src/utils.rs new file mode 100644 index 0000000000000..7cd512e2d4869 --- /dev/null +++ b/test-utils/test-runner/src/utils.rs @@ -0,0 +1,56 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use futures::{Sink, SinkExt}; +use std::fmt; +use std::io::Write; +use log::LevelFilter; + +/// Base db path gotten from env +pub fn base_path() -> Option { + std::env::var("DB_BASE_PATH").ok() +} + +/// Builds the global logger. +pub fn logger( + log_targets: Vec<(&'static str, LevelFilter)>, + executor: tokio::runtime::Handle, + log_sink: S, +) +where + S: Sink + Clone + Unpin + Send + Sync + 'static, + S::Error: Send + Sync + fmt::Debug, +{ + let mut builder = env_logger::builder(); + builder.format(move |buf: &mut env_logger::fmt::Formatter, record: &log::Record| { + let entry = format!("{} {} {}", record.level(), record.target(), record.args()); + let res = writeln!(buf, "{}", entry); + + let mut log_sink_clone = log_sink.clone(); + let _ = executor.spawn(async move { + log_sink_clone.send(entry).await.expect("log_stream is dropped"); + }); + res + }); + builder.write_style(env_logger::WriteStyle::Always); + + for (module, level) in log_targets { + builder.filter_module(module, level); + } + let _ = builder.is_test(true).try_init(); +}