From 0d95b60def51b559aaafd040931cbbcc5094c3bb Mon Sep 17 00:00:00 2001 From: clearloop Date: Wed, 25 Nov 2020 12:27:21 +0800 Subject: [PATCH] Pull from paritytech/substrate#7590 (#7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * make ClientConfig public (#7544) * sc-basic-authorship: remove useless dependencies (#7550) Signed-off-by: koushiro * Add slashing events to elections-phragmen. (#7543) * Add slashing events to elections-phragmen. * Fix build * Apply suggestions from code review * Update frame/elections-phragmen/src/lib.rs * Update frame/elections-phragmen/src/lib.rs Co-authored-by: Guillaume Thiolliere Co-authored-by: Guillaume Thiolliere * Remove necessity to pass ConsensusEngineId when registering notifications protocol (#7549) * Remove necessity to pass ConsensusEngineId when registering notifications protocol * Line width * Fix tests protocol name * Other renames * Doc update * Change issue in TODO * sc-cli: replace bip39 with tiny-bip39 (#7551) Signed-off-by: koushiro * Add extra docs to on_initialize (#7552) * Add some extra on_initialize docs. * Address review comments. * More Extensible Multiaddress Format (#7380) * More extensible multiaddress format * update name * Don't depend on indices to define multiaddress type * Use MultiAddress in Node Template too! * reduce traits, fix build * support multiple `StaticLookup` * bump tx version * feedback * Fix weight template to remove ugliness in rust doc (#7565) fixed weight template * Cargo.lock: Run cargo update (#7553) * Cargo.lock: Run cargo update * Cargo.lock: Downgrade cc to v1.0.62 * Cargo.lock: Revert wasm-* updates * .github: Add dependabot config and thus enable dependabot (#7509) * .github: Add dependabot config and thus enable dependabot * Update .github/dependabot.yml Co-authored-by: Pierre Krieger Co-authored-by: Pierre Krieger * Thread-local parameter_types for testing. (#7542) * Thread-local parameter_types for testing. * Better docs. * Some minors * Merge'em * Update frame/support/src/lib.rs Co-authored-by: Bastian Köcher * Align more to basti's trick * Update frame/support/src/lib.rs * Update frame/support/src/lib.rs Co-authored-by: Bastian Köcher Co-authored-by: Bastian Köcher * Bump wasm-bindgen-test from 0.3.12 to 0.3.17 (#7567) * Bump wasm-bindgen-test from 0.3.12 to 0.3.17 Bumps [wasm-bindgen-test](https://github.com/rustwasm/wasm-bindgen) from 0.3.12 to 0.3.17. - [Release notes](https://github.com/rustwasm/wasm-bindgen/releases) - [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/master/CHANGELOG.md) - [Commits](https://github.com/rustwasm/wasm-bindgen/commits) Signed-off-by: dependabot[bot] * Update wasm-bindgen pin to 0.2.68 Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Pierre Krieger * pallet-evm: move to Frontier (Part IV) (#7573) * Bump secrecy from 0.6.0 to 0.7.0 (#7568) * Bump secrecy from 0.6.0 to 0.7.0 Bumps [secrecy](https://github.com/iqlusioninc/crates) from 0.6.0 to 0.7.0. - [Release notes](https://github.com/iqlusioninc/crates/releases) - [Commits](https://github.com/iqlusioninc/crates/compare/secrecy/v0.6.0...secrecy/v0.7.0) Signed-off-by: dependabot[bot] * Fix compilation errors Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Pierre Krieger * Bump wasm-bindgen-futures from 0.4.17 to 0.4.18 (#7572) Bumps [wasm-bindgen-futures](https://github.com/rustwasm/wasm-bindgen) from 0.4.17 to 0.4.18. - [Release notes](https://github.com/rustwasm/wasm-bindgen/releases) - [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/master/CHANGELOG.md) - [Commits](https://github.com/rustwasm/wasm-bindgen/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump lru from 0.4.3 to 0.6.1 (#7577) Bumps [lru](https://github.com/jeromefroe/lru-rs) from 0.4.3 to 0.6.1. - [Release notes](https://github.com/jeromefroe/lru-rs/releases) - [Changelog](https://github.com/jeromefroe/lru-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/jeromefroe/lru-rs/compare/0.4.3...0.6.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump wasm-bindgen-test from 0.3.17 to 0.3.18 (#7579) Bumps [wasm-bindgen-test](https://github.com/rustwasm/wasm-bindgen) from 0.3.17 to 0.3.18. - [Release notes](https://github.com/rustwasm/wasm-bindgen/releases) - [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/master/CHANGELOG.md) - [Commits](https://github.com/rustwasm/wasm-bindgen/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump wasm-timer from 0.2.4 to 0.2.5 (#7578) Bumps [wasm-timer](https://github.com/tomaka/wasm-timer) from 0.2.4 to 0.2.5. - [Release notes](https://github.com/tomaka/wasm-timer/releases) - [Commits](https://github.com/tomaka/wasm-timer/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * grandpa: remove light-client specific block import pipeline (#7546) * grandpa: remove light-client specific block import * consensus, network: remove finality proofs * client/authority-discovery: Publish and query on exponential interval (#7545) * client/authority-discovery: Publish and query on exponential interval When a node starts up publishing and querying might fail due to various reasons, for example due to being not yet fully bootstrapped on the DHT. Thus one should retry rather sooner than later. On the other hand, a long running node is likely well connected and thus timely retries are not needed. For this reasoning use an exponentially increasing interval for `publish_interval`, `query_interval` and `priority_group_set_interval` instead of a constant interval. * client/authority-discovery/src/interval.rs: Add license header * .maintain/gitlab: Ensure adder collator tests are run on CI * sc-network: update some dependencies (#7582) Signed-off-by: koushiro * Bump linregress and do some other cleanups (#7580) * Wasm-builder 3.0 (#7532) * Build every wasm crate in its own project with wasm-builder Building all wasm crates in one workspace was a nice idea, however it just introduced problems: 1. We needed to prune old members, but this didn't worked for old git deps. 2. We locked the whole wasm workspace while building one crate. This could lead to infinitely locking the workspace on a crash. Now we just build every crate in its own project, this means we will build the dependencies multiple times. While building the dependencies multiple times, we still decrease the build time by around 30 seconds for Polkadot and Substrate because of the new parallelism ;) * Remove the requirement on wasm-builder-runner This removes the requirement on wasm-builder-runner by using the new `build_dep` feature of cargo. We use nightly anyway and that enables us to use this feature. This solves the problem of not mixing build/proc-macro deps with normal deps. By doing this we get rid off this complicated project structure and can depend directly on `wasm-builder`. This also removes all the code from wasm-builder-runner and mentions that it is deprecated. * Copy the `Cargo.lock` to the correct folder * Remove wasm-builder-runner * Update docs * Fix deterministic check Modified-by: Bastian Köcher * Try to make the ui test happy * Switch to `SKIP_WASM_BUILD` * Rename `SKIP_WASM_BINARY` to the correct name... * Update utils/wasm-builder/src/builder.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Update utils/wasm-builder/src/builder.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Bump tracing from 0.1.21 to 0.1.22 (#7589) Bumps [tracing](https://github.com/tokio-rs/tracing) from 0.1.21 to 0.1.22. - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.21...tracing-0.1.22) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * contracts: Add `salt` argument to contract instantiation (#7482) * pallet-contracts: Fix seal_restore_to to output proper module errors Those errors where part of the decl_error for some time but where never actually returned. This allows proper debugging of failed restorations. Previously, any error did return the misleading `ContractTrapped`. * Bind UncheckedFrom + AsRef<[u8]> everywhere This allows us to make assumptions about the AccoutId that are necessary for testing and in order to benchmark the module properly. This also groups free standing functions into inherent functions in order to minimize the places where the new bounds need to be specified. * Rework contract address determination * Do not allow override by runtime author * Instantiate gained a new parameter "salt" This change is done now in expecation of the upcoming code rent which needs to change the instantiation dispatchable and host function anyways. The situation in where we have only something that is like CREATE2 makes it impossible for UIs to help the user to create an arbitrary amount of instantiations from the same code. With this change we have the same functionality as ethereum with a CREATE and CREATE2 instantation semantic. * Remove TrieIdGenerator The new trait bounds allows us to remove this workaround from the configuration trait. * Remove default parameters for config trait It should be solely the responsiblity to determine proper values for these parameter. As a matter of fact most runtime weren't using these values anyways. * Fix tests for new account id type Because of the new bounds on the trait tests can't get away by using u64 as accound id. Replacing the 8 byte value by a 32 byte value creates out quite a bit of code churn. * Fix benchmarks The benchmarks need adaption to the new instantiate semantics. * Fix compile errors caused by adding new trait bounds * Fix compile errors caused by renaming storage and rent functions * Adapt host functions and dispatchables to the new salt * Add tests for instantiate host functions (was not possible before) * Add benchmark results * Adapt to the new WeightInfo The new benchmarks add a new parameter for salt "s" to the instantiate weights that needs to be applied. * Fix deploying_wasm_contract_should_work integration test This test is adapted to use the new instantiate signature. * Break overlong line * Break more long lines Co-authored-by: Parity Benchmarking Bot * */Cargo.toml: Remove unused dependencies (#7590) * */Cargo.toml: Remove unused dependencies Using cargo-udeps to detect unused dependencies. * client/network/Cargo: Revert dependency removal * Cargo.lock: Update Co-authored-by: Andrew Plaza Co-authored-by: Qinxuan Chen Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Guillaume Thiolliere Co-authored-by: Pierre Krieger Co-authored-by: Tomasz Drwięga Co-authored-by: Shawn Tabrizi Co-authored-by: Alexander Theißen Co-authored-by: Max Inden Co-authored-by: Bastian Köcher Co-authored-by: Bastian Köcher Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Wei Tang Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> Co-authored-by: Parity Benchmarking Bot --- .github/dependabot.yml | 7 + .gitlab-ci.yml | 12 +- .maintain/frame-weight-template.hbs | 3 +- .../gitlab/check_polkadot_companion_build.sh | 3 + .../substrate-dashboard.json | 102 -- Cargo.lock | 626 ++++++++---- Cargo.toml | 4 - bin/node-template/node/src/service.rs | 30 +- bin/node-template/runtime/Cargo.toml | 2 +- bin/node-template/runtime/build.rs | 3 +- bin/node-template/runtime/src/lib.rs | 6 +- bin/node/bench/src/tempdb.rs | 4 +- bin/node/browser-testing/Cargo.toml | 6 +- bin/node/cli/Cargo.toml | 4 +- bin/node/cli/src/service.rs | 37 +- bin/node/executor/tests/basic.rs | 10 +- bin/node/runtime/Cargo.toml | 2 +- bin/node/runtime/build.rs | 3 +- bin/node/runtime/src/lib.rs | 22 +- bin/node/testing/src/bench.rs | 9 +- bin/node/testing/src/keyring.rs | 2 +- client/api/Cargo.toml | 3 - client/authority-discovery/Cargo.toml | 2 - client/authority-discovery/src/interval.rs | 62 ++ client/authority-discovery/src/lib.rs | 51 +- client/authority-discovery/src/worker.rs | 73 +- .../authority-discovery/src/worker/tests.rs | 60 -- client/basic-authorship/Cargo.toml | 1 - client/cli/Cargo.toml | 4 +- client/cli/src/params/keystore_params.rs | 23 +- client/consensus/aura/src/lib.rs | 4 +- client/consensus/babe/src/lib.rs | 6 +- client/consensus/babe/src/tests.rs | 8 +- client/consensus/manual-seal/src/lib.rs | 4 - client/consensus/pow/src/lib.rs | 4 +- client/executor/Cargo.toml | 2 +- client/executor/runtime-test/Cargo.toml | 2 +- client/executor/runtime-test/build.rs | 6 +- client/executor/runtime-test/src/lib.rs | 2 +- client/finality-grandpa/src/aux_schema.rs | 22 - .../finality-grandpa/src/communication/mod.rs | 2 - .../src/communication/tests.rs | 23 +- .../finality-grandpa/src/consensus_changes.rs | 78 -- client/finality-grandpa/src/environment.rs | 91 +- client/finality-grandpa/src/finality_proof.rs | 41 +- client/finality-grandpa/src/import.rs | 15 +- client/finality-grandpa/src/lib.rs | 7 - client/finality-grandpa/src/light_import.rs | 880 ---------------- client/finality-grandpa/src/observer.rs | 5 - client/finality-grandpa/src/tests.rs | 190 +--- client/network-gossip/Cargo.toml | 2 +- client/network-gossip/src/bridge.rs | 51 +- client/network-gossip/src/lib.rs | 18 +- client/network-gossip/src/state_machine.rs | 54 +- client/network/Cargo.toml | 10 +- client/network/build.rs | 1 - client/network/src/behaviour.rs | 65 +- client/network/src/chain.rs | 12 - client/network/src/config.rs | 39 +- client/network/src/discovery.rs | 6 +- client/network/src/finality_requests.rs | 403 -------- client/network/src/gossip.rs | 9 +- client/network/src/gossip/tests.rs | 17 +- client/network/src/lib.rs | 1 - client/network/src/protocol.rs | 159 +-- client/network/src/protocol/event.rs | 8 +- .../src/protocol/generic_proto/handler.rs | 2 +- client/network/src/protocol/message.rs | 34 +- client/network/src/protocol/sync.rs | 158 +-- .../src/protocol/sync/extra_requests.rs | 5 +- client/network/src/schema.rs | 3 - client/network/src/schema/finality.v1.proto | 19 - client/network/src/service.rs | 166 +-- client/network/src/service/metrics.rs | 5 - client/network/src/service/out_events.rs | 29 +- client/network/src/service/tests.rs | 49 +- client/network/test/src/block_import.rs | 1 - client/network/test/src/lib.rs | 39 +- client/service/Cargo.toml | 2 +- client/service/src/builder.rs | 10 +- client/service/src/lib.rs | 4 +- client/telemetry/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- docs/CODEOWNERS | 3 - docs/README.adoc | 22 - frame/balances/src/tests_composite.rs | 12 +- frame/balances/src/tests_local.rs | 13 +- frame/benchmarking/Cargo.toml | 3 +- frame/contracts/fixtures/call_return_code.wat | 36 +- frame/contracts/fixtures/caller_contract.wat | 21 +- .../fixtures/destroy_and_transfer.wat | 42 +- frame/contracts/fixtures/drain.wat | 2 +- .../fixtures/instantiate_return_code.wat | 38 +- frame/contracts/fixtures/restoration.wat | 23 +- frame/contracts/fixtures/self_destruct.wat | 39 +- .../fixtures/self_destructing_constructor.wat | 2 +- frame/contracts/fixtures/set_rent.wat | 28 +- .../fixtures/transfer_return_code.wat | 21 +- frame/contracts/src/benchmarking/code.rs | 25 +- frame/contracts/src/benchmarking/mod.rs | 63 +- frame/contracts/src/benchmarking/sandbox.rs | 13 +- frame/contracts/src/exec.rs | 111 +- frame/contracts/src/lib.rs | 195 ++-- frame/contracts/src/rent.rs | 749 +++++++------- frame/contracts/src/schedule.rs | 8 +- frame/contracts/src/storage.rs | 342 ++++--- frame/contracts/src/tests.rs | 518 +++++----- frame/contracts/src/wasm/code_cache.rs | 7 +- frame/contracts/src/wasm/env_def/macros.rs | 14 +- frame/contracts/src/wasm/mod.rs | 194 ++-- frame/contracts/src/wasm/runtime.rs | 956 +++++++++-------- frame/contracts/src/weights.rs | 965 +++++++----------- frame/democracy/src/tests.rs | 16 +- frame/elections-phragmen/src/lib.rs | 44 +- frame/elections/src/mock.rs | 46 +- frame/elections/src/tests.rs | 12 +- frame/evm/Cargo.toml | 51 - frame/evm/README.md | 29 - frame/evm/src/backend.rs | 216 ---- frame/evm/src/lib.rs | 678 ------------ frame/evm/src/precompiles.rs | 167 --- frame/evm/src/tests.rs | 189 ---- frame/indices/src/address.rs | 159 --- frame/indices/src/lib.rs | 15 +- frame/membership/src/lib.rs | 8 +- frame/staking/src/mock.rs | 62 +- frame/support/src/lib.rs | 92 +- frame/support/src/traits.rs | 11 +- .../test/tests/construct_runtime_ui.rs | 2 +- frame/support/test/tests/decl_module_ui.rs | 2 +- frame/support/test/tests/decl_storage_ui.rs | 2 +- .../support/test/tests/derive_no_bound_ui.rs | 2 +- frame/support/test/tests/reserved_keyword.rs | 2 +- frame/transaction-payment/src/lib.rs | 23 +- frame/vesting/src/lib.rs | 10 +- primitives/api/test/tests/trybuild.rs | 2 +- primitives/blockchain/Cargo.toml | 3 +- primitives/consensus/common/Cargo.toml | 2 +- .../consensus/common/src/block_import.rs | 24 +- .../consensus/common/src/import_queue.rs | 29 +- .../common/src/import_queue/basic_queue.rs | 128 +-- .../common/src/import_queue/buffered_link.rs | 20 - primitives/consensus/common/src/lib.rs | 2 +- primitives/consensus/common/src/metrics.rs | 10 - primitives/core/Cargo.toml | 2 +- primitives/io/Cargo.toml | 2 +- primitives/panic-handler/Cargo.toml | 1 - .../test-wasm-deprecated/Cargo.toml | 2 +- .../test-wasm-deprecated/build.rs | 3 +- .../test-wasm-deprecated/src/lib.rs | 2 +- .../runtime-interface/test-wasm/Cargo.toml | 2 +- .../runtime-interface/test-wasm/build.rs | 3 +- .../runtime-interface/test-wasm/src/lib.rs | 2 +- primitives/runtime-interface/test/Cargo.toml | 2 +- primitives/runtime-interface/tests/ui.rs | 2 +- primitives/runtime/Cargo.toml | 2 - primitives/runtime/src/lib.rs | 4 + primitives/runtime/src/multiaddress.rs | 66 ++ primitives/runtime/src/traits.rs | 38 + primitives/tracing/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- test-utils/runtime/build.rs | 3 +- test-utils/runtime/src/lib.rs | 2 +- utils/browser/Cargo.toml | 2 +- utils/frame/benchmarking-cli/src/template.hbs | 3 +- utils/wasm-builder-runner/Cargo.toml | 15 - utils/wasm-builder-runner/README.md | 12 - utils/wasm-builder-runner/src/lib.rs | 498 --------- utils/wasm-builder/Cargo.toml | 6 +- utils/wasm-builder/README.md | 40 +- utils/wasm-builder/src/builder.rs | 245 +++++ utils/wasm-builder/src/lib.rs | 132 +-- utils/wasm-builder/src/wasm_project.rs | 228 ++--- 173 files changed, 3822 insertions(+), 7977 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 client/authority-discovery/src/interval.rs delete mode 100644 client/finality-grandpa/src/consensus_changes.rs delete mode 100644 client/finality-grandpa/src/light_import.rs delete mode 100644 client/network/src/finality_requests.rs delete mode 100644 client/network/src/schema/finality.v1.proto delete mode 100644 frame/evm/Cargo.toml delete mode 100644 frame/evm/README.md delete mode 100644 frame/evm/src/backend.rs delete mode 100644 frame/evm/src/lib.rs delete mode 100644 frame/evm/src/precompiles.rs delete mode 100644 frame/evm/src/tests.rs delete mode 100644 frame/indices/src/address.rs create mode 100644 primitives/runtime/src/multiaddress.rs delete mode 100644 utils/wasm-builder-runner/Cargo.toml delete mode 100644 utils/wasm-builder-runner/README.md delete mode 100644 utils/wasm-builder-runner/src/lib.rs create mode 100644 utils/wasm-builder/src/builder.rs diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000000..d782bb80f7539 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + labels: ["A2-insubstantial", "B0-silent", "C1-low"] + schedule: + interval: "daily" diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cbb56fcf72679..b37d60a941d44 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -197,7 +197,7 @@ cargo-check-benches: <<: *docker-env <<: *test-refs script: - - BUILD_DUMMY_WASM_BINARY=1 time cargo +nightly check --benches --all + - SKIP_WASM_BUILD=1 time cargo +nightly check --benches --all - cargo run --release -p node-bench -- ::node::import::native::sr25519::transfer_keep_alive::paritydb::small - cargo run --release -p node-bench -- ::trie::read::small - sccache -s @@ -208,7 +208,7 @@ cargo-check-subkey: <<: *test-refs script: - cd ./bin/utils/subkey - - BUILD_DUMMY_WASM_BINARY=1 time cargo check --release + - SKIP_WASM_BUILD=1 time cargo check --release - sccache -s test-deterministic-wasm: @@ -222,7 +222,7 @@ test-deterministic-wasm: # build runtime - cargo build --verbose --release -p node-runtime # make checksum - - sha256sum target/release/wbuild/target/wasm32-unknown-unknown/release/node_runtime.wasm > checksum.sha256 + - sha256sum target/release/wbuild/node-runtime/target/wasm32-unknown-unknown/release/node_runtime.wasm > checksum.sha256 # clean up – FIXME: can we reuse some of the artifacts? - cargo clean # build again @@ -343,7 +343,7 @@ cargo-check-macos: <<: *docker-env <<: *test-refs script: - - BUILD_DUMMY_WASM_BINARY=1 time cargo check --release + - SKIP_WASM_BUILD=1 time cargo check --release - sccache -s tags: - osx @@ -451,7 +451,7 @@ build-linux-subkey: &build-subkey - mkdir -p ./artifacts/subkey script: - cd ./bin/utils/subkey - - BUILD_DUMMY_WASM_BINARY=1 time cargo build --release --verbose + - SKIP_WASM_BUILD=1 time cargo build --release --verbose - cd - - mv ./target/release/subkey ./artifacts/subkey/. - echo -n "Subkey version = " @@ -483,7 +483,7 @@ build-rust-doc: - ./crate-docs/ script: - rm -f ./crate-docs/index.html # use it as an indicator if the job succeeds - - BUILD_DUMMY_WASM_BINARY=1 RUSTDOCFLAGS="--html-in-header $(pwd)/.maintain/rustdoc-header.html" + - SKIP_WASM_BUILD=1 RUSTDOCFLAGS="--html-in-header $(pwd)/.maintain/rustdoc-header.html" time cargo +nightly doc --no-deps --workspace --all-features --verbose - mv ./target/doc ./crate-docs - echo "" > ./crate-docs/index.html diff --git a/.maintain/frame-weight-template.hbs b/.maintain/frame-weight-template.hbs index 146cc4cfcbdb5..aac37f0833c7d 100644 --- a/.maintain/frame-weight-template.hbs +++ b/.maintain/frame-weight-template.hbs @@ -15,7 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Weights for {{pallet}} +//! Autogenerated weights for {{pallet}} +//! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}} //! DATE: {{date}}, STEPS: {{cmd.steps}}, REPEAT: {{cmd.repeat}}, LOW RANGE: {{cmd.lowest_range_values}}, HIGH RANGE: {{cmd.highest_range_values}} //! EXECUTION: {{cmd.execution}}, WASM-EXECUTION: {{cmd.wasm_execution}}, CHAIN: {{cmd.chain}}, DB CACHE: {{cmd.db_cache}} diff --git a/.maintain/gitlab/check_polkadot_companion_build.sh b/.maintain/gitlab/check_polkadot_companion_build.sh index 73a5a36ff8af9..4b6e45c267efe 100755 --- a/.maintain/gitlab/check_polkadot_companion_build.sh +++ b/.maintain/gitlab/check_polkadot_companion_build.sh @@ -92,3 +92,6 @@ cd polkadot # Test Polkadot pr or master branch with this Substrate commit. cargo update -p sp-io time cargo test --all --release --verbose --features=real-overseer + +cd parachain/test-parachains/adder/collator/ +time cargo test --release --verbose --locked --features=real-overseer diff --git a/.maintain/monitoring/grafana-dashboards/substrate-dashboard.json b/.maintain/monitoring/grafana-dashboards/substrate-dashboard.json index 629b22617b22a..a61e8a49bade7 100644 --- a/.maintain/monitoring/grafana-dashboards/substrate-dashboard.json +++ b/.maintain/monitoring/grafana-dashboards/substrate-dashboard.json @@ -756,108 +756,6 @@ "alignLevel": null } }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 6, - "w": 6, - "x": 0, - "y": 12 - }, - "hiddenSeries": false, - "id": 23, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "[[metric_namespace]]_sync_extra_finality_proofs_active{instance=\"[[instance]]\",network=\"[[network]]\"}", - "legendFormat": "{{instance}} active", - "refId": "A" - }, - { - "expr": "[[metric_namespace]]_sync_extra_finality_proofs_failed{instance=\"[[instance]]\",network=\"[[network]]\"}", - "legendFormat": "{{instance}} failed", - "refId": "B" - }, - { - "expr": "[[metric_namespace]]_sync_extra_finality_proofs_importing{instance=\"[[instance]]\",network=\"[[network]]\"}", - "legendFormat": "{{instance}} importing", - "refId": "C" - }, - { - "expr": "[[metric_namespace]]_sync_extra_finality_proofs_pending{instance=\"[[instance]]\",network=\"[[network]]\"}", - "legendFormat": "{{instance}} pending", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Sync Proof", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, { "aliasColors": {}, "bars": false, diff --git a/Cargo.lock b/Cargo.lock index 96687059b0805..7dc17b4217de1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,6 +97,7 @@ checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" [[package]] name = "ahash" version = "0.4.6" +<<<<<<< HEAD source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6789e291be47ace86a60303502173d84af8327e3627ecf334356ee0f87a164c" @@ -108,16 +109,18 @@ checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ "memchr", ] +======= +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6789e291be47ace86a60303502173d84af8327e3627ecf334356ee0f87a164c" +>>>>>>> parity/master [[package]] -name = "alga" -version = "0.9.3" +name = "aho-corasick" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f823d037a7ec6ea2197046bafd4ae150e6bc36f9ca347404f46a46823fa84f2" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ - "approx", - "num-complex", - "num-traits", + "memchr", ] [[package]] @@ -245,7 +248,11 @@ dependencies = [ "concurrent-queue", "fastrand", "futures-lite", +<<<<<<< HEAD "once_cell 1.5.2", +======= + "once_cell", +>>>>>>> parity/master "vec-arena", ] @@ -259,7 +266,11 @@ dependencies = [ "async-io", "futures-lite", "num_cpus", +<<<<<<< HEAD "once_cell 1.5.2", +======= + "once_cell", +>>>>>>> parity/master ] [[package]] @@ -274,7 +285,11 @@ dependencies = [ "libc", "log", "nb-connect", +<<<<<<< HEAD "once_cell 1.5.2", +======= + "once_cell", +>>>>>>> parity/master "parking", "polling", "vec-arena", @@ -311,7 +326,11 @@ dependencies = [ "log", "memchr", "num_cpus", +<<<<<<< HEAD "once_cell 1.5.2", +======= + "once_cell", +>>>>>>> parity/master "pin-project-lite 0.1.11", "pin-utils", "slab", @@ -339,9 +358,15 @@ dependencies = [ [[package]] name = "async-trait" +<<<<<<< HEAD version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d" +======= +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0" +>>>>>>> parity/master dependencies = [ "proc-macro2", "quote", @@ -388,9 +413,15 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" +<<<<<<< HEAD version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598" +======= +version = "0.3.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2baad346b2d4e94a24347adeee9c7a93f412ee94b9cc26e5b59dea23848e9f28" +>>>>>>> parity/master dependencies = [ "addr2line", "cfg-if 1.0.0", @@ -469,6 +500,7 @@ dependencies = [ ] [[package]] +<<<<<<< HEAD name = "bip39" version = "0.6.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -490,6 +522,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3" [[package]] +======= +>>>>>>> parity/master name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -605,15 +639,13 @@ dependencies = [ "atomic-waker", "fastrand", "futures-lite", +<<<<<<< HEAD "once_cell 1.5.2", +======= + "once_cell", +>>>>>>> parity/master ] -[[package]] -name = "bs58" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" - [[package]] name = "bs58" version = "0.4.0" @@ -690,13 +722,20 @@ checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" [[package]] name = "cargo_metadata" +<<<<<<< HEAD version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8de60b887edf6d74370fc8eb177040da4847d971d6234c7b13a6da324ef0caf" dependencies = [ "semver 0.9.0", +======= +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5a5f7b42f606b7f23674f6f4d877628350682bc40687d3fae65679a58d55345" +dependencies = [ + "semver 0.11.0", +>>>>>>> parity/master "serde", - "serde_derive", "serde_json", ] @@ -711,9 +750,15 @@ dependencies = [ [[package]] name = "cc" +<<<<<<< HEAD version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15" +======= +version = "1.0.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40" +>>>>>>> parity/master dependencies = [ "jobserver", ] @@ -1058,6 +1103,7 @@ dependencies = [ ] [[package]] +<<<<<<< HEAD name = "crossbeam" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1082,6 +1128,8 @@ dependencies = [ ] [[package]] +======= +>>>>>>> parity/master name = "crossbeam-channel" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1125,7 +1173,21 @@ dependencies = [ "lazy_static", "maybe-uninit", "memoffset", - "scopeguard 1.1.0", + "scopeguard", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f" +dependencies = [ + "cfg-if 1.0.0", + "const_fn", + "crossbeam-utils 0.8.0", + "lazy_static", + "memoffset", + "scopeguard", ] [[package]] @@ -1540,6 +1602,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" [[package]] +<<<<<<< HEAD name = "evm" version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1590,6 +1653,8 @@ dependencies = [ ] [[package]] +======= +>>>>>>> parity/master name = "exit-future" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1864,13 +1929,18 @@ dependencies = [ "frame-system 2.0.0", "impl-trait-for-tuples", "log", +<<<<<<< HEAD "once_cell 1.5.2", +======= + "once_cell", +>>>>>>> parity/master "parity-scale-codec", "parity-util-mem", "paste 0.1.18", "pretty_assertions", "serde", "smallvec 1.5.0", +<<<<<<< HEAD "sp-api 2.0.0", "sp-arithmetic 2.0.0", "sp-core 2.0.0", @@ -1880,6 +1950,17 @@ dependencies = [ "sp-state-machine 0.8.0", "sp-std 2.0.0", "sp-tracing 2.0.0", +======= + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-inherents", + "sp-io", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-tracing", +>>>>>>> parity/master "substrate-test-runtime-client", ] @@ -2059,16 +2140,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi 0.3.9", -] - [[package]] name = "fs_extra" version = "1.2.0" @@ -2128,26 +2199,20 @@ dependencies = [ "futures-sink", ] -[[package]] -name = "futures-channel-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" -dependencies = [ - "futures-core-preview", -] - [[package]] name = "futures-core" version = "0.3.8" +<<<<<<< HEAD source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748" [[package]] name = "futures-core-preview" version = "0.3.0-alpha.19" +======= +>>>>>>> parity/master source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" +checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748" [[package]] name = "futures-cpupool" @@ -2232,7 +2297,11 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d" dependencies = [ +<<<<<<< HEAD "once_cell 1.5.2", +======= + "once_cell", +>>>>>>> parity/master ] [[package]] @@ -2272,18 +2341,6 @@ dependencies = [ "slab", ] -[[package]] -name = "futures-util-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" -dependencies = [ - "futures-channel-preview", - "futures-core-preview", - "pin-utils", - "slab", -] - [[package]] name = "futures_codec" version = "0.4.1" @@ -2499,26 +2556,27 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.1.8" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" +checksum = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" dependencies = [ - "byteorder", - "scopeguard 0.3.3", + "ahash 0.2.19", + "autocfg 0.1.7", ] [[package]] name = "hashbrown" -version = "0.6.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" +checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" dependencies = [ - "ahash 0.2.19", - "autocfg 0.1.7", + "ahash 0.3.8", + "autocfg 1.0.1", ] [[package]] name = "hashbrown" +<<<<<<< HEAD version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" @@ -2533,6 +2591,12 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" dependencies = [ +======= +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +dependencies = [ +>>>>>>> parity/master "ahash 0.4.6", ] @@ -2700,7 +2764,7 @@ dependencies = [ "time", "tokio 0.1.22", "tokio-buf", - "tokio-executor 0.1.10", + "tokio-executor", "tokio-io", "tokio-reactor", "tokio-tcp", @@ -2845,9 +2909,15 @@ dependencies = [ [[package]] name = "instant" +<<<<<<< HEAD version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +======= +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613" +>>>>>>> parity/master dependencies = [ "cfg-if 1.0.0", ] @@ -2927,9 +2997,15 @@ dependencies = [ [[package]] name = "js-sys" +<<<<<<< HEAD version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85a7e2c92a4804dd459b86c339278d0fe87cf93757fae222c3fa3ae75458bc73" +======= +version = "0.3.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" +>>>>>>> parity/master dependencies = [ "wasm-bindgen", ] @@ -3243,7 +3319,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8186060d6bd415e4e928e6cb44c4fe7e7a7dd53437bd936ce7e5f421e45a51" dependencies = [ "asn1_der", - "bs58 0.4.0", + "bs58", "ed25519-dalek", "either", "fnv", @@ -3265,7 +3341,7 @@ dependencies = [ "sha2 0.9.2", "smallvec 1.5.0", "thiserror", - "unsigned-varint 0.5.1", + "unsigned-varint", "void", "zeroize", ] @@ -3342,7 +3418,11 @@ dependencies = [ "rand 0.7.3", "sha2 0.9.2", "smallvec 1.5.0", +<<<<<<< HEAD "unsigned-varint 0.5.1", +======= + "unsigned-varint", +>>>>>>> parity/master "wasm-timer", ] @@ -3384,7 +3464,7 @@ dependencies = [ "sha2 0.9.2", "smallvec 1.5.0", "uint", - "unsigned-varint 0.5.1", + "unsigned-varint", "void", "wasm-timer", ] @@ -3426,7 +3506,11 @@ dependencies = [ "parking_lot 0.11.1", "rand 0.7.3", "smallvec 1.5.0", +<<<<<<< HEAD "unsigned-varint 0.5.1", +======= + "unsigned-varint", +>>>>>>> parity/master ] [[package]] @@ -3479,7 +3563,7 @@ dependencies = [ "log", "prost", "prost-build", - "unsigned-varint 0.5.1", + "unsigned-varint", "void", ] @@ -3494,7 +3578,7 @@ dependencies = [ "pin-project 0.4.27", "rand 0.7.3", "salsa20", - "sha3 0.9.1", + "sha3", ] [[package]] @@ -3513,7 +3597,11 @@ dependencies = [ "minicbor", "rand 0.7.3", "smallvec 1.5.0", +<<<<<<< HEAD "unsigned-varint 0.5.1", +======= + "unsigned-varint", +>>>>>>> parity/master "wasm-timer", ] @@ -3664,10 +3752,11 @@ dependencies = [ [[package]] name = "linregress" -version = "0.1.7" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9290cf6f928576eeb9c096c6fad9d8d452a0a1a70a2bbffa6e36064eedc0aac9" +checksum = "0d0ad4b5cc8385a881c561fac3501353d63d2a2b7a357b5064d71815c9a92724" dependencies = [ +<<<<<<< HEAD "failure", "nalgebra 0.18.1", "statrs 0.10.0", @@ -3681,6 +3770,10 @@ checksum = "0d0ad4b5cc8385a881c561fac3501353d63d2a2b7a357b5064d71815c9a92724" dependencies = [ "nalgebra 0.21.1", "statrs 0.12.0", +======= + "nalgebra", + "statrs", +>>>>>>> parity/master ] [[package]] @@ -3701,22 +3794,13 @@ dependencies = [ "paste 0.1.18", ] -[[package]] -name = "lock_api" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -dependencies = [ - "scopeguard 0.3.3", -] - [[package]] name = "lock_api" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" dependencies = [ - "scopeguard 1.1.0", + "scopeguard", ] [[package]] @@ -3725,7 +3809,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" dependencies = [ - "scopeguard 1.1.0", + "scopeguard", ] [[package]] @@ -3740,6 +3824,7 @@ dependencies = [ [[package]] name = "loom" version = "0.3.6" +<<<<<<< HEAD source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0e8460f2f2121162705187214720353c517b97bdfb3494c0b1e33d83ebe4bed" dependencies = [ @@ -3753,10 +3838,16 @@ dependencies = [ [[package]] name = "lru" version = "0.4.3" +======= +>>>>>>> parity/master source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0609345ddee5badacf857d4f547e0e5a2e987db77085c24cd887f73573a04237" +checksum = "a0e8460f2f2121162705187214720353c517b97bdfb3494c0b1e33d83ebe4bed" dependencies = [ - "hashbrown 0.6.3", + "cfg-if 0.1.10", + "generator", + "scoped-tls", + "serde", + "serde_json", ] [[package]] @@ -4013,8 +4104,13 @@ dependencies = [ "digest 0.9.0", "sha-1 0.9.2", "sha2 0.9.2", +<<<<<<< HEAD "sha3 0.9.1", "unsigned-varint 0.5.1", +======= + "sha3", + "unsigned-varint", +>>>>>>> parity/master ] [[package]] @@ -4034,23 +4130,28 @@ dependencies = [ "log", "pin-project 1.0.2", "smallvec 1.5.0", +<<<<<<< HEAD "unsigned-varint 0.5.1", +======= + "unsigned-varint", +>>>>>>> parity/master ] [[package]] name = "nalgebra" -version = "0.18.1" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaa9fddbc34c8c35dd2108515587b8ce0cab396f17977b8c738568e4edb521a2" +checksum = "d6b6147c3d50b4f3cdabfe2ecc94a0191fd3d6ad58aefd9664cf396285883486" dependencies = [ - "alga", "approx", - "generic-array 0.12.3", + "generic-array 0.13.2", "matrixmultiply", "num-complex", "num-rational", "num-traits", - "rand 0.6.5", + "rand 0.7.3", + "rand_distr", + "simba", "typenum", ] @@ -4091,6 +4192,16 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "nb-connect" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8123a81538e457d44b933a02faf885d3fe8408806b23fa700e8f01c6c3a98998" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "net2" version = "0.2.35" @@ -4176,8 +4287,13 @@ version = "2.0.0" dependencies = [ "assert_cmd", "frame-benchmarking-cli", +<<<<<<< HEAD "frame-support 2.0.0", "frame-system 2.0.0", +======= + "frame-support", + "frame-system", +>>>>>>> parity/master "futures 0.3.8", "hex-literal", "log", @@ -4418,7 +4534,7 @@ dependencies = [ "sp-transaction-pool", "sp-version 2.0.0", "static_assertions", - "substrate-wasm-builder-runner", + "substrate-wasm-builder", ] [[package]] @@ -4488,8 +4604,13 @@ dependencies = [ "sp-session", "sp-std 2.0.0", "sp-transaction-pool", +<<<<<<< HEAD "sp-version 2.0.0", "substrate-wasm-builder-runner", +======= + "sp-version", + "substrate-wasm-builder", +>>>>>>> parity/master ] [[package]] @@ -4641,17 +4762,17 @@ dependencies = [ [[package]] name = "object" version = "0.22.0" +<<<<<<< HEAD source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" [[package]] name = "once_cell" version = "0.1.8" +======= +>>>>>>> parity/master source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" -dependencies = [ - "parking_lot 0.7.1", -] +checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" [[package]] name = "once_cell" @@ -5025,6 +5146,7 @@ dependencies = [ ] [[package]] +<<<<<<< HEAD name = "pallet-evm" version = "2.0.0" dependencies = [ @@ -5047,6 +5169,8 @@ dependencies = [ ] [[package]] +======= +>>>>>>> parity/master name = "pallet-example" version = "2.0.0" dependencies = [ @@ -5557,11 +5681,19 @@ dependencies = [ "parity-scale-codec", "serde", "smallvec 1.5.0", +<<<<<<< HEAD "sp-core 2.0.0", "sp-io 2.0.0", "sp-runtime 2.0.0", "sp-std 2.0.0", "sp-storage 2.0.0", +======= + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-storage", +>>>>>>> parity/master ] [[package]] @@ -5667,14 +5799,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43244a26dc1ddd3097216bb12eaa6cf8a07b060c72718d9ebd60fd297d6401df" dependencies = [ "arrayref", - "bs58 0.4.0", + "bs58", "byteorder", "data-encoding", "multihash", "percent-encoding 2.1.0", "serde", "static_assertions", +<<<<<<< HEAD "unsigned-varint 0.5.1", +======= + "unsigned-varint", +>>>>>>> parity/master "url 2.2.0", ] @@ -5796,16 +5932,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" -[[package]] -name = "parking_lot" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -dependencies = [ - "lock_api 0.1.5", - "parking_lot_core 0.4.0", -] - [[package]] name = "parking_lot" version = "0.9.0" @@ -5838,19 +5964,6 @@ dependencies = [ "parking_lot_core 0.8.0", ] -[[package]] -name = "parking_lot_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -dependencies = [ - "libc", - "rand 0.6.5", - "rustc_version", - "smallvec 0.6.13", - "winapi 0.3.9", -] - [[package]] name = "parking_lot_core" version = "0.6.2" @@ -5928,7 +6041,6 @@ checksum = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" dependencies = [ "byteorder", "crypto-mac 0.7.0", - "rayon", ] [[package]] @@ -6060,6 +6172,15 @@ dependencies = [ [[package]] name = "pin-project-lite" version = "0.1.11" +<<<<<<< HEAD +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" + +[[package]] +name = "pin-project-lite" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +======= source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" @@ -6067,6 +6188,7 @@ checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" name = "pin-project-lite" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +>>>>>>> parity/master checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c" [[package]] @@ -6402,19 +6524,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "rand" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -dependencies = [ - "cloudabi 0.0.3", - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "winapi 0.3.9", -] - [[package]] name = "rand" version = "0.6.5" @@ -6617,7 +6726,11 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" dependencies = [ +<<<<<<< HEAD "crossbeam-channel 0.5.0", +======= + "crossbeam-channel", +>>>>>>> parity/master "crossbeam-deque 0.8.0", "crossbeam-utils 0.8.0", "lazy_static", @@ -6738,6 +6851,7 @@ checksum = "e005d658ad26eacc2b6c506dfde519f4e277e328d0eb3379ca61647d70a8f531" [[package]] name = "ring" +<<<<<<< HEAD version = "0.16.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5911690c9b773bab7e657471afc207f3827b249a657241327e3544d79bcabdd" @@ -6745,23 +6859,21 @@ dependencies = [ "cc", "libc", "once_cell 1.5.2", +======= +version = "0.16.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72b84d47e8ec5a4f2872e8262b8f8256c5be1c938a7d6d3a867a3ba8f722f74" +dependencies = [ + "cc", + "libc", + "once_cell", +>>>>>>> parity/master "spin", "untrusted", "web-sys", "winapi 0.3.9", ] -[[package]] -name = "ripemd160" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eca4ecc81b7f313189bf73ce724400a07da2a6dac19588b03c8bd76a2dcc251" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "opaque-debug 0.3.0", -] - [[package]] name = "rlp" version = "0.4.6" @@ -6921,7 +7033,6 @@ name = "sc-authority-discovery" version = "0.8.0" dependencies = [ "async-trait", - "bytes 0.5.6", "derive_more", "either", "futures 0.3.8", @@ -6934,7 +7045,6 @@ dependencies = [ "quickcheck", "rand 0.7.3", "sc-client-api", - "sc-keystore", "sc-network", "sc-peerset", "serde_json", @@ -6972,7 +7082,6 @@ dependencies = [ "sp-transaction-pool", "substrate-prometheus-endpoint", "substrate-test-runtime-client", - "tokio-executor 0.2.0-alpha.6", ] [[package]] @@ -7029,7 +7138,6 @@ version = "0.8.0" dependencies = [ "ansi_term 0.12.1", "atty", - "bip39", "chrono", "fdlimit", "futures 0.3.8", @@ -7062,6 +7170,10 @@ dependencies = [ "structopt", "tempfile", "thiserror", +<<<<<<< HEAD +======= + "tiny-bip39", +>>>>>>> parity/master "tokio 0.2.23", "tracing", "tracing-log", @@ -7086,7 +7198,6 @@ dependencies = [ "fnv", "futures 0.3.8", "hash-db", - "hex-literal", "kvdb", "kvdb-memorydb", "lazy_static", @@ -7094,12 +7205,17 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.10.2", "sc-executor", +<<<<<<< HEAD "sc-telemetry", "sp-api 2.0.0", +======= + "sp-api", +>>>>>>> parity/master "sp-blockchain", "sp-consensus", "sp-core 2.0.0", "sp-database", +<<<<<<< HEAD "sp-externalities 0.8.0", "sp-inherents 2.0.0", "sp-keyring", @@ -7108,6 +7224,15 @@ dependencies = [ "sp-state-machine 0.8.0", "sp-std 2.0.0", "sp-storage 2.0.0", +======= + "sp-externalities", + "sp-inherents", + "sp-keystore", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-storage", +>>>>>>> parity/master "sp-test-primitives", "sp-transaction-pool", "sp-trie 2.0.0", @@ -7586,9 +7711,15 @@ dependencies = [ "parking_lot 0.10.2", "rand 0.7.3", "serde_json", +<<<<<<< HEAD "sp-application-crypto 2.0.0", "sp-core 2.0.0", "sp-keystore 0.8.0", +======= + "sp-application-crypto", + "sp-core", + "sp-keystore", +>>>>>>> parity/master "subtle 2.3.0", "tempfile", ] @@ -7619,7 +7750,7 @@ dependencies = [ "async-std", "async-trait", "bitflags", - "bs58 0.3.1", + "bs58", "bytes 0.5.6", "derive_more", "either", @@ -7635,10 +7766,14 @@ dependencies = [ "linked-hash-map", "linked_hash_set", "log", - "lru 0.4.3", + "lru 0.6.1", "nohash-hasher", "parity-scale-codec", +<<<<<<< HEAD "parking_lot 0.10.2", +======= + "parking_lot 0.11.1", +>>>>>>> parity/master "pin-project 0.4.27", "prost", "prost-build", @@ -7651,8 +7786,13 @@ dependencies = [ "serde_json", "slog", "slog_derive", +<<<<<<< HEAD "smallvec 0.6.13", "sp-arithmetic 2.0.0", +======= + "smallvec 1.5.0", + "sp-arithmetic", +>>>>>>> parity/master "sp-blockchain", "sp-consensus", "sp-core 2.0.0", @@ -7666,7 +7806,7 @@ dependencies = [ "substrate-test-runtime-client", "tempfile", "thiserror", - "unsigned-varint 0.4.0", + "unsigned-varint", "void", "wasm-timer", "zeroize", @@ -7681,7 +7821,7 @@ dependencies = [ "futures-timer 3.0.2", "libp2p", "log", - "lru 0.4.3", + "lru 0.6.1", "quickcheck", "rand 0.7.3", "sc-network", @@ -7861,7 +8001,7 @@ dependencies = [ "sp-sandbox 0.8.0", "sp-std 2.0.0", "sp-tasks", - "substrate-wasm-builder-runner", + "substrate-wasm-builder", ] [[package]] @@ -8129,12 +8269,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" -[[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" - [[package]] name = "scopeguard" version = "1.1.0" @@ -8173,9 +8307,9 @@ dependencies = [ [[package]] name = "secrecy" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9182278ed645df3477a9c27bfee0621c621aa16f6972635f7f795dae3d81070f" +checksum = "0673d6a6449f5e7d12a1caf424fd9363e2af3a4953023ed455e3c4beef4597c0" dependencies = [ "zeroize", ] @@ -8218,7 +8352,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" dependencies = [ - "semver-parser", + "semver-parser 0.7.0", ] [[package]] @@ -8227,7 +8361,20 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ +<<<<<<< HEAD "semver-parser", +======= + "semver-parser 0.7.0", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser 0.10.1", +>>>>>>> parity/master "serde", ] @@ -8238,6 +8385,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] +<<<<<<< HEAD +======= +name = "semver-parser" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ef146c2ad5e5f4b037cd6ce2ebb775401729b19a82040c1beac9d36c7d1428" +dependencies = [ + "pest", +] + +[[package]] +>>>>>>> parity/master name = "send_wrapper" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -8340,19 +8499,6 @@ dependencies = [ "opaque-debug 0.3.0", ] -[[package]] -name = "sha3" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" -dependencies = [ - "block-buffer 0.7.3", - "byte-tools", - "digest 0.8.1", - "keccak", - "opaque-debug 0.2.3", -] - [[package]] name = "sha3" version = "0.9.1" @@ -8493,9 +8639,15 @@ dependencies = [ [[package]] name = "socket2" +<<<<<<< HEAD version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c29947abdee2a218277abeca306f25789c938e500ea5a9d4b12a5a504466902" +======= +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd8b795c389288baa5f355489c65e71fd48a02104600d15c4cfbc561e9e429d" +>>>>>>> parity/master dependencies = [ "cfg-if 1.0.0", "libc", @@ -8714,10 +8866,9 @@ name = "sp-blockchain" version = "2.0.0" dependencies = [ "log", - "lru 0.4.3", + "lru 0.6.1", "parity-scale-codec", "parking_lot 0.10.2", - "sp-block-builder", "sp-consensus", "sp-database", "sp-runtime 2.0.0", @@ -9006,6 +9157,7 @@ name = "sp-io" version = "2.0.0" dependencies = [ "futures 0.3.8", +<<<<<<< HEAD "hash-db", "libsecp256k1", "log", @@ -9030,6 +9182,8 @@ version = "2.0.0" source = "git+https://github.com/paritytech/substrate?branch=master#3558103e2e80259ab0e8c136ec23687647cb32f4" dependencies = [ "futures 0.3.8", +======= +>>>>>>> parity/master "hash-db", "libsecp256k1", "log", @@ -9151,7 +9305,6 @@ version = "2.0.0" source = "git+https://github.com/paritytech/substrate?branch=master#3558103e2e80259ab0e8c136ec23687647cb32f4" dependencies = [ "backtrace", - "log", ] [[package]] @@ -9177,6 +9330,7 @@ dependencies = [ "rand 0.7.3", "serde", "serde_json", +<<<<<<< HEAD "sp-application-crypto 2.0.0", "sp-arithmetic 2.0.0", "sp-core 2.0.0", @@ -9206,6 +9360,14 @@ dependencies = [ "sp-inherents 2.0.0 (git+https://github.com/paritytech/substrate)", "sp-io 2.0.0 (git+https://github.com/paritytech/substrate)", "sp-std 2.0.0 (git+https://github.com/paritytech/substrate)", +======= + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-state-machine", + "sp-std", +>>>>>>> parity/master ] [[package]] @@ -9288,22 +9450,38 @@ dependencies = [ name = "sp-runtime-interface-test-wasm" version = "2.0.0" dependencies = [ +<<<<<<< HEAD "sp-core 2.0.0", "sp-io 2.0.0", "sp-runtime-interface 2.0.0", "sp-std 2.0.0", "substrate-wasm-builder-runner", +======= + "sp-core", + "sp-io", + "sp-runtime-interface", + "sp-std", + "substrate-wasm-builder", +>>>>>>> parity/master ] [[package]] name = "sp-runtime-interface-test-wasm-deprecated" version = "2.0.0" dependencies = [ +<<<<<<< HEAD "sp-core 2.0.0", "sp-io 2.0.0", "sp-runtime-interface 2.0.0", "sp-std 2.0.0", "substrate-wasm-builder-runner", +======= + "sp-core", + "sp-io", + "sp-runtime-interface", + "sp-std", + "substrate-wasm-builder", +>>>>>>> parity/master ] [[package]] @@ -9375,6 +9553,7 @@ dependencies = [ "pretty_assertions", "rand 0.7.3", "smallvec 1.5.0", +<<<<<<< HEAD "sp-core 2.0.0", "sp-externalities 0.8.0", "sp-panic-handler 2.0.0", @@ -9403,6 +9582,14 @@ dependencies = [ "sp-panic-handler 2.0.0 (git+https://github.com/paritytech/substrate)", "sp-std 2.0.0 (git+https://github.com/paritytech/substrate)", "sp-trie 2.0.0 (git+https://github.com/paritytech/substrate)", +======= + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-runtime", + "sp-std", + "sp-trie", +>>>>>>> parity/master "thiserror", "trie-db", "trie-root", @@ -9640,6 +9827,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "statrs" +<<<<<<< HEAD version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10102ac8d55e35db2b3fafc26f81ba8647da2e15879ab686a67e6d19af2685e8" @@ -9649,6 +9837,8 @@ dependencies = [ [[package]] name = "statrs" +======= +>>>>>>> parity/master version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cce16f6de653e88beca7bd13780d08e09d4489dbca1f9210e041bc4852481382" @@ -9799,15 +9989,24 @@ dependencies = [ name = "substrate-frame-rpc-support" version = "2.0.0" dependencies = [ +<<<<<<< HEAD "frame-support 2.0.0", "frame-system 2.0.0", +======= + "frame-support", + "frame-system", +>>>>>>> parity/master "futures 0.3.8", "jsonrpc-client-transports", "jsonrpc-core", "parity-scale-codec", "sc-rpc-api", "serde", +<<<<<<< HEAD "sp-storage 2.0.0", +======= + "sp-storage", +>>>>>>> parity/master "tokio 0.2.23", ] @@ -9915,7 +10114,7 @@ dependencies = [ "sp-trie 2.0.0", "sp-version 2.0.0", "substrate-test-runtime-client", - "substrate-wasm-builder-runner", + "substrate-wasm-builder", "trie-db", ] @@ -9985,24 +10184,18 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" -version = "2.0.1" +version = "3.0.0" dependencies = [ "ansi_term 0.12.1", "atty", "build-helper", "cargo_metadata", - "fs2", - "itertools 0.8.2", "tempfile", "toml", "walkdir", "wasm-gc-api", ] -[[package]] -name = "substrate-wasm-builder-runner" -version = "2.0.0" - [[package]] name = "subtle" version = "1.0.0" @@ -10066,9 +10259,15 @@ dependencies = [ [[package]] name = "termcolor" +<<<<<<< HEAD version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +======= +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf11676eb135389f21fcda654382c4859bbfc1d2f36e4425a2f829bb41b1e20e" +>>>>>>> parity/master dependencies = [ "winapi-util", ] @@ -10152,7 +10351,11 @@ checksum = "d9e44c4759bae7f1032e286a7ef990bd9ed23fe831b7eeba0beb97484c2e59b8" dependencies = [ "anyhow", "hmac 0.8.1", +<<<<<<< HEAD "once_cell 1.5.2", +======= + "once_cell", +>>>>>>> parity/master "pbkdf2 0.4.0", "rand 0.7.3", "rustc-hash", @@ -10183,9 +10386,15 @@ dependencies = [ [[package]] name = "tinyvec" +<<<<<<< HEAD version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f" +======= +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b78a366903f506d2ad52ca8dc552102ffdd3e937ba8a227f024dc1d1eae28575" +>>>>>>> parity/master dependencies = [ "tinyvec_macros", ] @@ -10208,11 +10417,11 @@ dependencies = [ "num_cpus", "tokio-codec", "tokio-current-thread", - "tokio-executor 0.1.10", + "tokio-executor", "tokio-fs", "tokio-io", "tokio-reactor", - "tokio-sync 0.1.8", + "tokio-sync", "tokio-tcp", "tokio-threadpool", "tokio-timer", @@ -10272,7 +10481,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" dependencies = [ "futures 0.1.30", +<<<<<<< HEAD "tokio-executor 0.1.10", +======= + "tokio-executor", +>>>>>>> parity/master ] [[package]] @@ -10283,6 +10496,7 @@ checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" dependencies = [ "crossbeam-utils 0.7.2", "futures 0.1.30", +<<<<<<< HEAD ] [[package]] @@ -10294,6 +10508,8 @@ dependencies = [ "futures-util-preview", "lazy_static", "tokio-sync 0.2.0-alpha.6", +======= +>>>>>>> parity/master ] [[package]] @@ -10356,9 +10572,9 @@ dependencies = [ "num_cpus", "parking_lot 0.9.0", "slab", - "tokio-executor 0.1.10", + "tokio-executor", "tokio-io", - "tokio-sync 0.1.8", + "tokio-sync", ] [[package]] @@ -10390,6 +10606,7 @@ checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" dependencies = [ "fnv", "futures 0.1.30", +<<<<<<< HEAD ] [[package]] @@ -10401,6 +10618,8 @@ dependencies = [ "fnv", "futures-core-preview", "futures-util-preview", +======= +>>>>>>> parity/master ] [[package]] @@ -10431,7 +10650,7 @@ dependencies = [ "log", "num_cpus", "slab", - "tokio-executor 0.1.10", + "tokio-executor", ] [[package]] @@ -10443,7 +10662,7 @@ dependencies = [ "crossbeam-utils 0.7.2", "futures 0.1.30", "slab", - "tokio-executor 0.1.10", + "tokio-executor", ] [[package]] @@ -10767,6 +10986,7 @@ checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" dependencies = [ "generic-array 0.14.4", "subtle 2.3.0", +<<<<<<< HEAD ] [[package]] @@ -10779,6 +10999,8 @@ dependencies = [ "futures-io", "futures-util", "futures_codec", +======= +>>>>>>> parity/master ] [[package]] @@ -10913,9 +11135,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.67" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0563a9a4b071746dd5aedbc3a28c6fe9be4586fb3fbadb67c400d4f53c6b16c" +checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" dependencies = [ "cfg-if 0.1.10", "serde", @@ -10925,9 +11147,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.67" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc71e4c5efa60fb9e74160e89b93353bc24059999c0ae0fb03affc39770310b0" +checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" dependencies = [ "bumpalo", "lazy_static", @@ -10940,9 +11162,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" +<<<<<<< HEAD version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95f8d235a77f880bcef268d379810ea6c0af2eacfa90b1ad5af731776e0c4699" +======= +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" +>>>>>>> parity/master dependencies = [ "cfg-if 0.1.10", "js-sys", @@ -10952,9 +11180,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.67" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97c57cefa5fa80e2ba15641578b44d36e7a64279bc5ed43c6dbaf329457a2ed2" +checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -10962,9 +11190,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.67" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841a6d1c35c6f596ccea1f82504a192a60378f64b3bb0261904ad8f2f5657556" +checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" dependencies = [ "proc-macro2", "quote", @@ -10975,15 +11203,21 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.67" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93b162580e34310e5931c4b792560108b10fd14d64915d7fff8ff00180e70092" +checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" [[package]] name = "wasm-bindgen-test" +<<<<<<< HEAD version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d92df9d5715606f9e48f85df3b78cb77ae44a2ea9a5f2a785a97bd0066b9300" +======= +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34d1cdc8b98a557f24733d50a1199c4b0635e465eecba9c45b214544da197f64" +>>>>>>> parity/master dependencies = [ "console_error_panic_hook", "js-sys", @@ -10995,9 +11229,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" +<<<<<<< HEAD version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51611ce8e84cba89379d91fc5074bacc5530f69da1c09a2853d906129d12b3b8" +======= +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8fb9c67be7439ee8ab1b7db502a49c05e51e2835b66796c705134d9b8e1a585" +>>>>>>> parity/master dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index b78c4da055801..2e3cff821e02e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,6 @@ members = [ "client/transaction-pool", "client/transaction-pool/graph", "utils/prometheus", - "utils/wasm-builder-runner", "frame/assets", "frame/aura", "frame/atomic-swap", @@ -75,7 +74,6 @@ members = [ "frame/democracy", "frame/elections-phragmen", "frame/elections", - "frame/evm", "frame/example", "frame/example-offchain-worker", "frame/example-parallel", @@ -219,8 +217,6 @@ crossbeam-queue = { opt-level = 3 } crypto-mac = { opt-level = 3 } curve25519-dalek = { opt-level = 3 } ed25519-dalek = { opt-level = 3 } -evm-core = { opt-level = 3 } -evm-runtime = { opt-level = 3 } flate2 = { opt-level = 3 } futures-channel = { opt-level = 3 } hashbrown = { opt-level = 3 } diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index d85de7c840dfd..83481f8c15214 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -9,7 +9,7 @@ use sp_inherents::InherentDataProviders; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; -use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState}; +use sc_finality_grandpa::SharedVoterState; // Our native executor instance. native_executor_instance!( @@ -64,7 +64,6 @@ pub fn new_partial(config: &Configuration) -> Result Result { other: (block_import, grandpa_link), } = new_partial(&config)?; - let finality_proof_provider = - GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); - let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, @@ -99,8 +95,6 @@ pub fn new_full(config: Configuration) -> Result { import_queue, on_demand: None, block_announce_validator_builder: None, - finality_proof_request_builder: None, - finality_proof_provider: Some(finality_proof_provider.clone()), })?; if config.offchain_worker.enabled { @@ -229,6 +223,8 @@ pub fn new_light(config: Configuration) -> Result { let (client, backend, keystore_container, mut task_manager, on_demand) = sc_service::new_light_parts::(&config)?; + let select_chain = sc_consensus::LongestChain::new(backend.clone()); + let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( config.transaction_pool.clone(), config.prometheus_registry(), @@ -237,19 +233,16 @@ pub fn new_light(config: Configuration) -> Result { on_demand.clone(), )); - let grandpa_block_import = sc_finality_grandpa::light_block_import( - client.clone(), backend.clone(), &(client.clone() as Arc<_>), - Arc::new(on_demand.checker().clone()) as Arc<_>, + let (grandpa_block_import, _) = sc_finality_grandpa::block_import( + client.clone(), + &(client.clone() as Arc<_>), + select_chain.clone(), )?; - let finality_proof_import = grandpa_block_import.clone(); - let finality_proof_request_builder = - finality_proof_import.create_finality_proof_request_builder(); let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( sc_consensus_aura::slot_duration(&*client)?, - grandpa_block_import, - None, - Some(Box::new(finality_proof_import)), + grandpa_block_import.clone(), + Some(Box::new(grandpa_block_import)), client.clone(), InherentDataProviders::new(), &task_manager.spawn_handle(), @@ -257,9 +250,6 @@ pub fn new_light(config: Configuration) -> Result { sp_consensus::NeverCanAuthor, )?; - let finality_proof_provider = - GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); - let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, @@ -269,8 +259,6 @@ pub fn new_light(config: Configuration) -> Result { import_queue, on_demand: Some(on_demand.clone()), block_announce_validator_builder: None, - finality_proof_request_builder: Some(finality_proof_request_builder), - finality_proof_provider: Some(finality_proof_provider), })?; if config.offchain_worker.enabled { diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index ed5a114b813f8..f1b15070ddde9 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -48,7 +48,7 @@ hex-literal = { version = "0.3.1", optional = true } template = { version = "2.0.0", default-features = false, path = "../pallets/template", package = "pallet-template" } [build-dependencies] -wasm-builder-runner = { version = "2.0.0", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } +substrate-wasm-builder = { version = "3.0.0", path = "../../../utils/wasm-builder" } [features] default = ["std"] diff --git a/bin/node-template/runtime/build.rs b/bin/node-template/runtime/build.rs index 9654139121f6f..9b53d2457dffd 100644 --- a/bin/node-template/runtime/build.rs +++ b/bin/node-template/runtime/build.rs @@ -1,9 +1,8 @@ -use wasm_builder_runner::WasmBuilder; +use substrate_wasm_builder::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates("2.0.1") .export_heap_base() .import_memory() .build() diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index d67a5bde96457..aadfd931cdb50 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -13,7 +13,7 @@ use sp_runtime::{ transaction_validity::{TransactionValidity, TransactionSource}, }; use sp_runtime::traits::{ - BlakeTwo256, Block as BlockT, IdentityLookup, Verify, IdentifyAccount, NumberFor, Saturating, + BlakeTwo256, Block as BlockT, AccountIdLookup, Verify, IdentifyAccount, NumberFor, Saturating, }; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -148,7 +148,7 @@ impl frame_system::Trait for Runtime { /// The aggregated dispatch type that is available for extrinsics. type Call = Call; /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = IdentityLookup; + type Lookup = AccountIdLookup; /// The index type for storing how many extrinsics an account has signed. type Index = Index; /// The index type for blocks. @@ -293,7 +293,7 @@ construct_runtime!( ); /// The address format for describing accounts. -pub type Address = AccountId; +pub type Address = sp_runtime::MultiAddress; /// Block header type as expected by this runtime. pub type Header = generic::Header; /// Block type as expected by this runtime. diff --git a/bin/node/bench/src/tempdb.rs b/bin/node/bench/src/tempdb.rs index 4020fd1029368..abce7daa518bf 100644 --- a/bin/node/bench/src/tempdb.rs +++ b/bin/node/bench/src/tempdb.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::{io, sync::Arc}; +use std::{io, path::PathBuf, sync::Arc}; use kvdb::{KeyValueDB, DBTransaction}; use kvdb_rocksdb::{DatabaseConfig, Database}; @@ -124,7 +124,7 @@ impl Clone for TempDatabase { .map(|f_result| f_result.expect("failed to read file in seed db") .path() - ).collect(); + ).collect::>(); fs_extra::copy_items( &self_db_files, new_dir.path(), diff --git a/bin/node/browser-testing/Cargo.toml b/bin/node/browser-testing/Cargo.toml index fade57d8124f3..e072607a7b658 100644 --- a/bin/node/browser-testing/Cargo.toml +++ b/bin/node/browser-testing/Cargo.toml @@ -12,9 +12,9 @@ libp2p = { version = "0.30.1", default-features = false } jsonrpc-core = "15.0.0" serde = "1.0.106" serde_json = "1.0.48" -wasm-bindgen = { version = "=0.2.67", features = ["serde-serialize"] } -wasm-bindgen-futures = "0.4.10" -wasm-bindgen-test = "0.3.10" +wasm-bindgen = { version = "=0.2.68", features = ["serde-serialize"] } +wasm-bindgen-futures = "0.4.18" +wasm-bindgen-test = "0.3.18" futures = "0.3.4" node-cli = { path = "../cli", default-features = false, features = ["browser"] , version = "2.0.0"} diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 26a23ce36ecc0..6574ccb733b52 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -41,7 +41,7 @@ hex-literal = "0.3.1" log = "0.4.8" rand = "0.7.2" structopt = { version = "0.3.8", optional = true } -tracing = "0.1.19" +tracing = "0.1.22" parking_lot = "0.10.0" # primitives @@ -102,7 +102,7 @@ node-inspect = { version = "0.8.0", optional = true, path = "../inspect" } # WASM-specific dependencies wasm-bindgen = { version = "0.2.57", optional = true } -wasm-bindgen-futures = { version = "0.4.7", optional = true } +wasm-bindgen-futures = { version = "0.4.18", optional = true } browser-utils = { package = "substrate-browser-utils", path = "../../../utils/browser", optional = true, version = "0.8.0"} [target.'cfg(target_arch="x86_64")'.dependencies] diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 3bc406b84fc67..9d7c9bb1b7a66 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -22,7 +22,6 @@ use std::sync::Arc; use sc_consensus_babe; -use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; use node_primitives::Block; use node_runtime::RuntimeApi; use sc_service::{ @@ -57,10 +56,7 @@ pub fn new_partial(config: &Configuration) -> Result, sc_consensus_babe::BabeLink, ), - ( - grandpa::SharedVoterState, - Arc>, - ), + grandpa::SharedVoterState, ) >, ServiceError> { let (client, backend, keystore_container, task_manager) = @@ -93,7 +89,6 @@ pub fn new_partial(config: &Configuration) -> Result Result Result<( on_demand.clone(), )); - let grandpa_block_import = grandpa::light_block_import( - client.clone(), backend.clone(), &(client.clone() as Arc<_>), - Arc::new(on_demand.checker().clone()), + let (grandpa_block_import, _) = grandpa::block_import( + client.clone(), + &(client.clone() as Arc<_>), + select_chain.clone(), )?; - - let finality_proof_import = grandpa_block_import.clone(); - let finality_proof_request_builder = - finality_proof_import.create_finality_proof_request_builder(); + let justification_import = grandpa_block_import.clone(); let (babe_block_import, babe_link) = sc_consensus_babe::block_import( sc_consensus_babe::Config::get_or_compute(&*client)?, @@ -383,8 +374,7 @@ pub fn new_light_base(config: Configuration) -> Result<( let import_queue = sc_consensus_babe::import_queue( babe_link, babe_block_import, - None, - Some(Box::new(finality_proof_import)), + Some(Box::new(justification_import)), client.clone(), select_chain.clone(), inherent_data_providers.clone(), @@ -393,9 +383,6 @@ pub fn new_light_base(config: Configuration) -> Result<( sp_consensus::NeverCanAuthor, )?; - let finality_proof_provider = - GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); - let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, @@ -405,8 +392,6 @@ pub fn new_light_base(config: Configuration) -> Result<( import_queue, on_demand: Some(on_demand.clone()), block_announce_validator_builder: None, - finality_proof_request_builder: Some(finality_proof_request_builder), - finality_proof_provider: Some(finality_proof_provider), })?; network_starter.start_network(); diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs index 723e3a7e4ba62..236e0a823ac33 100644 --- a/bin/node/executor/tests/basic.rs +++ b/bin/node/executor/tests/basic.rs @@ -27,7 +27,6 @@ use sp_runtime::{ traits::Hash as HashT, transaction_validity::InvalidTransaction, }; -use pallet_contracts::ContractAddressFor; use frame_system::{self, EventRecord, Phase}; use node_runtime::{ @@ -583,10 +582,10 @@ fn deploying_wasm_contract_should_work() { let transfer_code = wat::parse_str(CODE_TRANSFER).unwrap(); let transfer_ch = ::Hashing::hash(&transfer_code); - let addr = ::DetermineContractAddress::contract_address_for( + let addr = pallet_contracts::Module::::contract_address( + &charlie(), &transfer_ch, &[], - &charlie(), ); let subsistence = pallet_contracts::Config::::subsistence_threshold_uncached(); @@ -613,7 +612,8 @@ fn deploying_wasm_contract_should_work() { 1 * DOLLARS + subsistence, 500_000_000, transfer_ch, - Vec::new() + Vec::new(), + Vec::new(), ) ), }, @@ -621,7 +621,7 @@ fn deploying_wasm_contract_should_work() { signed: Some((charlie(), signed_extra(2, 0))), function: Call::Contracts( pallet_contracts::Call::call::( - pallet_indices::address::Address::Id(addr.clone()), + sp_runtime::MultiAddress::Id(addr.clone()), 10, 500_000_000, vec![0x00, 0x01, 0x02, 0x03] diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 2bad2db510be4..eabc9f61c62e5 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -79,7 +79,7 @@ pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0", default-featur pallet-vesting = { version = "2.0.0", default-features = false, path = "../../../frame/vesting" } [build-dependencies] -wasm-builder-runner = { version = "2.0.0", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } +substrate-wasm-builder = { version = "3.0.0", path = "../../../utils/wasm-builder" } [dev-dependencies] sp-io = { version = "2.0.0", path = "../../../primitives/io" } diff --git a/bin/node/runtime/build.rs b/bin/node/runtime/build.rs index 4f111bc993007..8a0b4d7a0c157 100644 --- a/bin/node/runtime/build.rs +++ b/bin/node/runtime/build.rs @@ -15,12 +15,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use wasm_builder_runner::WasmBuilder; +use substrate_wasm_builder::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("2.0.1", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .build() diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index bfa412e882031..4feff5d051abe 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -91,11 +91,11 @@ use sp_runtime::generic::Era; #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +/// Wasm binary unwrapped. If built with `SKIP_WASM_BUILD`, the function panics. #[cfg(feature = "std")] -/// Wasm binary unwrapped. If built with `BUILD_DUMMY_WASM_BINARY`, the function panics. pub fn wasm_binary_unwrap() -> &'static [u8] { WASM_BINARY.expect("Development wasm binary is not available. This means the client is \ - built with `BUILD_DUMMY_WASM_BINARY` flag and it is only usable for \ + built with `SKIP_WASM_BUILD` flag and it is only usable for \ production chains. Please rebuild with the flag disabled.") } @@ -111,7 +111,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_version: 260, impl_version: 0, apis: RUNTIME_API_VERSIONS, - transaction_version: 1, + transaction_version: 2, }; /// Native version. @@ -675,6 +675,10 @@ parameter_types! { pub const RentByteFee: Balance = 4 * MILLICENTS; pub const RentDepositOffset: Balance = 1000 * MILLICENTS; pub const SurchargeReward: Balance = 150 * MILLICENTS; + pub const SignedClaimHandicap: u32 = 2; + pub const MaxDepth: u32 = 32; + pub const StorageSizeOffset: u32 = 8; + pub const MaxValueSize: u32 = 16 * 1024; } impl pallet_contracts::Trait for Runtime { @@ -682,17 +686,15 @@ impl pallet_contracts::Trait for Runtime { type Randomness = RandomnessCollectiveFlip; type Currency = Balances; type Event = Event; - type DetermineContractAddress = pallet_contracts::SimpleAddressDeterminer; - type TrieIdGenerator = pallet_contracts::TrieIdFromParentCounter; type RentPayment = (); - type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap; + type SignedClaimHandicap = SignedClaimHandicap; type TombstoneDeposit = TombstoneDeposit; - type StorageSizeOffset = pallet_contracts::DefaultStorageSizeOffset; + type StorageSizeOffset = StorageSizeOffset; type RentByteFee = RentByteFee; type RentDepositOffset = RentDepositOffset; type SurchargeReward = SurchargeReward; - type MaxDepth = pallet_contracts::DefaultMaxDepth; - type MaxValueSize = pallet_contracts::DefaultMaxValueSize; + type MaxDepth = MaxDepth; + type MaxValueSize = MaxValueSize; type WeightPrice = pallet_transaction_payment::Module; type WeightInfo = pallet_contracts::weights::SubstrateWeight; } @@ -931,7 +933,7 @@ construct_runtime!( ); /// The address format for describing accounts. -pub type Address = ::Source; +pub type Address = sp_runtime::MultiAddress; /// Block header type as expected by this runtime. pub type Header = generic::Header; /// Block type as expected by this runtime. diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index 153a52375c2a9..35af52a2f36c1 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -172,7 +172,7 @@ impl Clone for BenchDb { .map(|f_result| f_result.expect("failed to read file in seed db") .path() - ).collect(); + ).collect::>(); fs_extra::copy_items( &seed_db_files, dir.path(), @@ -317,7 +317,7 @@ impl<'a> Iterator for BlockContentIterator<'a> { BlockType::RandomTransfersKeepAlive => { Call::Balances( BalancesCall::transfer_keep_alive( - pallet_indices::address::Address::Id(receiver), + sp_runtime::MultiAddress::Id(receiver), node_runtime::ExistentialDeposit::get() + 1, ) ) @@ -325,7 +325,7 @@ impl<'a> Iterator for BlockContentIterator<'a> { BlockType::RandomTransfersReaping => { Call::Balances( BalancesCall::transfer( - pallet_indices::address::Address::Id(receiver), + sp_runtime::MultiAddress::Id(receiver), // Transfer so that ending balance would be 1 less than existential deposit // so that we kill the sender account. 100*DOLLARS - (node_runtime::ExistentialDeposit::get() - 1), @@ -591,7 +591,7 @@ impl BenchKeyring { } }).into(); UncheckedExtrinsic { - signature: Some((pallet_indices::address::Address::Id(signed), signature, extra)), + signature: Some((sp_runtime::MultiAddress::Id(signed), signature, extra)), function: payload.0, } } @@ -695,7 +695,6 @@ impl BenchContext { clear_justification_requests: false, needs_justification: false, bad_justification: false, - needs_finality_proof: false, is_new_best: true, } ) diff --git a/bin/node/testing/src/keyring.rs b/bin/node/testing/src/keyring.rs index 3413748563633..f0b8ff707294e 100644 --- a/bin/node/testing/src/keyring.rs +++ b/bin/node/testing/src/keyring.rs @@ -94,7 +94,7 @@ pub fn sign(xt: CheckedExtrinsic, spec_version: u32, tx_version: u32, genesis_ha } }).into(); UncheckedExtrinsic { - signature: Some((pallet_indices::address::Address::Id(signed), signature, extra)), + signature: Some((sp_runtime::MultiAddress::Id(signed), signature, extra)), function: payload.0, } } diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index d0fb5fc3ee0e2..7d770912f271f 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -23,9 +23,7 @@ fnv = "1.0.6" futures = "0.3.1" hash-db = { version = "0.15.2", default-features = false } sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } -hex-literal = "0.3.1" sp-inherents = { version = "2.0.0", default-features = false, path = "../../primitives/inherents" } -sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" } kvdb = "0.7.0" log = "0.4.8" parking_lot = "0.10.0" @@ -39,7 +37,6 @@ sp-api = { version = "2.0.0", path = "../../primitives/api" } sp-utils = { version = "2.0.0", path = "../../primitives/utils" } sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } sp-state-machine = { version = "0.8.0", path = "../../primitives/state-machine" } -sc-telemetry = { version = "2.0.0", path = "../telemetry" } sp-trie = { version = "2.0.0", path = "../../primitives/trie" } sp-storage = { version = "2.0.0", path = "../../primitives/storage" } sp-transaction-pool = { version = "2.0.0", path = "../../primitives/transaction-pool" } diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index 40b929fc8a0f4..fc948de53eb39 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -18,7 +18,6 @@ prost-build = "0.6.1" [dependencies] async-trait = "0.1" -bytes = "0.5.0" codec = { package = "parity-scale-codec", default-features = false, version = "1.3.4" } derive_more = "0.99.2" either = "1.5.3" @@ -30,7 +29,6 @@ prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../.. prost = "0.6.1" rand = "0.7.2" sc-client-api = { version = "2.0.0", path = "../api" } -sc-keystore = { version = "2.0.0", path = "../keystore" } sc-network = { version = "0.8.0", path = "../network" } serde_json = "1.0.41" sp-authority-discovery = { version = "2.0.0", path = "../../primitives/authority-discovery" } diff --git a/client/authority-discovery/src/interval.rs b/client/authority-discovery/src/interval.rs new file mode 100644 index 0000000000000..b3aa5b1c0f678 --- /dev/null +++ b/client/authority-discovery/src/interval.rs @@ -0,0 +1,62 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +use futures::stream::Stream; +use futures::future::FutureExt; +use futures::ready; +use futures_timer::Delay; +use std::pin::Pin; +use std::task::{Context, Poll}; +use std::time::Duration; + +/// Exponentially increasing interval +/// +/// Doubles interval duration on each tick until the configured maximum is reached. +pub struct ExpIncInterval { + max: Duration, + next: Duration, + delay: Delay, +} + +impl ExpIncInterval { + /// Create a new [`ExpIncInterval`]. + pub fn new(start: Duration, max: Duration) -> Self { + let delay = Delay::new(start); + Self { + max, + next: start * 2, + delay, + } + } + + /// Fast forward the exponentially increasing interval to the configured maximum. + pub fn set_to_max(&mut self) { + self.next = self.max; + self.delay = Delay::new(self.next); + } +} + +impl Stream for ExpIncInterval { + type Item = (); + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + ready!(self.delay.poll_unpin(cx)); + self.delay = Delay::new(self.next); + self.next = std::cmp::min(self.max, self.next * 2); + + Poll::Ready(Some(())) + } +} diff --git a/client/authority-discovery/src/lib.rs b/client/authority-discovery/src/lib.rs index 4ee57f31e04a5..41aa01e56bde2 100644 --- a/client/authority-discovery/src/lib.rs +++ b/client/authority-discovery/src/lib.rs @@ -38,50 +38,41 @@ use sp_runtime::traits::Block as BlockT; use sp_api::ProvideRuntimeApi; mod error; +mod interval; mod service; +mod worker; + #[cfg(test)] mod tests; -mod worker; /// Configuration of [`Worker`]. pub struct WorkerConfig { - /// The interval in which the node will publish its own address on the DHT. + /// The maximum interval in which the node will publish its own address on the DHT. /// - /// By default this is set to 12 hours. - pub publish_interval: Duration, - /// The interval in which the node will query the DHT for new entries. + /// By default this is set to 1 hour. + pub max_publish_interval: Duration, + /// The maximum interval in which the node will query the DHT for new entries. /// /// By default this is set to 10 minutes. - pub query_interval: Duration, - /// The time the node will wait before triggering the first DHT query or publish. - /// - /// By default this is set to 30 seconds. - /// - /// This default is based on the rough boostrap time required by libp2p Kademlia. - pub query_start_delay: Duration, - /// The interval in which the worker will instruct the peerset to connect to a random subset - /// of discovered validators. - /// - /// By default this is set to 10 minutes. - pub priority_group_set_interval: Duration, - /// The time the worker will wait after each query interval tick to pass a subset of - /// the cached authority addresses down to the peerset. - /// - /// Be aware that the actual delay will be computed by [`Self::query_start_delay`] + - /// [`Self::priority_group_set_start_delay`] - /// - /// By default this is set to 5 minutes. - pub priority_group_set_offset: Duration, + pub max_query_interval: Duration, } impl Default for WorkerConfig { fn default() -> Self { Self { - publish_interval: Duration::from_secs(12 * 60 * 60), - query_interval: Duration::from_secs(10 * 60), - query_start_delay: Duration::from_secs(30), - priority_group_set_interval: Duration::from_secs(10 * 60), - priority_group_set_offset: Duration::from_secs(5 * 60), + // Kademlia's default time-to-live for Dht records is 36h, republishing records every + // 24h through libp2p-kad. Given that a node could restart at any point in time, one can + // not depend on the republishing process, thus publishing own external addresses should + // happen on an interval < 36h. + max_publish_interval: Duration::from_secs(1 * 60 * 60), + // External addresses of remote authorities can change at any given point in time. The + // interval on which to trigger new queries for the current and next authorities is a trade + // off between efficiency and performance. + // + // Querying 700 [`AuthorityId`]s takes ~8m on the Kusama DHT (16th Nov 2020) when + // comparing `authority_discovery_authority_addresses_requested_total` and + // `authority_discovery_dht_event_received`. + max_query_interval: Duration::from_secs(10 * 60), } } } diff --git a/client/authority-discovery/src/worker.rs b/client/authority-discovery/src/worker.rs index 42ae3a5213f0f..c8e7a9f7aee35 100644 --- a/client/authority-discovery/src/worker.rs +++ b/client/authority-discovery/src/worker.rs @@ -14,17 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use crate::{error::{Error, Result}, ServicetoWorkerMsg}; +use crate::{error::{Error, Result}, interval::ExpIncInterval, ServicetoWorkerMsg}; use std::collections::{HashMap, HashSet}; use std::convert::TryInto; use std::marker::PhantomData; use std::sync::Arc; -use std::time::{Duration, Instant}; +use std::time::Duration; use futures::channel::mpsc; use futures::{FutureExt, Stream, StreamExt, stream::Fuse}; -use futures_timer::Delay; use addr_cache::AddrCache; use async_trait::async_trait; @@ -54,8 +53,6 @@ mod schema { include!(concat!(env!("OUT_DIR"), "/authority_discovery.rs")); } #[cfg(test)] pub mod tests; -type Interval = Box + Unpin + Send + Sync>; - const LOG_TARGET: &'static str = "sub-authority-discovery"; /// Name of the Substrate peerset priority group for authorities discovered through the authority @@ -113,12 +110,12 @@ pub struct Worker { dht_event_rx: DhtEventStream, /// Interval to be proactive, publishing own addresses. - publish_interval: Interval, + publish_interval: ExpIncInterval, /// Interval at which to request addresses of authorities, refilling the pending lookups queue. - query_interval: Interval, + query_interval: ExpIncInterval, /// Interval on which to set the peerset priority group to a new random /// set of addresses. - priority_group_set_interval: Interval, + priority_group_set_interval: ExpIncInterval, /// Queue of throttled lookups pending to be passed to the network. pending_lookups: Vec, @@ -153,31 +150,26 @@ where prometheus_registry: Option, config: crate::WorkerConfig, ) -> Self { - // Kademlia's default time-to-live for Dht records is 36h, republishing - // records every 24h through libp2p-kad. - // Given that a node could restart at any point in time, one can not depend on the - // republishing process, thus publishing own external addresses should happen on an interval - // < 36h. - let publish_interval = interval_at( - Instant::now() + config.query_start_delay, - config.publish_interval, + // When a node starts up publishing and querying might fail due to various reasons, for + // example due to being not yet fully bootstrapped on the DHT. Thus one should retry rather + // sooner than later. On the other hand, a long running node is likely well connected and + // thus timely retries are not needed. For this reasoning use an exponentially increasing + // interval for `publish_interval`, `query_interval` and `priority_group_set_interval` + // instead of a constant interval. + let publish_interval = ExpIncInterval::new( + Duration::from_secs(2), + config.max_publish_interval, ); - - // External addresses of remote authorities can change at any given point in time. The - // interval on which to trigger new queries for the current authorities is a trade off - // between efficiency and performance. - let query_interval_start = Instant::now() + config.query_start_delay; - let query_interval_duration = config.query_interval; - let query_interval = interval_at(query_interval_start, query_interval_duration); - - // Querying 500 [`AuthorityId`]s takes ~1m on the Kusama DHT (10th of August 2020) when - // comparing `authority_discovery_authority_addresses_requested_total` and - // `authority_discovery_dht_event_received`. With that in mind set the peerset priority - // group on the same interval as the [`query_interval`] above, - // just delayed by 5 minutes by default. - let priority_group_set_interval = interval_at( - query_interval_start + config.priority_group_set_offset, - config.priority_group_set_interval, + let query_interval = ExpIncInterval::new( + Duration::from_secs(2), + config.max_query_interval, + ); + let priority_group_set_interval = ExpIncInterval::new( + Duration::from_secs(2), + // Trade-off between node connection churn and connectivity. Using half of + // [`crate::WorkerConfig::max_query_interval`] to update priority group once at the + // beginning and once in the middle of each query interval. + config.max_query_interval / 2, ); let addr_cache = AddrCache::new(); @@ -413,7 +405,7 @@ where } if log_enabled!(log::Level::Debug) { - let hashes = v.iter().map(|(hash, _value)| hash.clone()); + let hashes: Vec<_> = v.iter().map(|(hash, _value)| hash.clone()).collect(); debug!( target: LOG_TARGET, "Value for hash '{:?}' found on Dht.", hashes, @@ -449,6 +441,11 @@ where } }, DhtEvent::ValuePut(hash) => { + // Fast forward the exponentially increasing interval to the configured maximum. In + // case this was the first successful address publishing there is no need for a + // timely retry. + self.publish_interval.set_to_max(); + if let Some(metrics) = &self.metrics { metrics.dht_event_received.with_label_values(&["value_put"]).inc(); } @@ -661,16 +658,6 @@ fn hash_authority_id(id: &[u8]) -> libp2p::kad::record::Key { libp2p::kad::record::Key::new(&libp2p::multihash::Sha2_256::digest(id)) } -fn interval_at(start: Instant, duration: Duration) -> Interval { - let stream = futures::stream::unfold(start, move |next| { - let time_until_next = next.saturating_duration_since(Instant::now()); - - Delay::new(time_until_next).map(move |_| Some(((), next + duration))) - }); - - Box::new(stream) -} - /// Prometheus metrics for a [`Worker`]. #[derive(Clone)] pub(crate) struct Metrics { diff --git a/client/authority-discovery/src/worker/tests.rs b/client/authority-discovery/src/worker/tests.rs index 12adb8f232514..fee861dfeb0c7 100644 --- a/client/authority-discovery/src/worker/tests.rs +++ b/client/authority-discovery/src/worker/tests.rs @@ -37,66 +37,6 @@ use substrate_test_runtime_client::runtime::Block; use super::*; -#[test] -fn interval_at_with_start_now() { - let start = Instant::now(); - - let mut interval = interval_at( - std::time::Instant::now(), - std::time::Duration::from_secs(10), - ); - - futures::executor::block_on(async { - interval.next().await; - }); - - assert!( - Instant::now().saturating_duration_since(start) < Duration::from_secs(1), - "Expected low resolution instant interval to fire within less than a second.", - ); -} - -#[test] -fn interval_at_is_queuing_ticks() { - let start = Instant::now(); - - let interval = interval_at(start, std::time::Duration::from_millis(100)); - - // Let's wait for 200ms, thus 3 elements should be queued up (1st at 0ms, 2nd at 100ms, 3rd - // at 200ms). - std::thread::sleep(Duration::from_millis(200)); - - futures::executor::block_on(async { - interval.take(3).collect::>().await; - }); - - // Make sure we did not wait for more than 300 ms, which would imply that `at_interval` is - // not queuing ticks. - assert!( - Instant::now().saturating_duration_since(start) < Duration::from_millis(300), - "Expect interval to /queue/ events when not polled for a while.", - ); -} - -#[test] -fn interval_at_with_initial_delay() { - let start = Instant::now(); - - let mut interval = interval_at( - std::time::Instant::now() + Duration::from_millis(100), - std::time::Duration::from_secs(10), - ); - - futures::executor::block_on(async { - interval.next().await; - }); - - assert!( - Instant::now().saturating_duration_since(start) > Duration::from_millis(100), - "Expected interval with initial delay not to fire right away.", - ); -} - #[derive(Clone)] pub(crate) struct TestApi { pub(crate) authorities: Vec, diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index 1b1d8921bcfb3..f097d8044f612 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -29,7 +29,6 @@ sc-telemetry = { version = "2.0.0", path = "../telemetry" } sp-transaction-pool = { version = "2.0.0", path = "../../primitives/transaction-pool" } sc-block-builder = { version = "0.8.0", path = "../block-builder" } sc-proposer-metrics = { version = "0.8.0", path = "../proposer-metrics" } -tokio-executor = { version = "0.2.0-alpha.6", features = ["blocking"] } [dev-dependencies] sc-transaction-pool = { version = "2.0.0", path = "../../client/transaction-pool" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 942d30e90db5b..900dddf870189 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -25,7 +25,7 @@ libp2p = "0.30.1" parity-scale-codec = "1.3.0" hex = "0.4.2" rand = "0.7.3" -bip39 = "0.6.0-beta.1" +tiny-bip39 = "0.8.0" serde_json = "1.0.41" sc-keystore = { version = "2.0.0", path = "../keystore" } sp-panic-handler = { version = "2.0.0", path = "../../primitives/panic-handler" } @@ -45,7 +45,7 @@ structopt = "0.3.8" sc-tracing = { version = "2.0.0", path = "../tracing" } chrono = "0.4.10" serde = "1.0.111" -tracing = "0.1.10" +tracing = "0.1.22" tracing-log = "0.1.1" tracing-subscriber = "0.2.10" sc-cli-proc-macro = { version = "2.0.0", path = "./proc-macro" } diff --git a/client/cli/src/params/keystore_params.rs b/client/cli/src/params/keystore_params.rs index 3c04d63144595..2ecd21cb3dd00 100644 --- a/client/cli/src/params/keystore_params.rs +++ b/client/cli/src/params/keystore_params.rs @@ -22,8 +22,7 @@ use std::fs; use std::path::PathBuf; use structopt::StructOpt; use crate::error; -use sp_core::crypto::{SecretString, Zeroize}; -use std::str::FromStr; +use sp_core::crypto::SecretString; /// default sub directory for the key store const DEFAULT_KEYSTORE_CONFIG_PATH: &'static str = "keystore"; @@ -72,21 +71,15 @@ impl KeystoreParams { let password = if self.password_interactive { #[cfg(not(target_os = "unknown"))] { - let mut password = input_keystore_password()?; - let secret = std::str::FromStr::from_str(password.as_str()) - .map_err(|()| "Error reading password")?; - password.zeroize(); - Some(secret) + let password = input_keystore_password()?; + Some(SecretString::new(password)) } #[cfg(target_os = "unknown")] None } else if let Some(ref file) = self.password_filename { - let mut password = fs::read_to_string(file) + let password = fs::read_to_string(file) .map_err(|e| format!("{}", e))?; - let secret = std::str::FromStr::from_str(password.as_str()) - .map_err(|()| "Error reading password")?; - password.zeroize(); - Some(secret) + Some(SecretString::new(password)) } else { self.password.clone() }; @@ -104,10 +97,8 @@ impl KeystoreParams { let (password_interactive, password) = (self.password_interactive, self.password.clone()); let pass = if password_interactive { - let mut password = rpassword::read_password_from_tty(Some("Key password: "))?; - let pass = Some(FromStr::from_str(&password).map_err(|()| "Error reading password")?); - password.zeroize(); - pass + let password = rpassword::read_password_from_tty(Some("Key password: "))?; + Some(SecretString::new(password)) } else { password }; diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 97bfb217b9396..246b39771277d 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -47,7 +47,7 @@ use sp_consensus::{ BlockOrigin, Error as ConsensusError, SelectChain, SlotData, BlockCheckParams, ImportResult }; use sp_consensus::import_queue::{ - Verifier, BasicQueue, DefaultImportQueue, BoxJustificationImport, BoxFinalityProofImport, + Verifier, BasicQueue, DefaultImportQueue, BoxJustificationImport, }; use sc_client_api::{backend::AuxStore, BlockOf}; use sp_blockchain::{ @@ -836,7 +836,6 @@ pub fn import_queue( slot_duration: SlotDuration, block_import: I, justification_import: Option>, - finality_proof_import: Option>, client: Arc, inherent_data_providers: InherentDataProviders, spawner: &S, @@ -868,7 +867,6 @@ pub fn import_queue( verifier, Box::new(block_import), justification_import, - finality_proof_import, spawner, registry, )) diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index c672440d114b5..3f2a583482afb 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -79,9 +79,7 @@ use std::{ any::Any, borrow::Cow, convert::TryInto, }; use sp_consensus::{ImportResult, CanAuthorWith}; -use sp_consensus::import_queue::{ - BoxJustificationImport, BoxFinalityProofImport, -}; +use sp_consensus::import_queue::BoxJustificationImport; use sp_core::crypto::Public; use sp_application_crypto::AppKey; use sp_keystore::{SyncCryptoStorePtr, SyncCryptoStore}; @@ -1484,7 +1482,6 @@ pub fn import_queue( babe_link: BabeLink, block_import: Inner, justification_import: Option>, - finality_proof_import: Option>, client: Arc, select_chain: SelectChain, inherent_data_providers: InherentDataProviders, @@ -1516,7 +1513,6 @@ pub fn import_queue( verifier, Box::new(block_import), justification_import, - finality_proof_import, spawner, registry, )) diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index b31699d13e0c8..6e0536c85ced7 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -37,11 +37,11 @@ use sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging; use sc_block_builder::{BlockBuilder, BlockBuilderProvider}; use sp_consensus::{ NoNetwork as DummyOracle, Proposal, RecordProof, AlwaysCanAuthor, - import_queue::{BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport}, + import_queue::{BoxBlockImport, BoxJustificationImport}, }; use sc_network_test::*; use sc_network_test::{Block as TestBlock, PeersClient}; -use sc_network::config::{BoxFinalityProofRequestBuilder, ProtocolConfig}; +use sc_network::config::ProtocolConfig; use sp_runtime::{generic::DigestItem, traits::{Block as BlockT, DigestFor}}; use sc_client_api::{BlockchainEvents, backend::TransactionFor}; use log::debug; @@ -272,8 +272,6 @@ impl TestNetFactory for BabeTestNet { -> ( BlockImportAdapter, Option>, - Option>, - Option>, Option, ) { @@ -295,8 +293,6 @@ impl TestNetFactory for BabeTestNet { ( BlockImportAdapter::new_full(block_import), None, - None, - None, Some(PeerData { link, inherent_data_providers, block_import: data_block_import }), ) } diff --git a/client/consensus/manual-seal/src/lib.rs b/client/consensus/manual-seal/src/lib.rs index d025d6aaf689f..5a1cd0f79b47d 100644 --- a/client/consensus/manual-seal/src/lib.rs +++ b/client/consensus/manual-seal/src/lib.rs @@ -84,7 +84,6 @@ pub fn import_queue( ManualSealVerifier, block_import, None, - None, spawner, registry, ) @@ -349,7 +348,6 @@ mod tests { clear_justification_requests: false, needs_justification: false, bad_justification: false, - needs_finality_proof: false, is_new_best: true, } } @@ -416,7 +414,6 @@ mod tests { clear_justification_requests: false, needs_justification: false, bad_justification: false, - needs_finality_proof: false, is_new_best: true, } } @@ -494,7 +491,6 @@ mod tests { clear_justification_requests: false, needs_justification: false, bad_justification: false, - needs_finality_proof: false, is_new_best: true } } diff --git a/client/consensus/pow/src/lib.rs b/client/consensus/pow/src/lib.rs index b73b9aa91f802..e353ed6358a00 100644 --- a/client/consensus/pow/src/lib.rs +++ b/client/consensus/pow/src/lib.rs @@ -56,7 +56,7 @@ use sp_consensus::{ BlockCheckParams, ImportResult, }; use sp_consensus::import_queue::{ - BoxBlockImport, BasicQueue, Verifier, BoxJustificationImport, BoxFinalityProofImport, + BoxBlockImport, BasicQueue, Verifier, BoxJustificationImport, }; use codec::{Encode, Decode}; use prometheus_endpoint::Registry; @@ -503,7 +503,6 @@ pub type PowImportQueue = BasicQueue; pub fn import_queue( block_import: BoxBlockImport, justification_import: Option>, - finality_proof_import: Option>, algorithm: Algorithm, inherent_data_providers: InherentDataProviders, spawner: &impl sp_core::traits::SpawnNamed, @@ -524,7 +523,6 @@ pub fn import_queue( verifier, block_import, justification_import, - finality_proof_import, spawner, registry, )) diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index b88e8926be141..803a49d1deaaf 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -48,7 +48,7 @@ test-case = "0.3.3" sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } sp-tracing = { version = "2.0.0", path = "../../primitives/tracing" } sc-tracing = { version = "2.0.0", path = "../tracing" } -tracing = "0.1.19" +tracing = "0.1.22" tracing-subscriber = "0.2.10" [features] diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index ba23e31febee5..1a898b92ca9ab 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -22,7 +22,7 @@ sp-std = { version = "2.0.0", default-features = false, path = "../../../primiti sp-tasks = { version = "2.0.0", default-features = false, path = "../../../primitives/tasks" } [build-dependencies] -wasm-builder-runner = { version = "2.0.0", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } +substrate-wasm-builder = { version = "3.0.0", path = "../../../utils/wasm-builder" } [features] default = [ "std" ] diff --git a/client/executor/runtime-test/build.rs b/client/executor/runtime-test/build.rs index bc07db900c31e..a83de21db7f0f 100644 --- a/client/executor/runtime-test/build.rs +++ b/client/executor/runtime-test/build.rs @@ -14,13 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use wasm_builder_runner::WasmBuilder; +use substrate_wasm_builder::WasmBuilder; fn main() { // regular build WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("2.0.1", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .build(); @@ -28,10 +27,9 @@ fn main() { // and building with tracing activated WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("2.0.1", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .set_file_name("wasm_binary_with_tracing.rs") - .append_to_rust_flags("--cfg feature=\\\"with-tracing\\\"") + .append_to_rust_flags(r#"--cfg feature="with-tracing""#) .build(); } diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs index 404530c1c3ebf..f4cef65b629aa 100644 --- a/client/executor/runtime-test/src/lib.rs +++ b/client/executor/runtime-test/src/lib.rs @@ -4,8 +4,8 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +/// Wasm binary unwrapped. If built with `SKIP_WASM_BUILD`, the function panics. #[cfg(feature = "std")] -/// Wasm binary unwrapped. If built with `BUILD_DUMMY_WASM_BINARY`, the function panics. pub fn wasm_binary_unwrap() -> &'static [u8] { WASM_BINARY.expect("Development wasm binary is not available. Testing is only \ supported with the flag disabled.") diff --git a/client/finality-grandpa/src/aux_schema.rs b/client/finality-grandpa/src/aux_schema.rs index 4ed96d058ac6b..97041f4081a72 100644 --- a/client/finality-grandpa/src/aux_schema.rs +++ b/client/finality-grandpa/src/aux_schema.rs @@ -17,7 +17,6 @@ //! Schema for stuff in the aux-db. use std::fmt::Debug; -use std::sync::Arc; use parity_scale_codec::{Encode, Decode}; use sc_client_api::backend::AuxStore; use sp_blockchain::{Result as ClientResult, Error as ClientError}; @@ -28,7 +27,6 @@ use log::{info, warn}; use sp_finality_grandpa::{AuthorityList, SetId, RoundNumber}; use crate::authorities::{AuthoritySet, SharedAuthoritySet, PendingChange, DelayKind}; -use crate::consensus_changes::{SharedConsensusChanges, ConsensusChanges}; use crate::environment::{ CompletedRound, CompletedRounds, CurrentRounds, HasVoted, SharedVoterSetState, VoterSetState, }; @@ -38,7 +36,6 @@ const VERSION_KEY: &[u8] = b"grandpa_schema_version"; const SET_STATE_KEY: &[u8] = b"grandpa_completed_round"; const CONCLUDED_ROUNDS: &[u8] = b"grandpa_concluded_rounds"; const AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters"; -const CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes"; const CURRENT_VERSION: u32 = 2; @@ -122,7 +119,6 @@ pub(crate) fn load_decode(backend: &B, key: &[u8]) -> Cl /// Persistent data kept between runs. pub(crate) struct PersistentData { pub(crate) authority_set: SharedAuthoritySet>, - pub(crate) consensus_changes: SharedConsensusChanges>, pub(crate) set_state: SharedVoterSetState, } @@ -272,8 +268,6 @@ pub(crate) fn load_persistent( G: FnOnce() -> ClientResult, { let version: Option = load_decode(backend, VERSION_KEY)?; - let consensus_changes = load_decode(backend, CONSENSUS_CHANGES_KEY)? - .unwrap_or_else(ConsensusChanges::>::empty); let make_genesis_round = move || RoundState::genesis((genesis_hash, genesis_number)); @@ -282,7 +276,6 @@ pub(crate) fn load_persistent( if let Some((new_set, set_state)) = migrate_from_version0::(backend, &make_genesis_round)? { return Ok(PersistentData { authority_set: new_set.into(), - consensus_changes: Arc::new(consensus_changes.into()), set_state: set_state.into(), }); } @@ -291,7 +284,6 @@ pub(crate) fn load_persistent( if let Some((new_set, set_state)) = migrate_from_version1::(backend, &make_genesis_round)? { return Ok(PersistentData { authority_set: new_set.into(), - consensus_changes: Arc::new(consensus_changes.into()), set_state: set_state.into(), }); } @@ -321,7 +313,6 @@ pub(crate) fn load_persistent( return Ok(PersistentData { authority_set: set.into(), - consensus_changes: Arc::new(consensus_changes.into()), set_state: set_state.into(), }); } @@ -359,7 +350,6 @@ pub(crate) fn load_persistent( Ok(PersistentData { authority_set: genesis_set.into(), set_state: genesis_state.into(), - consensus_changes: Arc::new(consensus_changes.into()), }) } @@ -421,18 +411,6 @@ pub(crate) fn write_concluded_round( backend.insert_aux(&[(&key[..], round_data.encode().as_slice())], &[]) } -/// Update the consensus changes. -pub(crate) fn update_consensus_changes( - set: &ConsensusChanges, - write_aux: F -) -> R where - H: Encode + Clone, - N: Encode + Clone, - F: FnOnce(&[(&'static [u8], &[u8])]) -> R, -{ - write_aux(&[(CONSENSUS_CHANGES_KEY, set.encode().as_slice())]) -} - #[cfg(test)] pub(crate) fn load_authorities(backend: &B) -> Option> { diff --git a/client/finality-grandpa/src/communication/mod.rs b/client/finality-grandpa/src/communication/mod.rs index 3daffcb9f2522..038d82a8cdc3b 100644 --- a/client/finality-grandpa/src/communication/mod.rs +++ b/client/finality-grandpa/src/communication/mod.rs @@ -68,7 +68,6 @@ mod periodic; #[cfg(test)] pub(crate) mod tests; -pub use sp_finality_grandpa::GRANDPA_ENGINE_ID; pub const GRANDPA_PROTOCOL_NAME: &'static str = "/paritytech/grandpa/1"; // cost scalars for reporting peers. @@ -215,7 +214,6 @@ impl> NetworkBridge { let validator = Arc::new(validator); let gossip_engine = Arc::new(Mutex::new(GossipEngine::new( service.clone(), - GRANDPA_ENGINE_ID, GRANDPA_PROTOCOL_NAME, validator.clone() ))); diff --git a/client/finality-grandpa/src/communication/tests.rs b/client/finality-grandpa/src/communication/tests.rs index 1a773acd6d0fb..e1685256f7b8d 100644 --- a/client/finality-grandpa/src/communication/tests.rs +++ b/client/finality-grandpa/src/communication/tests.rs @@ -24,10 +24,11 @@ use sc_network_gossip::Validator; use std::sync::Arc; use sp_keyring::Ed25519Keyring; use parity_scale_codec::Encode; -use sp_runtime::{ConsensusEngineId, traits::NumberFor}; +use sp_runtime::traits::NumberFor; use std::{borrow::Cow, pin::Pin, task::{Context, Poll}}; +use crate::communication::GRANDPA_PROTOCOL_NAME; use crate::environment::SharedVoterSetState; -use sp_finality_grandpa::{AuthorityList, GRANDPA_ENGINE_ID}; +use sp_finality_grandpa::AuthorityList; use super::gossip::{self, GossipValidator}; use super::{VoterSet, Round, SetId}; @@ -57,11 +58,11 @@ impl sc_network_gossip::Network for TestNetwork { fn disconnect_peer(&self, _: PeerId) {} - fn write_notification(&self, who: PeerId, _: ConsensusEngineId, message: Vec) { + fn write_notification(&self, who: PeerId, _: Cow<'static, str>, message: Vec) { let _ = self.sender.unbounded_send(Event::WriteNotification(who, message)); } - fn register_notifications_protocol(&self, _: ConsensusEngineId, _: Cow<'static, str>) {} + fn register_notifications_protocol(&self, _: Cow<'static, str>) {} fn announce(&self, block: Hash, _associated_data: Vec) { let _ = self.sender.unbounded_send(Event::Announce(block)); @@ -86,7 +87,7 @@ impl sc_network_gossip::ValidatorContext for TestNetwork { >::write_notification( self, who.clone(), - GRANDPA_ENGINE_ID, + GRANDPA_PROTOCOL_NAME.into(), data, ); } @@ -287,20 +288,20 @@ fn good_commit_leads_to_relay() { // Add the sending peer and send the commit let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened { remote: sender_id.clone(), - engine_id: GRANDPA_ENGINE_ID, + protocol: GRANDPA_PROTOCOL_NAME.into(), role: ObservedRole::Full, }); let _ = sender.unbounded_send(NetworkEvent::NotificationsReceived { remote: sender_id.clone(), - messages: vec![(GRANDPA_ENGINE_ID, commit_to_send.clone().into())], + messages: vec![(GRANDPA_PROTOCOL_NAME.into(), commit_to_send.clone().into())], }); // Add a random peer which will be the recipient of this message let receiver_id = sc_network::PeerId::random(); let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened { remote: receiver_id.clone(), - engine_id: GRANDPA_ENGINE_ID, + protocol: GRANDPA_PROTOCOL_NAME.into(), role: ObservedRole::Full, }); @@ -319,7 +320,7 @@ fn good_commit_leads_to_relay() { sender.unbounded_send(NetworkEvent::NotificationsReceived { remote: receiver_id, - messages: vec![(GRANDPA_ENGINE_ID, msg.encode().into())], + messages: vec![(GRANDPA_PROTOCOL_NAME.into(), msg.encode().into())], }) }; @@ -434,12 +435,12 @@ fn bad_commit_leads_to_report() { Event::EventStream(sender) => { let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened { remote: sender_id.clone(), - engine_id: GRANDPA_ENGINE_ID, + protocol: GRANDPA_PROTOCOL_NAME.into(), role: ObservedRole::Full, }); let _ = sender.unbounded_send(NetworkEvent::NotificationsReceived { remote: sender_id.clone(), - messages: vec![(GRANDPA_ENGINE_ID, commit_to_send.clone().into())], + messages: vec![(GRANDPA_PROTOCOL_NAME.into(), commit_to_send.clone().into())], }); true diff --git a/client/finality-grandpa/src/consensus_changes.rs b/client/finality-grandpa/src/consensus_changes.rs deleted file mode 100644 index 1ce7b551d0d7c..0000000000000 --- a/client/finality-grandpa/src/consensus_changes.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate 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. - -// Substrate 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 Substrate. If not, see . - -use std::sync::Arc; -use parity_scale_codec::{Encode, Decode}; - -/// Consensus-related data changes tracker. -#[derive(Clone, Debug, Encode, Decode)] -pub(crate) struct ConsensusChanges { - pending_changes: Vec<(N, H)>, -} - -impl ConsensusChanges { - /// Create empty consensus changes. - pub(crate) fn empty() -> Self { - ConsensusChanges { pending_changes: Vec::new(), } - } -} - -impl ConsensusChanges { - - /// Returns reference to all pending changes. - pub fn pending_changes(&self) -> &[(N, H)] { - &self.pending_changes - } - - /// Note unfinalized change of consensus-related data. - pub(crate) fn note_change(&mut self, at: (N, H)) { - let idx = self.pending_changes - .binary_search_by_key(&at.0, |change| change.0) - .unwrap_or_else(|i| i); - self.pending_changes.insert(idx, at); - } - - /// Finalize all pending consensus changes that are finalized by given block. - /// Returns true if there any changes were finalized. - pub(crate) fn finalize ::sp_blockchain::Result>>( - &mut self, - block: (N, H), - canonical_at_height: F, - ) -> ::sp_blockchain::Result<(bool, bool)> { - let (split_idx, has_finalized_changes) = self.pending_changes.iter() - .enumerate() - .take_while(|(_, &(at_height, _))| at_height <= block.0) - .fold((None, Ok(false)), |(_, has_finalized_changes), (idx, ref at)| - ( - Some(idx), - has_finalized_changes - .and_then(|has_finalized_changes| if has_finalized_changes { - Ok(has_finalized_changes) - } else { - canonical_at_height(at.0).map(|can_hash| Some(at.1) == can_hash) - }), - )); - - let altered_changes = split_idx.is_some(); - if let Some(split_idx) = split_idx { - self.pending_changes = self.pending_changes.split_off(split_idx + 1); - } - has_finalized_changes.map(|has_finalized_changes| (altered_changes, has_finalized_changes)) - } -} - -/// Thread-safe consensus changes tracker reference. -pub(crate) type SharedConsensusChanges = Arc>>; diff --git a/client/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs index 9b3a656d0cd8f..790be2a221788 100644 --- a/client/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -34,10 +34,10 @@ use finality_grandpa::{ BlockNumberOps, Error as GrandpaError, round::State as RoundState, voter, voter_set::VoterSet, }; -use sp_blockchain::{HeaderBackend, HeaderMetadata, Error as ClientError}; +use sp_blockchain::HeaderMetadata; use sp_runtime::generic::BlockId; use sp_runtime::traits::{ - Block as BlockT, Header as HeaderT, NumberFor, One, Zero, + Block as BlockT, Header as HeaderT, NumberFor, Zero, }; use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; @@ -50,7 +50,6 @@ use sp_consensus::SelectChain; use crate::authorities::{AuthoritySet, SharedAuthoritySet}; use crate::communication::Network as NetworkT; -use crate::consensus_changes::SharedConsensusChanges; use crate::notification::GrandpaJustificationSender; use crate::justification::GrandpaJustification; use crate::until_imported::UntilVoteTargetImported; @@ -440,7 +439,6 @@ pub(crate) struct Environment, SC, pub(crate) voters: Arc>, pub(crate) config: Config, pub(crate) authority_set: SharedAuthoritySet>, - pub(crate) consensus_changes: SharedConsensusChanges>, pub(crate) network: crate::communication::NetworkBridge, pub(crate) set_id: SetId, pub(crate) voter_set_state: SharedVoterSetState, @@ -1115,7 +1113,6 @@ where finalize_block( self.client.clone(), &self.authority_set, - &self.consensus_changes, Some(self.config.justification_period.into()), hash, number, @@ -1180,7 +1177,6 @@ impl From> for JustificationOrCommit< pub(crate) fn finalize_block( client: Arc, authority_set: &SharedAuthoritySet>, - consensus_changes: &SharedConsensusChanges>, justification_period: Option>, hash: Block::Hash, number: NumberFor, @@ -1215,15 +1211,6 @@ where // FIXME #1483: clone only when changed let old_authority_set = authority_set.clone(); - // holds the old consensus changes in case it is changed below, needed for - // reverting in case of failure - let mut old_consensus_changes = None; - - let mut consensus_changes = consensus_changes.lock(); - let canon_at_height = |canon_number| { - // "true" because the block is finalized - canonical_at_height(&*client, (hash, number), true, canon_number) - }; let update_res: Result<_, Error> = client.lock_import_and_run(|import_op| { let status = authority_set.apply_standard_changes( @@ -1233,26 +1220,6 @@ where initial_sync, ).map_err(|e| Error::Safety(e.to_string()))?; - // check if this is this is the first finalization of some consensus changes - let (alters_consensus_changes, finalizes_consensus_changes) = consensus_changes - .finalize((number, hash), &canon_at_height)?; - - if alters_consensus_changes { - old_consensus_changes = Some(consensus_changes.clone()); - - let write_result = crate::aux_schema::update_consensus_changes( - &*consensus_changes, - |insert| apply_aux(import_op, insert, &[]), - ); - - if let Err(e) = write_result { - warn!(target: "afg", "Failed to write updated consensus changes to disk. Bailing."); - warn!(target: "afg", "Node is in a potentially inconsistent state."); - - return Err(e.into()); - } - } - // send a justification notification if a sender exists and in case of error log it. fn notify_justification( justification_sender: Option<&GrandpaJustificationSender>, @@ -1280,9 +1247,7 @@ where let mut justification_required = // justification is always required when block that enacts new authorities // set is finalized - status.new_set_block.is_some() || - // justification is required when consensus changes are finalized - finalizes_consensus_changes; + status.new_set_block.is_some(); // justification is required every N blocks to be able to prove blocks // finalization to remote nodes @@ -1387,57 +1352,7 @@ where Err(e) => { *authority_set = old_authority_set; - if let Some(old_consensus_changes) = old_consensus_changes { - *consensus_changes = old_consensus_changes; - } - Err(CommandOrError::Error(e)) } } } - -/// Using the given base get the block at the given height on this chain. The -/// target block must be an ancestor of base, therefore `height <= base.height`. -pub(crate) fn canonical_at_height>( - provider: &C, - base: (Block::Hash, NumberFor), - base_is_canonical: bool, - height: NumberFor, -) -> Result, ClientError> { - if height > base.1 { - return Ok(None); - } - - if height == base.1 { - if base_is_canonical { - return Ok(Some(base.0)); - } else { - return Ok(provider.hash(height).unwrap_or(None)); - } - } else if base_is_canonical { - return Ok(provider.hash(height).unwrap_or(None)); - } - - let one = NumberFor::::one(); - - // start by getting _canonical_ block with number at parent position and then iterating - // backwards by hash. - let mut current = match provider.header(BlockId::Number(base.1 - one))? { - Some(header) => header, - _ => return Ok(None), - }; - - // we've already checked that base > height above. - let mut steps = base.1 - height - one; - - while steps > NumberFor::::zero() { - current = match provider.header(BlockId::Hash(*current.parent_hash()))? { - Some(header) => header, - _ => return Ok(None), - }; - - steps -= one; - } - - Ok(Some(current.hash())) -} diff --git a/client/finality-grandpa/src/finality_proof.rs b/client/finality-grandpa/src/finality_proof.rs index 33dd69cc11d6e..bf367ab3f4a55 100644 --- a/client/finality-grandpa/src/finality_proof.rs +++ b/client/finality-grandpa/src/finality_proof.rs @@ -16,6 +16,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +// NOTE: should be removed with: https://github.com/paritytech/substrate/pull/7339 +#![allow(dead_code)] + //! GRANDPA block finality proof generation and check. //! //! Finality of block B is proved by providing: @@ -37,7 +40,7 @@ //! of the U) could be returned. use std::sync::Arc; -use log::{trace, warn}; +use log::trace; use sp_blockchain::{Backend as BlockchainBackend, Error as ClientError, Result as ClientResult}; use sc_client_api::{ @@ -206,34 +209,6 @@ impl FinalityProofProvider } } -impl sc_network::config::FinalityProofProvider for FinalityProofProvider - where - Block: BlockT, - NumberFor: BlockNumberOps, - B: Backend + Send + Sync + 'static, -{ - fn prove_finality( - &self, - for_block: Block::Hash, - request: &[u8], - ) -> Result>, ClientError> { - let request: FinalityProofRequest = Decode::decode(&mut &request[..]) - .map_err(|e| { - warn!(target: "afg", "Unable to decode finality proof request: {}", e.what()); - ClientError::Backend("Invalid finality proof request".to_string()) - })?; - match request { - FinalityProofRequest::Original(request) => prove_finality::<_, _, GrandpaJustification>( - &*self.backend.blockchain(), - &*self.authority_provider, - request.authorities_set_id, - request.last_finalized, - for_block, - ), - } - } -} - /// The effects of block finality. #[derive(Debug, PartialEq)] pub struct FinalityEffects { @@ -290,14 +265,6 @@ struct OriginalFinalityProofRequest { pub last_finalized: H, } -/// Prepare data blob associated with finality proof request. -pub(crate) fn make_finality_proof_request(last_finalized: H, authorities_set_id: u64) -> Vec { - FinalityProofRequest::Original(OriginalFinalityProofRequest { - authorities_set_id, - last_finalized, - }).encode() -} - /// Prepare proof-of-finality for the best possible block in the range: (begin; end]. /// /// It is assumed that the caller already have a proof-of-finality for the block 'begin'. diff --git a/client/finality-grandpa/src/import.rs b/client/finality-grandpa/src/import.rs index 04df95a3187e1..89f9d0c16ad7c 100644 --- a/client/finality-grandpa/src/import.rs +++ b/client/finality-grandpa/src/import.rs @@ -41,7 +41,6 @@ use sp_runtime::traits::{ use crate::{Error, CommandOrError, NewAuthoritySet, VoterCommand}; use crate::authorities::{AuthoritySet, SharedAuthoritySet, DelayKind, PendingChange}; -use crate::consensus_changes::SharedConsensusChanges; use crate::environment::finalize_block; use crate::justification::GrandpaJustification; use crate::notification::GrandpaJustificationSender; @@ -61,7 +60,6 @@ pub struct GrandpaBlockImport { select_chain: SC, authority_set: SharedAuthoritySet>, send_voter_commands: TracingUnboundedSender>>, - consensus_changes: SharedConsensusChanges>, authority_set_hard_forks: HashMap>>, justification_sender: GrandpaJustificationSender, _phantom: PhantomData, @@ -76,7 +74,6 @@ impl Clone for select_chain: self.select_chain.clone(), authority_set: self.authority_set.clone(), send_voter_commands: self.send_voter_commands.clone(), - consensus_changes: self.consensus_changes.clone(), authority_set_hard_forks: self.authority_set_hard_forks.clone(), justification_sender: self.justification_sender.clone(), _phantom: PhantomData, @@ -439,7 +436,6 @@ impl BlockImport // we don't want to finalize on `inner.import_block` let mut justification = block.justification.take(); - let enacts_consensus_change = !new_cache.is_empty(); let import_result = (&*self.inner).import_block(block, new_cache); let mut imported_aux = { @@ -517,7 +513,7 @@ impl BlockImport ); import_res.unwrap_or_else(|err| { - if needs_justification || enacts_consensus_change { + if needs_justification { debug!(target: "afg", "Imported block #{} that enacts authority set change with \ invalid justification: {:?}, requesting justification from peers.", number, err); imported_aux.bad_justification = true; @@ -535,12 +531,6 @@ impl BlockImport imported_aux.needs_justification = true; } - - // we have imported block with consensus data changes, but without justification - // => remember to create justification when next block will be finalized - if enacts_consensus_change { - self.consensus_changes.lock().note_change((number, hash)); - } } } @@ -561,7 +551,6 @@ impl GrandpaBlockImport>, send_voter_commands: TracingUnboundedSender>>, - consensus_changes: SharedConsensusChanges>, authority_set_hard_forks: Vec<(SetId, PendingChange>)>, justification_sender: GrandpaJustificationSender, ) -> GrandpaBlockImport { @@ -605,7 +594,6 @@ impl GrandpaBlockImport. - -use std::collections::HashMap; -use std::sync::Arc; -use log::{info, trace, warn}; -use parking_lot::RwLock; -use sc_client_api::backend::{AuxStore, Backend, Finalizer, TransactionFor}; -use sp_blockchain::{HeaderBackend, Error as ClientError, well_known_cache_keys}; -use parity_scale_codec::{Encode, Decode}; -use sp_consensus::{ - import_queue::Verifier, - BlockOrigin, BlockImport, FinalityProofImport, BlockImportParams, ImportResult, ImportedAux, - BlockCheckParams, Error as ConsensusError, -}; -use sc_network::config::{BoxFinalityProofRequestBuilder, FinalityProofRequestBuilder}; -use sp_runtime::Justification; -use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT, DigestFor}; -use sp_finality_grandpa::{self, AuthorityList}; -use sp_runtime::generic::BlockId; - -use crate::GenesisAuthoritySetProvider; -use crate::aux_schema::load_decode; -use crate::consensus_changes::ConsensusChanges; -use crate::environment::canonical_at_height; -use crate::finality_proof::{ - AuthoritySetForFinalityChecker, ProvableJustification, make_finality_proof_request, -}; -use crate::justification::GrandpaJustification; - -/// LightAuthoritySet is saved under this key in aux storage. -const LIGHT_AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters"; -/// ConsensusChanges is saver under this key in aux storage. -const LIGHT_CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes"; - -/// Create light block importer. -pub fn light_block_import( - client: Arc, - backend: Arc, - genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, - authority_set_provider: Arc>, -) -> Result, ClientError> - where - BE: Backend, - Client: crate::ClientForGrandpa, -{ - let info = client.info(); - let import_data = load_aux_import_data( - info.finalized_hash, - &*client, - genesis_authorities_provider, - )?; - Ok(GrandpaLightBlockImport { - client, - backend, - authority_set_provider, - data: Arc::new(RwLock::new(import_data)), - }) -} - -/// A light block-import handler for GRANDPA. -/// -/// It is responsible for: -/// - checking GRANDPA justifications; -/// - fetching finality proofs for blocks that are enacting consensus changes. -pub struct GrandpaLightBlockImport { - client: Arc, - backend: Arc, - authority_set_provider: Arc>, - data: Arc>>, -} - -impl Clone for GrandpaLightBlockImport { - fn clone(&self) -> Self { - GrandpaLightBlockImport { - client: self.client.clone(), - backend: self.backend.clone(), - authority_set_provider: self.authority_set_provider.clone(), - data: self.data.clone(), - } - } -} - -/// Mutable data of light block importer. -struct LightImportData { - last_finalized: Block::Hash, - authority_set: LightAuthoritySet, - consensus_changes: ConsensusChanges>, -} - -/// Latest authority set tracker. -#[derive(Debug, Encode, Decode)] -struct LightAuthoritySet { - set_id: u64, - authorities: AuthorityList, -} - -impl GrandpaLightBlockImport { - /// Create finality proof request builder. - pub fn create_finality_proof_request_builder(&self) -> BoxFinalityProofRequestBuilder { - Box::new(GrandpaFinalityProofRequestBuilder(self.data.clone())) as _ - } -} - -impl BlockImport - for GrandpaLightBlockImport where - NumberFor: finality_grandpa::BlockNumberOps, - DigestFor: Encode, - BE: Backend + 'static, - for<'a> &'a Client: - HeaderBackend - + BlockImport> - + Finalizer - + AuxStore, -{ - type Error = ConsensusError; - type Transaction = TransactionFor; - - fn import_block( - &mut self, - block: BlockImportParams, - new_cache: HashMap>, - ) -> Result { - do_import_block::<_, _, _, GrandpaJustification>( - &*self.client, &mut *self.data.write(), block, new_cache - ) - } - - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - self.client.check_block(block) - } -} - -impl FinalityProofImport - for GrandpaLightBlockImport where - NumberFor: finality_grandpa::BlockNumberOps, - DigestFor: Encode, - BE: Backend + 'static, - for<'a> &'a Client: - HeaderBackend - + BlockImport> - + Finalizer - + AuxStore, -{ - type Error = ConsensusError; - - fn on_start(&mut self) -> Vec<(Block::Hash, NumberFor)> { - let mut out = Vec::new(); - let chain_info = (&*self.client).info(); - - let data = self.data.read(); - for (pending_number, pending_hash) in data.consensus_changes.pending_changes() { - if *pending_number > chain_info.finalized_number - && *pending_number <= chain_info.best_number - { - out.push((*pending_hash, *pending_number)); - } - } - - out - } - - fn import_finality_proof( - &mut self, - hash: Block::Hash, - number: NumberFor, - finality_proof: Vec, - verifier: &mut dyn Verifier, - ) -> Result<(Block::Hash, NumberFor), Self::Error> { - do_import_finality_proof::<_, _, _, GrandpaJustification>( - &*self.client, - self.backend.clone(), - &*self.authority_set_provider, - &mut *self.data.write(), - hash, - number, - finality_proof, - verifier, - ) - } -} - -impl LightAuthoritySet { - /// Get a genesis set with given authorities. - pub fn genesis(initial: AuthorityList) -> Self { - LightAuthoritySet { - set_id: sp_finality_grandpa::SetId::default(), - authorities: initial, - } - } - - /// Get latest set id. - pub fn set_id(&self) -> u64 { - self.set_id - } - - /// Get latest authorities set. - pub fn authorities(&self) -> AuthorityList { - self.authorities.clone() - } - - /// Set new authorities set. - pub fn update(&mut self, set_id: u64, authorities: AuthorityList) { - self.set_id = set_id; - self.authorities = authorities; - } -} - -struct GrandpaFinalityProofRequestBuilder(Arc>>); - -impl FinalityProofRequestBuilder for GrandpaFinalityProofRequestBuilder { - fn build_request_data(&mut self, _hash: &B::Hash) -> Vec { - let data = self.0.read(); - make_finality_proof_request( - data.last_finalized, - data.authority_set.set_id(), - ) - } -} - -/// Try to import new block. -fn do_import_block( - mut client: C, - data: &mut LightImportData, - mut block: BlockImportParams>, - new_cache: HashMap>, -) -> Result - where - C: HeaderBackend - + AuxStore - + Finalizer - + BlockImport> - + Clone, - B: Backend + 'static, - NumberFor: finality_grandpa::BlockNumberOps, - DigestFor: Encode, - J: ProvableJustification, -{ - let hash = block.post_hash(); - let number = *block.header.number(); - - // we don't want to finalize on `inner.import_block` - let justification = block.justification.take(); - let enacts_consensus_change = !new_cache.is_empty(); - let import_result = client.import_block(block, new_cache); - - let mut imported_aux = match import_result { - Ok(ImportResult::Imported(aux)) => aux, - Ok(r) => return Ok(r), - Err(e) => return Err(ConsensusError::ClientImport(e.to_string())), - }; - - match justification { - Some(justification) => { - trace!( - target: "afg", - "Imported block {}{}. Importing justification.", - if enacts_consensus_change { " which enacts consensus changes" } else { "" }, - hash, - ); - - do_import_justification::<_, _, _, J>(client, data, hash, number, justification) - }, - None if enacts_consensus_change => { - trace!( - target: "afg", - "Imported block {} which enacts consensus changes. Requesting finality proof.", - hash, - ); - - // remember that we need finality proof for this block - imported_aux.needs_finality_proof = true; - data.consensus_changes.note_change((number, hash)); - Ok(ImportResult::Imported(imported_aux)) - }, - None => Ok(ImportResult::Imported(imported_aux)), - } -} - -/// Try to import finality proof. -fn do_import_finality_proof( - client: C, - backend: Arc, - authority_set_provider: &dyn AuthoritySetForFinalityChecker, - data: &mut LightImportData, - _hash: Block::Hash, - _number: NumberFor, - finality_proof: Vec, - verifier: &mut dyn Verifier, -) -> Result<(Block::Hash, NumberFor), ConsensusError> - where - C: HeaderBackend - + AuxStore - + Finalizer - + BlockImport> - + Clone, - B: Backend + 'static, - DigestFor: Encode, - NumberFor: finality_grandpa::BlockNumberOps, - J: ProvableJustification, -{ - let authority_set_id = data.authority_set.set_id(); - let authorities = data.authority_set.authorities(); - let finality_effects = crate::finality_proof::check_finality_proof::<_, _, J>( - backend.blockchain(), - authority_set_id, - authorities, - authority_set_provider, - finality_proof, - ).map_err(|e| ConsensusError::ClientImport(e.to_string()))?; - - // try to import all new headers - let block_origin = BlockOrigin::NetworkBroadcast; - for header_to_import in finality_effects.headers_to_import { - let (block_to_import, new_authorities) = verifier.verify( - block_origin, - header_to_import, - None, - None, - ).map_err(|e| ConsensusError::ClientImport(e))?; - assert!( - block_to_import.justification.is_none(), - "We have passed None as justification to verifier.verify", - ); - - let mut cache = HashMap::new(); - if let Some(authorities) = new_authorities { - cache.insert(well_known_cache_keys::AUTHORITIES, authorities.encode()); - } - do_import_block::<_, _, _, J>( - client.clone(), - data, - block_to_import.convert_transaction(), - cache, - )?; - } - - // try to import latest justification - let finalized_block_hash = finality_effects.block; - let finalized_block_number = backend.blockchain() - .expect_block_number_from_id(&BlockId::Hash(finality_effects.block)) - .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; - do_finalize_block( - client.clone(), - data, - finalized_block_hash, - finalized_block_number, - finality_effects.justification.encode(), - )?; - - // apply new authorities set - data.authority_set.update( - finality_effects.new_set_id, - finality_effects.new_authorities, - ); - - // store new authorities set - require_insert_aux( - &client, - LIGHT_AUTHORITY_SET_KEY, - &data.authority_set, - "authority set", - )?; - - Ok((finalized_block_hash, finalized_block_number)) -} - -/// Try to import justification. -fn do_import_justification( - client: C, - data: &mut LightImportData, - hash: Block::Hash, - number: NumberFor, - justification: Justification, -) -> Result - where - C: HeaderBackend - + AuxStore - + Finalizer - + Clone, - B: Backend + 'static, - NumberFor: finality_grandpa::BlockNumberOps, - J: ProvableJustification, -{ - // with justification, we have two cases - // - // optimistic: the same GRANDPA authorities set has generated intermediate justification - // => justification is verified using current authorities set + we could proceed further - // - // pessimistic scenario: the GRANDPA authorities set has changed - // => we need to fetch new authorities set (i.e. finality proof) from remote node - - // first, try to behave optimistically - let authority_set_id = data.authority_set.set_id(); - let justification = J::decode_and_verify( - &justification, - authority_set_id, - &data.authority_set.authorities(), - ); - - // BadJustification error means that justification has been successfully decoded, but - // it isn't valid within current authority set - let justification = match justification { - Err(ClientError::BadJustification(_)) => { - trace!( - target: "afg", - "Justification for {} is not valid within current authorities set. Requesting finality proof.", - hash, - ); - - let mut imported_aux = ImportedAux::default(); - imported_aux.needs_finality_proof = true; - return Ok(ImportResult::Imported(imported_aux)); - }, - Err(e) => { - trace!( - target: "afg", - "Justification for {} is not valid. Bailing.", - hash, - ); - - return Err(ConsensusError::ClientImport(e.to_string())); - }, - Ok(justification) => { - trace!( - target: "afg", - "Justification for {} is valid. Finalizing the block.", - hash, - ); - - justification - }, - }; - - // finalize the block - do_finalize_block(client, data, hash, number, justification.encode()) -} - -/// Finalize the block. -fn do_finalize_block( - client: C, - data: &mut LightImportData, - hash: Block::Hash, - number: NumberFor, - justification: Justification, -) -> Result - where - C: HeaderBackend - + AuxStore - + Finalizer - + Clone, - B: Backend + 'static, - NumberFor: finality_grandpa::BlockNumberOps, -{ - // finalize the block - client.finalize_block(BlockId::Hash(hash), Some(justification), true).map_err(|e| { - warn!(target: "afg", "Error applying finality to block {:?}: {:?}", (hash, number), e); - ConsensusError::ClientImport(e.to_string()) - })?; - - // forget obsoleted consensus changes - let consensus_finalization_res = data.consensus_changes - .finalize( - (number, hash), - |at_height| canonical_at_height(&client, (hash, number), true, at_height) - ); - match consensus_finalization_res { - Ok((true, _)) => require_insert_aux( - &client, - LIGHT_CONSENSUS_CHANGES_KEY, - &data.consensus_changes, - "consensus changes", - )?, - Ok(_) => (), - Err(error) => return Err(on_post_finalization_error(error, "consensus changes")), - } - - // update last finalized block reference - data.last_finalized = hash; - - // we just finalized this block, so if we were importing it, it is now the new best - Ok(ImportResult::imported(true)) -} - -/// Load light import aux data from the store. -fn load_aux_import_data( - last_finalized: Block::Hash, - aux_store: &B, - genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, -) -> Result, ClientError> - where - B: AuxStore, - Block: BlockT, -{ - let authority_set = match load_decode(aux_store, LIGHT_AUTHORITY_SET_KEY)? { - Some(authority_set) => authority_set, - None => { - info!(target: "afg", "Loading GRANDPA authorities \ - from genesis on what appears to be first startup."); - - // no authority set on disk: fetch authorities from genesis state - let genesis_authorities = genesis_authorities_provider.get()?; - - let authority_set = LightAuthoritySet::genesis(genesis_authorities); - let encoded = authority_set.encode(); - aux_store.insert_aux(&[(LIGHT_AUTHORITY_SET_KEY, &encoded[..])], &[])?; - - authority_set - }, - }; - - let consensus_changes = match load_decode(aux_store, LIGHT_CONSENSUS_CHANGES_KEY)? { - Some(consensus_changes) => consensus_changes, - None => { - let consensus_changes = ConsensusChanges::>::empty(); - - let encoded = authority_set.encode(); - aux_store.insert_aux(&[(LIGHT_CONSENSUS_CHANGES_KEY, &encoded[..])], &[])?; - - consensus_changes - }, - }; - - Ok(LightImportData { - last_finalized, - authority_set, - consensus_changes, - }) -} - -/// Insert into aux store. If failed, return error && show inconsistency warning. -fn require_insert_aux( - store: &A, - key: &[u8], - value: &T, - value_type: &str, -) -> Result<(), ConsensusError> { - let encoded = value.encode(); - let update_res = store.insert_aux(&[(key, &encoded[..])], &[]); - if let Err(error) = update_res { - return Err(on_post_finalization_error(error, value_type)); - } - - Ok(()) -} - -/// Display inconsistency warning. -fn on_post_finalization_error(error: ClientError, value_type: &str) -> ConsensusError { - warn!(target: "afg", "Failed to write updated {} to disk. Bailing.", value_type); - warn!(target: "afg", "Node is in a potentially inconsistent state."); - ConsensusError::ClientImport(error.to_string()) -} - -#[cfg(test)] -pub mod tests { - use super::*; - use sp_consensus::{import_queue::CacheKeyId, ForkChoiceStrategy, BlockImport}; - use sp_finality_grandpa::AuthorityId; - use sp_core::{H256, crypto::Public}; - use sc_client_api::{in_mem::Blockchain as InMemoryAuxStore, StorageProof, BlockBackend}; - use substrate_test_runtime_client::runtime::{Block, Header}; - use crate::tests::TestApi; - use crate::finality_proof::{ - FinalityProofFragment, - tests::{TestJustification, ClosureAuthoritySetForFinalityChecker}, - }; - - struct OkVerifier; - - impl Verifier for OkVerifier { - fn verify( - &mut self, - origin: BlockOrigin, - header: Header, - _justification: Option, - _body: Option::Extrinsic>>, - ) -> Result<(BlockImportParams, Option)>>), String> { - Ok((BlockImportParams::new(origin, header), None)) - } - } - - pub struct NoJustificationsImport( - pub GrandpaLightBlockImport - ); - - impl Clone - for NoJustificationsImport where - NumberFor: finality_grandpa::BlockNumberOps, - DigestFor: Encode, - BE: Backend + 'static, - { - fn clone(&self) -> Self { - NoJustificationsImport(self.0.clone()) - } - } - - impl BlockImport - for NoJustificationsImport where - NumberFor: finality_grandpa::BlockNumberOps, - DigestFor: Encode, - BE: Backend + 'static, - for <'a > &'a Client: - HeaderBackend - + BlockImport> - + Finalizer - + AuxStore, - GrandpaLightBlockImport: - BlockImport, Error = ConsensusError> - { - type Error = ConsensusError; - type Transaction = TransactionFor; - - fn import_block( - &mut self, - mut block: BlockImportParams, - new_cache: HashMap>, - ) -> Result { - block.justification.take(); - self.0.import_block(block, new_cache) - } - - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - self.0.check_block(block) - } - } - - impl FinalityProofImport - for NoJustificationsImport where - NumberFor: finality_grandpa::BlockNumberOps, - BE: Backend + 'static, - DigestFor: Encode, - for <'a > &'a Client: - HeaderBackend - + BlockImport> - + Finalizer - + AuxStore, - { - type Error = ConsensusError; - - fn on_start(&mut self) -> Vec<(Block::Hash, NumberFor)> { - self.0.on_start() - } - - fn import_finality_proof( - &mut self, - hash: Block::Hash, - number: NumberFor, - finality_proof: Vec, - verifier: &mut dyn Verifier, - ) -> Result<(Block::Hash, NumberFor), Self::Error> { - self.0.import_finality_proof(hash, number, finality_proof, verifier) - } - } - - /// Creates light block import that ignores justifications that came outside of finality proofs. - pub fn light_block_import_without_justifications( - client: Arc, - backend: Arc, - genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, - authority_set_provider: Arc>, - ) -> Result, ClientError> - where - BE: Backend + 'static, - Client: crate::ClientForGrandpa, - { - light_block_import(client, backend, genesis_authorities_provider, authority_set_provider) - .map(NoJustificationsImport) - } - - fn import_block( - new_cache: HashMap>, - justification: Option, - ) -> ( - ImportResult, - substrate_test_runtime_client::client::Client, - Arc, - ) { - let (client, backend) = substrate_test_runtime_client::new_light(); - let mut import_data = LightImportData { - last_finalized: Default::default(), - authority_set: LightAuthoritySet::genesis(vec![(AuthorityId::from_slice(&[1; 32]), 1)]), - consensus_changes: ConsensusChanges::empty(), - }; - let mut block = BlockImportParams::new( - BlockOrigin::Own, - Header { - number: 1, - parent_hash: client.chain_info().best_hash, - state_root: Default::default(), - digest: Default::default(), - extrinsics_root: Default::default(), - }, - ); - block.justification = justification; - block.fork_choice = Some(ForkChoiceStrategy::LongestChain); - - ( - do_import_block::<_, _, _, TestJustification>( - &client, - &mut import_data, - block, - new_cache, - ).unwrap(), - client, - backend, - ) - } - - #[test] - fn finality_proof_not_required_when_consensus_data_does_not_changes_and_no_justification_provided() { - assert_eq!(import_block(HashMap::new(), None).0, ImportResult::Imported(ImportedAux { - clear_justification_requests: false, - needs_justification: false, - bad_justification: false, - needs_finality_proof: false, - is_new_best: true, - header_only: false, - })); - } - - #[test] - fn finality_proof_not_required_when_consensus_data_does_not_changes_and_correct_justification_provided() { - let justification = TestJustification((0, vec![(AuthorityId::from_slice(&[1; 32]), 1)]), Vec::new()).encode(); - assert_eq!(import_block(HashMap::new(), Some(justification)).0, ImportResult::Imported(ImportedAux { - clear_justification_requests: false, - needs_justification: false, - bad_justification: false, - needs_finality_proof: false, - is_new_best: true, - header_only: false, - })); - } - - #[test] - fn finality_proof_required_when_consensus_data_changes_and_no_justification_provided() { - let mut cache = HashMap::new(); - cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_slice(&[2; 32])].encode()); - assert_eq!(import_block(cache, None).0, ImportResult::Imported(ImportedAux { - clear_justification_requests: false, - needs_justification: false, - bad_justification: false, - needs_finality_proof: true, - is_new_best: true, - header_only: false, - })); - } - - #[test] - fn finality_proof_required_when_consensus_data_changes_and_incorrect_justification_provided() { - let justification = TestJustification((0, vec![]), Vec::new()).encode(); - let mut cache = HashMap::new(); - cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_slice(&[2; 32])].encode()); - assert_eq!( - import_block(cache, Some(justification)).0, - ImportResult::Imported(ImportedAux { - clear_justification_requests: false, - needs_justification: false, - bad_justification: false, - needs_finality_proof: true, - is_new_best: false, - header_only: false, - }, - )); - } - - - #[test] - fn aux_data_updated_on_start() { - let aux_store = InMemoryAuxStore::::new(); - let api = TestApi::new(vec![(AuthorityId::from_slice(&[1; 32]), 1)]); - - // when aux store is empty initially - assert!(aux_store.get_aux(LIGHT_AUTHORITY_SET_KEY).unwrap().is_none()); - assert!(aux_store.get_aux(LIGHT_CONSENSUS_CHANGES_KEY).unwrap().is_none()); - - // it is updated on importer start - load_aux_import_data(Default::default(), &aux_store, &api).unwrap(); - assert!(aux_store.get_aux(LIGHT_AUTHORITY_SET_KEY).unwrap().is_some()); - assert!(aux_store.get_aux(LIGHT_CONSENSUS_CHANGES_KEY).unwrap().is_some()); - } - - #[test] - fn aux_data_loaded_on_restart() { - let aux_store = InMemoryAuxStore::::new(); - let api = TestApi::new(vec![(AuthorityId::from_slice(&[1; 32]), 1)]); - - // when aux store is non-empty initially - let mut consensus_changes = ConsensusChanges::::empty(); - consensus_changes.note_change((42, Default::default())); - aux_store.insert_aux( - &[ - ( - LIGHT_AUTHORITY_SET_KEY, - LightAuthoritySet::genesis( - vec![(AuthorityId::from_slice(&[42; 32]), 2)] - ).encode().as_slice(), - ), - ( - LIGHT_CONSENSUS_CHANGES_KEY, - consensus_changes.encode().as_slice(), - ), - ], - &[], - ).unwrap(); - - // importer uses it on start - let data = load_aux_import_data(Default::default(), &aux_store, &api).unwrap(); - assert_eq!(data.authority_set.authorities(), vec![(AuthorityId::from_slice(&[42; 32]), 2)]); - assert_eq!(data.consensus_changes.pending_changes(), &[(42, Default::default())]); - } - - #[test] - fn authority_set_is_updated_on_finality_proof_import() { - let initial_set_id = 0; - let initial_set = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; - let updated_set = vec![(AuthorityId::from_slice(&[2; 32]), 2)]; - let babe_set_signal = vec![AuthorityId::from_slice(&[42; 32])].encode(); - - // import block #1 without justification - let mut cache = HashMap::new(); - cache.insert(well_known_cache_keys::AUTHORITIES, babe_set_signal); - let (_, client, backend) = import_block(cache, None); - - // import finality proof for block #1 - let hash = client.block_hash(1).unwrap().unwrap(); - let mut verifier = OkVerifier; - let mut import_data = LightImportData { - last_finalized: Default::default(), - authority_set: LightAuthoritySet::genesis(initial_set.clone()), - consensus_changes: ConsensusChanges::empty(), - }; - - // import finality proof - do_import_finality_proof::<_, _, _, TestJustification>( - &client, - backend, - &ClosureAuthoritySetForFinalityChecker( - |_, _, _| Ok(updated_set.clone()) - ), - &mut import_data, - Default::default(), - Default::default(), - vec![ - FinalityProofFragment::
{ - block: hash, - justification: TestJustification( - (initial_set_id, initial_set.clone()), - Vec::new(), - ).encode(), - unknown_headers: Vec::new(), - authorities_proof: Some(StorageProof::new(vec![])), - }, - ].encode(), - &mut verifier, - ).unwrap(); - - // verify that new authorities set has been saved to the aux storage - let data = load_aux_import_data(Default::default(), &client, &TestApi::new(initial_set)).unwrap(); - assert_eq!(data.authority_set.authorities(), updated_set); - } -} diff --git a/client/finality-grandpa/src/observer.rs b/client/finality-grandpa/src/observer.rs index fd00b35c40a73..c61998225e323 100644 --- a/client/finality-grandpa/src/observer.rs +++ b/client/finality-grandpa/src/observer.rs @@ -39,7 +39,6 @@ use crate::{ }; use crate::authorities::SharedAuthoritySet; use crate::communication::{Network as NetworkT, NetworkBridge}; -use crate::consensus_changes::SharedConsensusChanges; use crate::notification::GrandpaJustificationSender; use sp_finality_grandpa::AuthorityId; use std::marker::{PhantomData, Unpin}; @@ -68,7 +67,6 @@ impl<'a, Block, Client> finality_grandpa::Chain> fn grandpa_observer( client: &Arc, authority_set: &SharedAuthoritySet>, - consensus_changes: &SharedConsensusChanges>, voters: &Arc>, justification_sender: &Option>, last_finalized_number: NumberFor, @@ -83,7 +81,6 @@ where Client: crate::ClientForGrandpa, { let authority_set = authority_set.clone(); - let consensus_changes = consensus_changes.clone(); let client = client.clone(); let voters = voters.clone(); let justification_sender = justification_sender.clone(); @@ -123,7 +120,6 @@ where match environment::finalize_block( client.clone(), &authority_set, - &consensus_changes, None, finalized_hash, finalized_number, @@ -293,7 +289,6 @@ where let observer = grandpa_observer( &self.client, &self.persistent_data.authority_set, - &self.persistent_data.consensus_changes, &voters, &self.justification_sender, last_finalized_number, diff --git a/client/finality-grandpa/src/tests.rs b/client/finality-grandpa/src/tests.rs index 175c5360b2c13..ef8168e84f66c 100644 --- a/client/finality-grandpa/src/tests.rs +++ b/client/finality-grandpa/src/tests.rs @@ -25,7 +25,7 @@ use sc_network_test::{ Block, BlockImportAdapter, Hash, PassThroughVerifier, Peer, PeersClient, PeersFullClient, TestClient, TestNetFactory, FullPeerConfig, }; -use sc_network::config::{ProtocolConfig, BoxFinalityProofRequestBuilder}; +use sc_network::config::ProtocolConfig; use parking_lot::{RwLock, Mutex}; use futures_timer::Delay; use tokio::runtime::{Runtime, Handle}; @@ -36,22 +36,21 @@ use sp_api::{ApiRef, StorageProof, ProvideRuntimeApi}; use substrate_test_runtime_client::runtime::BlockNumber; use sp_consensus::{ BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, ImportResult, BlockImport, - import_queue::{BoxJustificationImport, BoxFinalityProofImport}, + import_queue::BoxJustificationImport, }; use std::{collections::{HashMap, HashSet}, pin::Pin}; use parity_scale_codec::Decode; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, HashFor}; use sp_runtime::generic::{BlockId, DigestItem}; -use sp_core::{H256, crypto::Public}; +use sp_core::H256; use sp_keystore::{SyncCryptoStorePtr, SyncCryptoStore}; use sp_finality_grandpa::{GRANDPA_ENGINE_ID, AuthorityList, EquivocationProof, GrandpaApi, OpaqueKeyOwnershipProof}; use sp_state_machine::{InMemoryBackend, prove_read, read_proof_check}; use authorities::AuthoritySet; use finality_proof::{ - FinalityProofProvider, AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker, + AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker, }; -use consensus_changes::ConsensusChanges; use sc_block_builder::BlockBuilderProvider; use sc_consensus::LongestChain; use sc_keystore::LocalKeystore; @@ -99,9 +98,7 @@ impl TestNetFactory for GrandpaTestNet { fn add_full_peer(&mut self) { self.add_full_peer_with_config(FullPeerConfig { - notifications_protocols: vec![ - (communication::GRANDPA_ENGINE_ID, communication::GRANDPA_PROTOCOL_NAME.into()) - ], + notifications_protocols: vec![communication::GRANDPA_PROTOCOL_NAME.into()], ..Default::default() }) } @@ -119,8 +116,6 @@ impl TestNetFactory for GrandpaTestNet { -> ( BlockImportAdapter, Option>, - Option>, - Option>, PeerData, ) { @@ -135,45 +130,12 @@ impl TestNetFactory for GrandpaTestNet { ( BlockImportAdapter::new_full(import), Some(justification_import), - None, - None, Mutex::new(Some(link)), ) }, - PeersClient::Light(ref client, ref backend) => { - use crate::light_import::tests::light_block_import_without_justifications; - - let authorities_provider = Arc::new(self.test_config.clone()); - // forbid direct finalization using justification that came with the block - // => light clients will try to fetch finality proofs - let import = light_block_import_without_justifications( - client.clone(), - backend.clone(), - &self.test_config, - authorities_provider, - ).expect("Could not create block import for fresh peer."); - let finality_proof_req_builder = import.0.create_finality_proof_request_builder(); - let proof_import = Box::new(import.clone()); - ( - BlockImportAdapter::new_light(import), - None, - Some(proof_import), - Some(finality_proof_req_builder), - Mutex::new(None), - ) - }, - } - } - - fn make_finality_proof_provider( - &self, - client: PeersClient - ) -> Option>> { - match client { - PeersClient::Full(_, ref backend) => { - Some(Arc::new(FinalityProofProvider::new(backend.clone(), self.test_config.clone()))) + PeersClient::Light(..) => { + panic!("Light client is not used in tests."); }, - PeersClient::Light(_, _) => None, } } @@ -681,24 +643,6 @@ fn transition_3_voters_twice_1_full_observer() { block_until_complete(wait_for, &net, &mut runtime); } -#[test] -fn justification_is_emitted_when_consensus_data_changes() { - let mut runtime = Runtime::new().unwrap(); - let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 3); - - // import block#1 WITH consensus data change - let new_authorities = vec![sp_consensus_babe::AuthorityId::from_slice(&[42; 32])]; - net.peer(0).push_authorities_change_block(new_authorities); - net.block_until_sync(); - let net = Arc::new(Mutex::new(net)); - run_to_completion(&mut runtime, 1, net.clone(), peers); - - // ... and check that there's justification for block#1 - assert!(net.lock().peer(0).client().justification(&BlockId::Number(1)).unwrap().is_some(), - "Missing justification for block#1"); -} - #[test] fn justification_is_generated_periodically() { let mut runtime = Runtime::new().unwrap(); @@ -719,25 +663,6 @@ fn justification_is_generated_periodically() { } } -#[test] -fn consensus_changes_works() { - let mut changes = ConsensusChanges::::empty(); - - // pending changes are not finalized - changes.note_change((10, H256::from_low_u64_be(1))); - assert_eq!(changes.finalize((5, H256::from_low_u64_be(5)), |_| Ok(None)).unwrap(), (false, false)); - - // no change is selected from competing pending changes - changes.note_change((1, H256::from_low_u64_be(1))); - changes.note_change((1, H256::from_low_u64_be(101))); - assert_eq!(changes.finalize((10, H256::from_low_u64_be(10)), |_| Ok(Some(H256::from_low_u64_be(1001)))).unwrap(), (true, false)); - - // change is selected from competing pending changes - changes.note_change((1, H256::from_low_u64_be(1))); - changes.note_change((1, H256::from_low_u64_be(101))); - assert_eq!(changes.finalize((10, H256::from_low_u64_be(10)), |_| Ok(Some(H256::from_low_u64_be(1)))).unwrap(), (true, true)); -} - #[test] fn sync_justifications_on_change_blocks() { let mut runtime = Runtime::new().unwrap(); @@ -946,7 +871,6 @@ fn allows_reimporting_change_blocks() { needs_justification: true, clear_justification_requests: false, bad_justification: false, - needs_finality_proof: false, is_new_best: true, header_only: false, }), @@ -1071,7 +995,7 @@ fn voter_persists_its_votes() { Poll::Pending => return Poll::Pending, Poll::Ready(None) => return Poll::Ready(()), Poll::Ready(Some(())) => { - let (_block_import, _, _, _, link) = + let (_block_import, _, link) = this.net.lock() .make_block_import::< TransactionFor @@ -1146,7 +1070,7 @@ fn voter_persists_its_votes() { }; let set_state = { - let (_, _, _, _, link) = net.lock() + let (_, _, link) = net.lock() .make_block_import::< TransactionFor >(client); @@ -1313,100 +1237,6 @@ fn finalize_3_voters_1_light_observer() { }); } -#[test] -fn finality_proof_is_fetched_by_light_client_when_consensus_data_changes() { - sp_tracing::try_init_simple(); - let mut runtime = Runtime::new().unwrap(); - - let peers = &[Ed25519Keyring::Alice]; - let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 1); - net.add_light_peer(); - - // import block#1 WITH consensus data change. Light client ignores justification - // && instead fetches finality proof for block #1 - net.peer(0).push_authorities_change_block(vec![sp_consensus_babe::AuthorityId::from_slice(&[42; 32])]); - let net = Arc::new(Mutex::new(net)); - run_to_completion(&mut runtime, 1, net.clone(), peers); - net.lock().block_until_sync(); - - // check that the block#1 is finalized on light client - runtime.block_on(futures::future::poll_fn(move |cx| { - if net.lock().peer(1).client().info().finalized_number == 1 { - Poll::Ready(()) - } else { - net.lock().poll(cx); - Poll::Pending - } - })); -} - -#[test] -fn empty_finality_proof_is_returned_to_light_client_when_authority_set_is_different() { - // for debug: to ensure that without forced change light client will sync finality proof - const FORCE_CHANGE: bool = true; - - sp_tracing::try_init_simple(); - let mut runtime = Runtime::new().unwrap(); - - // two of these guys are offline. - let genesis_authorities = if FORCE_CHANGE { - vec![ - Ed25519Keyring::Alice, - Ed25519Keyring::Bob, - Ed25519Keyring::Charlie, - Ed25519Keyring::One, - Ed25519Keyring::Two, - ] - } else { - vec![ - Ed25519Keyring::Alice, - Ed25519Keyring::Bob, - Ed25519Keyring::Charlie, - ] - }; - let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let api = TestApi::new(make_ids(&genesis_authorities)); - - let voters = make_ids(peers_a); - let net = GrandpaTestNet::new(api, 3); - let net = Arc::new(Mutex::new(net)); - - // best is #1 - net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { - // add a forced transition at block 5. - let mut block = builder.build().unwrap().block; - if FORCE_CHANGE { - add_forced_change(&mut block, 0, ScheduledChange { - next_authorities: voters.clone(), - delay: 3, - }); - } - block - }); - - // ensure block#10 enacts authorities set change => justification is generated - // normally it will reach light client, but because of the forced change, it will not - net.lock().peer(0).push_blocks(8, false); // best is #9 - net.lock().peer(0).push_authorities_change_block( - vec![sp_consensus_babe::AuthorityId::from_slice(&[42; 32])] - ); // #10 - net.lock().peer(0).push_blocks(1, false); // best is #11 - net.lock().block_until_sync(); - - // finalize block #11 on full clients - run_to_completion(&mut runtime, 11, net.clone(), peers_a); - - // request finalization by light client - net.lock().add_light_peer(); - net.lock().block_until_sync(); - - // check block, finalized on light client - assert_eq!( - net.lock().peer(3).client().info().finalized_number, - if FORCE_CHANGE { 0 } else { 10 }, - ); -} - #[test] fn voter_catches_up_to_latest_round_when_behind() { sp_tracing::try_init_simple(); @@ -1542,7 +1372,6 @@ where { let PersistentData { ref authority_set, - ref consensus_changes, ref set_state, .. } = link.persistent_data; @@ -1566,7 +1395,6 @@ where Environment { authority_set: authority_set.clone(), config: config.clone(), - consensus_changes: consensus_changes.clone(), client: link.client.clone(), select_chain: link.select_chain.clone(), set_id: authority_set.set_id(), diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index c120ff515c7ad..02d9345323960 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -19,7 +19,7 @@ futures = "0.3.4" futures-timer = "3.0.1" libp2p = { version = "0.30.1", default-features = false } log = "0.4.8" -lru = "0.4.3" +lru = "0.6.1" sc-network = { version = "0.8.0", path = "../network" } sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } wasm-timer = "0.2" diff --git a/client/network-gossip/src/bridge.rs b/client/network-gossip/src/bridge.rs index 70c2942597aa5..98ada69590f1c 100644 --- a/client/network-gossip/src/bridge.rs +++ b/client/network-gossip/src/bridge.rs @@ -23,7 +23,7 @@ use futures::prelude::*; use futures::channel::mpsc::{channel, Sender, Receiver}; use libp2p::PeerId; use log::trace; -use sp_runtime::{traits::Block as BlockT, ConsensusEngineId}; +use sp_runtime::traits::Block as BlockT; use std::{ borrow::Cow, collections::{HashMap, VecDeque}, @@ -38,7 +38,7 @@ pub struct GossipEngine { state_machine: ConsensusGossip, network: Box + Send>, periodic_maintenance_interval: futures_timer::Delay, - engine_id: ConsensusEngineId, + protocol: Cow<'static, str>, /// Incoming events from the network. network_event_stream: Pin + Send>>, @@ -68,20 +68,21 @@ impl GossipEngine { /// Create a new instance. pub fn new + Send + Clone + 'static>( network: N, - engine_id: ConsensusEngineId, - protocol_name: impl Into>, + protocol: impl Into>, validator: Arc>, ) -> Self where B: 'static { + let protocol = protocol.into(); + // We grab the event stream before registering the notifications protocol, otherwise we // might miss events. let network_event_stream = network.event_stream(); - network.register_notifications_protocol(engine_id, protocol_name.into()); + network.register_notifications_protocol(protocol.clone()); GossipEngine { - state_machine: ConsensusGossip::new(validator, engine_id), + state_machine: ConsensusGossip::new(validator, protocol.clone()), network: Box::new(network), periodic_maintenance_interval: futures_timer::Delay::new(PERIODIC_MAINTENANCE_INTERVAL), - engine_id, + protocol, network_event_stream, message_sinks: HashMap::new(), @@ -181,21 +182,21 @@ impl Future for GossipEngine { ForwardingState::Idle => { match this.network_event_stream.poll_next_unpin(cx) { Poll::Ready(Some(event)) => match event { - Event::NotificationStreamOpened { remote, engine_id, role } => { - if engine_id != this.engine_id { + Event::NotificationStreamOpened { remote, protocol, role } => { + if protocol != this.protocol { continue; } this.state_machine.new_peer(&mut *this.network, remote, role); } - Event::NotificationStreamClosed { remote, engine_id } => { - if engine_id != this.engine_id { + Event::NotificationStreamClosed { remote, protocol } => { + if protocol != this.protocol { continue; } this.state_machine.peer_disconnected(&mut *this.network, remote); }, Event::NotificationsReceived { remote, messages } => { let messages = messages.into_iter().filter_map(|(engine, data)| { - if engine == this.engine_id { + if engine == this.protocol { Some(data.to_vec()) } else { None @@ -299,6 +300,7 @@ mod tests { use rand::Rng; use sc_network::ObservedRole; use sp_runtime::{testing::H256, traits::{Block as BlockT}}; + use std::borrow::Cow; use std::convert::TryInto; use std::sync::{Arc, Mutex}; use substrate_test_runtime_client::runtime::Block; @@ -329,11 +331,11 @@ mod tests { unimplemented!(); } - fn write_notification(&self, _: PeerId, _: ConsensusEngineId, _: Vec) { + fn write_notification(&self, _: PeerId, _: Cow<'static, str>, _: Vec) { unimplemented!(); } - fn register_notifications_protocol(&self, _: ConsensusEngineId, _: Cow<'static, str>) {} + fn register_notifications_protocol(&self, _: Cow<'static, str>) {} fn announce(&self, _: B::Hash, _: Vec) { unimplemented!(); @@ -361,8 +363,7 @@ mod tests { let network = TestNetwork::default(); let mut gossip_engine = GossipEngine::::new( network.clone(), - [1, 2, 3, 4], - "my_protocol", + "/my_protocol", Arc::new(AllowAll{}), ); @@ -383,14 +384,13 @@ mod tests { #[test] fn keeps_multiple_subscribers_per_topic_updated_with_both_old_and_new_messages() { let topic = H256::default(); - let engine_id = [1, 2, 3, 4]; + let protocol = Cow::Borrowed("/my_protocol"); let remote_peer = PeerId::random(); let network = TestNetwork::default(); let mut gossip_engine = GossipEngine::::new( network.clone(), - engine_id.clone(), - "my_protocol", + protocol.clone(), Arc::new(AllowAll{}), ); @@ -404,7 +404,7 @@ mod tests { event_sender.start_send( Event::NotificationStreamOpened { remote: remote_peer.clone(), - engine_id: engine_id.clone(), + protocol: protocol.clone(), role: ObservedRole::Authority, } ).expect("Event stream is unbounded; qed."); @@ -413,7 +413,7 @@ mod tests { let events = messages.iter().cloned().map(|m| { Event::NotificationsReceived { remote: remote_peer.clone(), - messages: vec![(engine_id, m.into())] + messages: vec![(protocol.clone(), m.into())] } }).collect::>(); @@ -498,7 +498,7 @@ mod tests { } fn prop(channels: Vec, notifications: Vec>) { - let engine_id = [1, 2, 3, 4]; + let protocol = Cow::Borrowed("/my_protocol"); let remote_peer = PeerId::random(); let network = TestNetwork::default(); @@ -524,8 +524,7 @@ mod tests { let mut gossip_engine = GossipEngine::::new( network.clone(), - engine_id.clone(), - "my_protocol", + protocol.clone(), Arc::new(TestValidator{}), ); @@ -558,7 +557,7 @@ mod tests { event_sender.start_send( Event::NotificationStreamOpened { remote: remote_peer.clone(), - engine_id: engine_id.clone(), + protocol: protocol.clone(), role: ObservedRole::Authority, } ).expect("Event stream is unbounded; qed."); @@ -576,7 +575,7 @@ mod tests { message.push(i_notification.try_into().unwrap()); message.push(i_message.try_into().unwrap()); - (engine_id, message.into()) + (protocol.clone(), message.into()) }).collect(); event_sender.start_send(Event::NotificationsReceived { diff --git a/client/network-gossip/src/lib.rs b/client/network-gossip/src/lib.rs index 1d566ed3cbba2..09e946d1a1ea9 100644 --- a/client/network-gossip/src/lib.rs +++ b/client/network-gossip/src/lib.rs @@ -33,7 +33,7 @@ //! - Implement the `Network` trait, representing the low-level networking primitives. It is //! already implemented on `sc_network::NetworkService`. //! - Implement the `Validator` trait. See the section below. -//! - Decide on a `ConsensusEngineId`. Each gossiping protocol should have a different one. +//! - Decide on a protocol name. Each gossiping protocol should have a different one. //! - Build a `GossipEngine` using these three elements. //! - Use the methods of the `GossipEngine` in order to send out messages and receive incoming //! messages. @@ -60,7 +60,7 @@ pub use self::validator::{DiscardAll, MessageIntent, Validator, ValidatorContext use futures::prelude::*; use sc_network::{Event, ExHashT, NetworkService, PeerId, ReputationChange}; -use sp_runtime::{traits::Block as BlockT, ConsensusEngineId}; +use sp_runtime::{traits::Block as BlockT}; use std::{borrow::Cow, pin::Pin, sync::Arc}; mod bridge; @@ -79,15 +79,14 @@ pub trait Network { fn disconnect_peer(&self, who: PeerId); /// Send a notification to a peer. - fn write_notification(&self, who: PeerId, engine_id: ConsensusEngineId, message: Vec); + fn write_notification(&self, who: PeerId, protocol: Cow<'static, str>, message: Vec); /// Registers a notifications protocol. /// /// See the documentation of [`NetworkService:register_notifications_protocol`] for more information. fn register_notifications_protocol( &self, - engine_id: ConsensusEngineId, - protocol_name: Cow<'static, str>, + protocol: Cow<'static, str>, ); /// Notify everyone we're connected to that we have the given block. @@ -110,16 +109,15 @@ impl Network for Arc> { NetworkService::disconnect_peer(self, who) } - fn write_notification(&self, who: PeerId, engine_id: ConsensusEngineId, message: Vec) { - NetworkService::write_notification(self, who, engine_id, message) + fn write_notification(&self, who: PeerId, protocol: Cow<'static, str>, message: Vec) { + NetworkService::write_notification(self, who, protocol, message) } fn register_notifications_protocol( &self, - engine_id: ConsensusEngineId, - protocol_name: Cow<'static, str>, + protocol: Cow<'static, str>, ) { - NetworkService::register_notifications_protocol(self, engine_id, protocol_name) + NetworkService::register_notifications_protocol(self, protocol) } fn announce(&self, block: B::Hash, associated_data: Vec) { diff --git a/client/network-gossip/src/state_machine.rs b/client/network-gossip/src/state_machine.rs index 60c669ecb6680..8bd6d9df01911 100644 --- a/client/network-gossip/src/state_machine.rs +++ b/client/network-gossip/src/state_machine.rs @@ -18,6 +18,7 @@ use crate::{Network, MessageIntent, Validator, ValidatorContext, ValidationResult}; +use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::sync::Arc; use std::iter; @@ -26,7 +27,6 @@ use log::{error, trace}; use lru::LruCache; use libp2p::PeerId; use sp_runtime::traits::{Block as BlockT, Hash, HashFor}; -use sp_runtime::ConsensusEngineId; use sc_network::ObservedRole; use wasm_timer::Instant; @@ -89,7 +89,7 @@ impl<'g, 'p, B: BlockT> ValidatorContext for NetworkContext<'g, 'p, B> { /// Send addressed message to a peer. fn send_message(&mut self, who: &PeerId, message: Vec) { - self.network.write_notification(who.clone(), self.gossip.engine_id, message); + self.network.write_notification(who.clone(), self.gossip.protocol.clone(), message); } /// Send all messages with given topic to a peer. @@ -100,7 +100,7 @@ impl<'g, 'p, B: BlockT> ValidatorContext for NetworkContext<'g, 'p, B> { fn propagate<'a, B: BlockT, I>( network: &mut dyn Network, - engine_id: ConsensusEngineId, + protocol: Cow<'static, str>, messages: I, intent: MessageIntent, peers: &mut HashMap>, @@ -138,7 +138,7 @@ fn propagate<'a, B: BlockT, I>( peer.known_messages.insert(message_hash.clone()); trace!(target: "gossip", "Propagating to {}: {:?}", id, message); - network.write_notification(id.clone(), engine_id, message.clone()); + network.write_notification(id.clone(), protocol.clone(), message.clone()); } } } @@ -148,19 +148,19 @@ pub struct ConsensusGossip { peers: HashMap>, messages: Vec>, known_messages: LruCache, - engine_id: ConsensusEngineId, + protocol: Cow<'static, str>, validator: Arc>, next_broadcast: Instant, } impl ConsensusGossip { /// Create a new instance using the given validator. - pub fn new(validator: Arc>, engine_id: ConsensusEngineId) -> Self { + pub fn new(validator: Arc>, protocol: Cow<'static, str>) -> Self { ConsensusGossip { peers: HashMap::new(), messages: Default::default(), known_messages: LruCache::new(KNOWN_MESSAGES_CACHE_SIZE), - engine_id, + protocol, validator, next_broadcast: Instant::now() + REBROADCAST_INTERVAL, } @@ -235,7 +235,14 @@ impl ConsensusGossip { fn rebroadcast(&mut self, network: &mut dyn Network) { let messages = self.messages.iter() .map(|entry| (&entry.message_hash, &entry.topic, &entry.message)); - propagate(network, self.engine_id, messages, MessageIntent::PeriodicRebroadcast, &mut self.peers, &self.validator); + propagate( + network, + self.protocol.clone(), + messages, + MessageIntent::PeriodicRebroadcast, + &mut self.peers, + &self.validator + ); } /// Broadcast all messages with given topic. @@ -247,7 +254,7 @@ impl ConsensusGossip { } else { None } ); let intent = if force { MessageIntent::ForcedBroadcast } else { MessageIntent::Broadcast }; - propagate(network, self.engine_id, messages, intent, &mut self.peers, &self.validator); + propagate(network, self.protocol.clone(), messages, intent, &mut self.peers, &self.validator); } /// Prune old or no longer relevant consensus messages. Provide a predicate @@ -374,7 +381,7 @@ impl ConsensusGossip { peer.known_messages.insert(entry.message_hash.clone()); trace!(target: "gossip", "Sending topic message to {}: {:?}", who, entry.message); - network.write_notification(who.clone(), self.engine_id, entry.message.clone()); + network.write_notification(who.clone(), self.protocol.clone(), entry.message.clone()); } } } @@ -390,7 +397,14 @@ impl ConsensusGossip { let message_hash = HashFor::::hash(&message); self.register_message_hashed(message_hash, topic, message.clone(), None); let intent = if force { MessageIntent::ForcedBroadcast } else { MessageIntent::Broadcast }; - propagate(network, self.engine_id, iter::once((&message_hash, &topic, &message)), intent, &mut self.peers, &self.validator); + propagate( + network, + self.protocol.clone(), + iter::once((&message_hash, &topic, &message)), + intent, + &mut self.peers, + &self.validator + ); } /// Send addressed message to a peer. The message is not kept or multicast @@ -411,7 +425,7 @@ impl ConsensusGossip { trace!(target: "gossip", "Sending direct to {}: {:?}", who, message); peer.known_messages.insert(message_hash); - network.write_notification(who.clone(), self.engine_id, message); + network.write_notification(who.clone(), self.protocol.clone(), message); } } @@ -485,11 +499,11 @@ mod tests { unimplemented!(); } - fn write_notification(&self, _: PeerId, _: ConsensusEngineId, _: Vec) { + fn write_notification(&self, _: PeerId, _: Cow<'static, str>, _: Vec) { unimplemented!(); } - fn register_notifications_protocol(&self, _: ConsensusEngineId, _: Cow<'static, str>) {} + fn register_notifications_protocol(&self, _: Cow<'static, str>) {} fn announce(&self, _: B::Hash, _: Vec) { unimplemented!(); @@ -520,7 +534,7 @@ mod tests { let prev_hash = H256::random(); let best_hash = H256::random(); - let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), [0, 0, 0, 0]); + let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), "/foo".into()); let m1_hash = H256::random(); let m2_hash = H256::random(); let m1 = vec![1, 2, 3]; @@ -547,7 +561,7 @@ mod tests { #[test] fn message_stream_include_those_sent_before_asking() { - let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), [0, 0, 0, 0]); + let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), "/foo".into()); // Register message. let message = vec![4, 5, 6]; @@ -562,7 +576,7 @@ mod tests { #[test] fn can_keep_multiple_messages_per_topic() { - let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), [0, 0, 0, 0]); + let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), "/foo".into()); let topic = [1; 32].into(); let msg_a = vec![1, 2, 3]; @@ -576,7 +590,7 @@ mod tests { #[test] fn peer_is_removed_on_disconnect() { - let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), [0, 0, 0, 0]); + let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), "/foo".into()); let mut network = NoOpNetwork::default(); @@ -592,7 +606,7 @@ mod tests { fn on_incoming_ignores_discarded_messages() { let to_forward = ConsensusGossip::::new( Arc::new(DiscardAll), - [0, 0, 0, 0], + "/foo".into(), ).on_incoming( &mut NoOpNetwork::default(), PeerId::random(), @@ -612,7 +626,7 @@ mod tests { let to_forward = ConsensusGossip::::new( Arc::new(AllowAll), - [0, 0, 0, 0], + "/foo".into(), ).on_incoming( &mut network, // Unregistered peer. diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 6b66fd0cdee65..dac2cb22c4f35 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -20,7 +20,7 @@ prost-build = "0.6.1" async-trait = "0.1" async-std = "1.6.5" bitflags = "1.2.0" -bs58 = "0.3.1" +bs58 = "0.4.0" bytes = "0.5.0" codec = { package = "parity-scale-codec", version = "1.3.4", features = ["derive"] } derive_more = "0.99.2" @@ -36,9 +36,9 @@ ip_network = "0.3.4" linked-hash-map = "0.5.2" linked_hash_set = "0.1.3" log = "0.4.8" -lru = "0.4.0" +lru = "0.6.1" nohash-hasher = "0.2.0" -parking_lot = "0.10.0" +parking_lot = "0.11.1" pin-project = "0.4.6" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0", path = "../../utils/prometheus" } prost = "0.6.1" @@ -50,7 +50,7 @@ serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" slog = { version = "2.5.2", features = ["nested-values"] } slog_derive = "0.2.0" -smallvec = "0.6.10" +smallvec = "1.5.0" sp-arithmetic = { version = "2.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } sp-consensus = { version = "0.8.0", path = "../../primitives/consensus/common" } @@ -58,7 +58,7 @@ sp-core = { version = "2.0.0", path = "../../primitives/core" } sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } sp-utils = { version = "2.0.0", path = "../../primitives/utils" } thiserror = "1" -unsigned-varint = { version = "0.4.0", features = ["futures", "futures-codec"] } +unsigned-varint = { version = "0.5.0", features = ["futures", "futures-codec"] } void = "1.0.2" wasm-timer = "0.2" zeroize = "1.0.0" diff --git a/client/network/build.rs b/client/network/build.rs index 8ed460f163eb4..2ccc72d99df96 100644 --- a/client/network/build.rs +++ b/client/network/build.rs @@ -1,6 +1,5 @@ const PROTOS: &[&str] = &[ "src/schema/api.v1.proto", - "src/schema/finality.v1.proto", "src/schema/light.v1.proto" ]; diff --git a/client/network/src/behaviour.rs b/client/network/src/behaviour.rs index c8684eba625c5..b2914a5e0a72b 100644 --- a/client/network/src/behaviour.rs +++ b/client/network/src/behaviour.rs @@ -15,9 +15,9 @@ // along with Substrate. If not, see . use crate::{ - config::{ProtocolId, Role}, block_requests, light_client_handler, finality_requests, + config::{ProtocolId, Role}, block_requests, light_client_handler, peer_info, request_responses, discovery::{DiscoveryBehaviour, DiscoveryConfig, DiscoveryOut}, - protocol::{message::{self, Roles}, CustomMessageOutcome, NotificationsSink, Protocol}, + protocol::{message::Roles, CustomMessageOutcome, NotificationsSink, Protocol}, ObservedRole, DhtEvent, ExHashT, }; @@ -30,7 +30,7 @@ use libp2p::kad::record; use libp2p::swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters}; use log::debug; use sp_consensus::{BlockOrigin, import_queue::{IncomingBlock, Origin}}; -use sp_runtime::{traits::{Block as BlockT, NumberFor}, ConsensusEngineId, Justification}; +use sp_runtime::{traits::{Block as BlockT, NumberFor}, Justification}; use std::{ borrow::Cow, collections::{HashSet, VecDeque}, @@ -58,8 +58,6 @@ pub struct Behaviour { request_responses: request_responses::RequestResponsesBehaviour, /// Block request handling. block_requests: block_requests::BlockRequests, - /// Finality proof request handling. - finality_proof_requests: finality_requests::FinalityProofRequests, /// Light client request handling. light_client_handler: light_client_handler::LightClientHandler, @@ -76,7 +74,6 @@ pub struct Behaviour { pub enum BehaviourOut { BlockImport(BlockOrigin, Vec>), JustificationImport(Origin, B::Hash, NumberFor, Justification), - FinalityProofImport(Origin, B::Hash, NumberFor, Vec), /// Started a random iterative Kademlia discovery query. RandomKademliaStarted(ProtocolId), @@ -131,7 +128,7 @@ pub enum BehaviourOut { /// Node we opened the substream with. remote: PeerId, /// The concerned protocol. Each protocol uses a different substream. - engine_id: ConsensusEngineId, + protocol: Cow<'static, str>, /// Object that permits sending notifications to the peer. notifications_sink: NotificationsSink, /// Role of the remote. @@ -147,7 +144,7 @@ pub enum BehaviourOut { /// Id of the peer we are connected to. remote: PeerId, /// The concerned protocol. Each protocol uses a different substream. - engine_id: ConsensusEngineId, + protocol: Cow<'static, str>, /// Replacement for the previous [`NotificationsSink`]. notifications_sink: NotificationsSink, }, @@ -158,7 +155,7 @@ pub enum BehaviourOut { /// Node we closed the substream with. remote: PeerId, /// The concerned protocol. Each protocol uses a different substream. - engine_id: ConsensusEngineId, + protocol: Cow<'static, str>, }, /// Received one or more messages from the given node using the given protocol. @@ -166,7 +163,7 @@ pub enum BehaviourOut { /// Node we received the message from. remote: PeerId, /// Concerned protocol and associated message. - messages: Vec<(ConsensusEngineId, Bytes)>, + messages: Vec<(Cow<'static, str>, Bytes)>, }, /// Events generated by a DHT as a response to get_value or put_value requests as well as the @@ -182,7 +179,6 @@ impl Behaviour { user_agent: String, local_public_key: PublicKey, block_requests: block_requests::BlockRequests, - finality_proof_requests: finality_requests::FinalityProofRequests, light_client_handler: light_client_handler::LightClientHandler, disco_config: DiscoveryConfig, request_response_protocols: Vec, @@ -194,7 +190,6 @@ impl Behaviour { request_responses: request_responses::RequestResponsesBehaviour::new(request_response_protocols.into_iter())?, block_requests, - finality_proof_requests, light_client_handler, events: VecDeque::new(), role, @@ -257,19 +252,20 @@ impl Behaviour { /// will retain the protocols that were registered then, and not any new one. pub fn register_notifications_protocol( &mut self, - engine_id: ConsensusEngineId, - protocol_name: impl Into>, + protocol: impl Into>, ) { + let protocol = protocol.into(); + // This is the message that we will send to the remote as part of the initial handshake. // At the moment, we force this to be an encoded `Roles`. let handshake_message = Roles::from(&self.role).encode(); - let list = self.substrate.register_notifications_protocol(engine_id, protocol_name, handshake_message); + let list = self.substrate.register_notifications_protocol(protocol.clone(), handshake_message); for (remote, roles, notifications_sink) in list { let role = reported_roles_to_observed_role(&self.role, remote, roles); self.events.push_back(BehaviourOut::NotificationStreamOpened { remote: remote.clone(), - engine_id, + protocol: protocol.clone(), role, notifications_sink: notifications_sink.clone(), }); @@ -333,8 +329,6 @@ Behaviour { self.events.push_back(BehaviourOut::BlockImport(origin, blocks)), CustomMessageOutcome::JustificationImport(origin, hash, nb, justification) => self.events.push_back(BehaviourOut::JustificationImport(origin, hash, nb, justification)), - CustomMessageOutcome::FinalityProofImport(origin, hash, nb, proof) => - self.events.push_back(BehaviourOut::FinalityProofImport(origin, hash, nb, proof)), CustomMessageOutcome::BlockRequest { target, request } => { match self.block_requests.send_request(&target, request) { block_requests::SendRequestOutcome::Ok => { @@ -358,33 +352,30 @@ Behaviour { block_requests::SendRequestOutcome::EncodeError(_) => {}, } }, - CustomMessageOutcome::FinalityProofRequest { target, block_hash, request } => { - self.finality_proof_requests.send_request(&target, block_hash, request); - }, CustomMessageOutcome::NotificationStreamOpened { remote, protocols, roles, notifications_sink } => { let role = reported_roles_to_observed_role(&self.role, &remote, roles); - for engine_id in protocols { + for protocol in protocols { self.events.push_back(BehaviourOut::NotificationStreamOpened { remote: remote.clone(), - engine_id, + protocol, role: role.clone(), notifications_sink: notifications_sink.clone(), }); } }, CustomMessageOutcome::NotificationStreamReplaced { remote, protocols, notifications_sink } => - for engine_id in protocols { + for protocol in protocols { self.events.push_back(BehaviourOut::NotificationStreamReplaced { remote: remote.clone(), - engine_id, + protocol, notifications_sink: notifications_sink.clone(), }); }, CustomMessageOutcome::NotificationStreamClosed { remote, protocols } => - for engine_id in protocols { + for protocol in protocols { self.events.push_back(BehaviourOut::NotificationStreamClosed { remote: remote.clone(), - engine_id, + protocol, }); }, CustomMessageOutcome::NotificationsReceived { remote, messages } => { @@ -453,26 +444,6 @@ impl NetworkBehaviourEventProcess NetworkBehaviourEventProcess> for Behaviour { - fn inject_event(&mut self, event: finality_requests::Event) { - match event { - finality_requests::Event::Response { peer, block_hash, proof } => { - let response = message::FinalityProofResponse { - id: 0, - block: block_hash, - proof: if !proof.is_empty() { - Some(proof) - } else { - None - }, - }; - let ev = self.substrate.on_finality_proof_response(peer, response); - self.inject_event(ev); - } - } - } -} - impl NetworkBehaviourEventProcess for Behaviour { fn inject_event(&mut self, event: peer_info::PeerInfoEvent) { diff --git a/client/network/src/chain.rs b/client/network/src/chain.rs index 20fbe0284397d..61d19c10dae51 100644 --- a/client/network/src/chain.rs +++ b/client/network/src/chain.rs @@ -32,15 +32,3 @@ impl Client for T T: HeaderBackend + ProofProvider + BlockIdTo + BlockBackend + HeaderMetadata + Send + Sync {} - -/// Finality proof provider. -pub trait FinalityProofProvider: Send + Sync { - /// Prove finality of the block. - fn prove_finality(&self, for_block: Block::Hash, request: &[u8]) -> Result>, Error>; -} - -impl FinalityProofProvider for () { - fn prove_finality(&self, _for_block: Block::Hash, _request: &[u8]) -> Result>, Error> { - Ok(None) - } -} diff --git a/client/network/src/config.rs b/client/network/src/config.rs index 86450dc6e79bf..b7b113dc14692 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -21,7 +21,7 @@ //! The [`Params`] struct is the struct that must be passed in order to initialize the networking. //! See the documentation of [`Params`]. -pub use crate::chain::{Client, FinalityProofProvider}; +pub use crate::chain::Client; pub use crate::on_demand_layer::{AlwaysBadChecker, OnDemand}; pub use crate::request_responses::{IncomingRequest, ProtocolConfig as RequestResponseConfig}; pub use libp2p::{identity, core::PublicKey, wasm_ext::ExtTransport, build_multiaddr}; @@ -41,7 +41,7 @@ use libp2p::{ }; use prometheus_endpoint::Registry; use sp_consensus::{block_validation::BlockAnnounceValidator, import_queue::ImportQueue}; -use sp_runtime::{traits::Block as BlockT, ConsensusEngineId}; +use sp_runtime::traits::Block as BlockT; use std::{borrow::Cow, convert::TryFrom, future::Future, pin::Pin, str::FromStr}; use std::{ collections::HashMap, @@ -70,17 +70,6 @@ pub struct Params { /// Client that contains the blockchain. pub chain: Arc>, - /// Finality proof provider. - /// - /// This object, if `Some`, is used when a node on the network requests a proof of finality - /// from us. - pub finality_proof_provider: Option>>, - - /// How to build requests for proofs of finality. - /// - /// This object, if `Some`, is used when we need a proof of finality from another node. - pub finality_proof_request_builder: Option>, - /// The `OnDemand` object acts as a "receiver" for block data requests from the client. /// If `Some`, the network worker will process these requests and answer them. /// Normally used only for light clients. @@ -153,25 +142,6 @@ impl fmt::Display for Role { } } -/// Finality proof request builder. -pub trait FinalityProofRequestBuilder: Send { - /// Build data blob, associated with the request. - fn build_request_data(&mut self, hash: &B::Hash) -> Vec; -} - -/// Implementation of `FinalityProofRequestBuilder` that builds a dummy empty request. -#[derive(Debug, Default)] -pub struct DummyFinalityProofRequestBuilder; - -impl FinalityProofRequestBuilder for DummyFinalityProofRequestBuilder { - fn build_request_data(&mut self, _: &B::Hash) -> Vec { - Vec::new() - } -} - -/// Shared finality proof request builder struct used by the queue. -pub type BoxFinalityProofRequestBuilder = Box + Send + Sync>; - /// Result of the transaction import. #[derive(Clone, Copy, Debug)] pub enum TransactionImport { @@ -400,9 +370,8 @@ pub struct NetworkConfiguration { pub boot_nodes: Vec, /// The node key configuration, which determines the node's network identity keypair. pub node_key: NodeKeyConfig, - /// List of notifications protocols that the node supports. Must also include a - /// `ConsensusEngineId` for backwards-compatibility. - pub notifications_protocols: Vec<(ConsensusEngineId, Cow<'static, str>)>, + /// List of names of notifications protocols that the node supports. + pub notifications_protocols: Vec>, /// List of request-response protocols that the node supports. pub request_response_protocols: Vec, /// Maximum allowed number of incoming connections. diff --git a/client/network/src/discovery.rs b/client/network/src/discovery.rs index 60d35dbdf1ae0..717aec01f754a 100644 --- a/client/network/src/discovery.rs +++ b/client/network/src/discovery.rs @@ -693,7 +693,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { DiscoveryOut::ValueNotFound(e.into_key(), stats.duration().unwrap_or_else(Default::default)) } Err(e) => { - warn!(target: "sub-libp2p", + debug!(target: "sub-libp2p", "Libp2p => Failed to get record: {:?}", e); DiscoveryOut::ValueNotFound(e.into_key(), stats.duration().unwrap_or_else(Default::default)) } @@ -704,7 +704,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { let ev = match res { Ok(ok) => DiscoveryOut::ValuePut(ok.key, stats.duration().unwrap_or_else(Default::default)), Err(e) => { - warn!(target: "sub-libp2p", + debug!(target: "sub-libp2p", "Libp2p => Failed to put record: {:?}", e); DiscoveryOut::ValuePutFailed(e.into_key(), stats.duration().unwrap_or_else(Default::default)) } @@ -716,7 +716,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { Ok(ok) => debug!(target: "sub-libp2p", "Libp2p => Record republished: {:?}", ok.key), - Err(e) => warn!(target: "sub-libp2p", + Err(e) => debug!(target: "sub-libp2p", "Libp2p => Republishing of record {:?} failed with: {:?}", e.key(), e) } diff --git a/client/network/src/finality_requests.rs b/client/network/src/finality_requests.rs deleted file mode 100644 index 55f56b9a0cc25..0000000000000 --- a/client/network/src/finality_requests.rs +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. -// This file is part of Substrate. -// -// Substrate 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. -// -// Substrate 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 Substrate. If not, see . - -//! `NetworkBehaviour` implementation which handles incoming finality proof requests. -//! -//! Every request is coming in on a separate connection substream which gets -//! closed after we have sent the response back. Incoming requests are encoded -//! as protocol buffers (cf. `finality.v1.proto`). - -#![allow(unused)] - -use bytes::Bytes; -use codec::{Encode, Decode}; -use crate::{ - chain::FinalityProofProvider, - config::ProtocolId, - protocol::message, - schema, -}; -use futures::{future::BoxFuture, prelude::*, stream::FuturesUnordered}; -use libp2p::{ - core::{ - ConnectedPoint, - Multiaddr, - PeerId, - connection::ConnectionId, - upgrade::{InboundUpgrade, OutboundUpgrade, ReadOneError, UpgradeInfo, Negotiated}, - upgrade::{DeniedUpgrade, read_one, write_one} - }, - swarm::{ - NegotiatedSubstream, - NetworkBehaviour, - NetworkBehaviourAction, - NotifyHandler, - OneShotHandler, - OneShotHandlerConfig, - PollParameters, - SubstreamProtocol - } -}; -use prost::Message; -use sp_runtime::{generic::BlockId, traits::{Block, Header, One, Zero}}; -use std::{ - cmp::min, - collections::VecDeque, - io, - iter, - marker::PhantomData, - sync::Arc, - time::Duration, - task::{Context, Poll} -}; -use void::{Void, unreachable}; - -// Type alias for convenience. -pub type Error = Box; - -/// Event generated by the finality proof requests behaviour. -#[derive(Debug)] -pub enum Event { - /// A response to a finality proof request has arrived. - Response { - peer: PeerId, - /// Block hash originally passed to `send_request`. - block_hash: B::Hash, - /// Finality proof returned by the remote. - proof: Vec, - }, -} - -/// Configuration options for `FinalityProofRequests`. -#[derive(Debug, Clone)] -pub struct Config { - max_request_len: usize, - max_response_len: usize, - inactivity_timeout: Duration, - protocol: Bytes, -} - -impl Config { - /// Create a fresh configuration with the following options: - /// - /// - max. request size = 1 MiB - /// - max. response size = 1 MiB - /// - inactivity timeout = 15s - pub fn new(id: &ProtocolId) -> Self { - let mut c = Config { - max_request_len: 1024 * 1024, - max_response_len: 1024 * 1024, - inactivity_timeout: Duration::from_secs(15), - protocol: Bytes::new(), - }; - c.set_protocol(id); - c - } - - /// Limit the max. length of incoming finality proof request bytes. - pub fn set_max_request_len(&mut self, v: usize) -> &mut Self { - self.max_request_len = v; - self - } - - /// Limit the max. length of incoming finality proof response bytes. - pub fn set_max_response_len(&mut self, v: usize) -> &mut Self { - self.max_response_len = v; - self - } - - /// Limit the max. duration the substream may remain inactive before closing it. - pub fn set_inactivity_timeout(&mut self, v: Duration) -> &mut Self { - self.inactivity_timeout = v; - self - } - - /// Set protocol to use for upgrade negotiation. - pub fn set_protocol(&mut self, id: &ProtocolId) -> &mut Self { - let mut v = Vec::new(); - v.extend_from_slice(b"/"); - v.extend_from_slice(id.as_ref().as_bytes()); - v.extend_from_slice(b"/finality-proof/1"); - self.protocol = v.into(); - self - } -} - -/// The finality proof request handling behaviour. -pub struct FinalityProofRequests { - /// This behaviour's configuration. - config: Config, - /// How to construct finality proofs. - finality_proof_provider: Option>>, - /// Futures sending back the finality proof request responses. - outgoing: FuturesUnordered>, - /// Events to return as soon as possible from `poll`. - pending_events: VecDeque, Event>>, -} - -impl FinalityProofRequests -where - B: Block, -{ - /// Initializes the behaviour. - /// - /// If the proof provider is `None`, then the behaviour will not support the finality proof - /// requests protocol. - pub fn new(cfg: Config, finality_proof_provider: Option>>) -> Self { - FinalityProofRequests { - config: cfg, - finality_proof_provider, - outgoing: FuturesUnordered::new(), - pending_events: VecDeque::new(), - } - } - - /// Issue a new finality proof request. - /// - /// If the response doesn't arrive in time, or if the remote answers improperly, the target - /// will be disconnected. - pub fn send_request(&mut self, target: &PeerId, block_hash: B::Hash, request: Vec) { - let protobuf_rq = schema::v1::finality::FinalityProofRequest { - block_hash: block_hash.encode(), - request, - }; - - let mut buf = Vec::with_capacity(protobuf_rq.encoded_len()); - if let Err(err) = protobuf_rq.encode(&mut buf) { - log::warn!("failed to encode finality proof request {:?}: {:?}", protobuf_rq, err); - return; - } - - log::trace!("enqueueing finality proof request to {:?}: {:?}", target, protobuf_rq); - self.pending_events.push_back(NetworkBehaviourAction::NotifyHandler { - peer_id: target.clone(), - handler: NotifyHandler::Any, - event: OutboundProtocol { - request: buf, - block_hash, - max_response_size: self.config.max_response_len, - protocol: self.config.protocol.clone(), - }, - }); - } - - /// Callback, invoked when a new finality request has been received from remote. - fn on_finality_request(&mut self, peer: &PeerId, request: &schema::v1::finality::FinalityProofRequest) - -> Result - { - let block_hash = Decode::decode(&mut request.block_hash.as_ref())?; - - log::trace!(target: "sync", "Finality proof request from {} for {}", peer, block_hash); - - // Note that an empty Vec is sent if no proof is available. - let finality_proof = if let Some(provider) = &self.finality_proof_provider { - provider - .prove_finality(block_hash, &request.request)? - .unwrap_or_default() - } else { - log::error!("Answering a finality proof request while finality provider is empty"); - return Err(From::from("Empty finality proof provider".to_string())) - }; - - Ok(schema::v1::finality::FinalityProofResponse { proof: finality_proof }) - } -} - -impl NetworkBehaviour for FinalityProofRequests -where - B: Block -{ - type ProtocolsHandler = OneShotHandler, OutboundProtocol, NodeEvent>; - type OutEvent = Event; - - fn new_handler(&mut self) -> Self::ProtocolsHandler { - let p = InboundProtocol { - max_request_len: self.config.max_request_len, - protocol: if self.finality_proof_provider.is_some() { - Some(self.config.protocol.clone()) - } else { - None - }, - marker: PhantomData, - }; - let mut cfg = OneShotHandlerConfig::default(); - cfg.keep_alive_timeout = self.config.inactivity_timeout; - OneShotHandler::new(SubstreamProtocol::new(p, ()), cfg) - } - - fn addresses_of_peer(&mut self, _: &PeerId) -> Vec { - Vec::new() - } - - fn inject_connected(&mut self, _peer: &PeerId) { - } - - fn inject_disconnected(&mut self, _peer: &PeerId) { - } - - fn inject_event( - &mut self, - peer: PeerId, - connection: ConnectionId, - event: NodeEvent - ) { - match event { - NodeEvent::Request(request, mut stream) => { - match self.on_finality_request(&peer, &request) { - Ok(res) => { - log::trace!("enqueueing finality response for peer {}", peer); - let mut data = Vec::with_capacity(res.encoded_len()); - if let Err(e) = res.encode(&mut data) { - log::debug!("error encoding finality response for peer {}: {}", peer, e) - } else { - let future = async move { - if let Err(e) = write_one(&mut stream, data).await { - log::debug!("error writing finality response: {}", e) - } - }; - self.outgoing.push(future.boxed()) - } - } - Err(e) => log::debug!("error handling finality request from peer {}: {}", peer, e) - } - } - NodeEvent::Response(response, block_hash) => { - let ev = Event::Response { - peer, - block_hash, - proof: response.proof, - }; - self.pending_events.push_back(NetworkBehaviourAction::GenerateEvent(ev)); - } - } - } - - fn poll(&mut self, cx: &mut Context, _: &mut impl PollParameters) - -> Poll, Event>> - { - if let Some(ev) = self.pending_events.pop_front() { - return Poll::Ready(ev); - } - - while let Poll::Ready(Some(_)) = self.outgoing.poll_next_unpin(cx) {} - Poll::Pending - } -} - -/// Output type of inbound and outbound substream upgrades. -#[derive(Debug)] -pub enum NodeEvent { - /// Incoming request from remote and substream to use for the response. - Request(schema::v1::finality::FinalityProofRequest, T), - /// Incoming response from remote. - Response(schema::v1::finality::FinalityProofResponse, B::Hash), -} - -/// Substream upgrade protocol. -/// -/// We attempt to parse an incoming protobuf encoded request (cf. `Request`) -/// which will be handled by the `FinalityProofRequests` behaviour, i.e. the request -/// will become visible via `inject_node_event` which then dispatches to the -/// relevant callback to process the message and prepare a response. -#[derive(Debug, Clone)] -pub struct InboundProtocol { - /// The max. request length in bytes. - max_request_len: usize, - /// The protocol to use during upgrade negotiation. If `None`, then the incoming protocol - /// is simply disabled. - protocol: Option, - /// Marker to pin the block type. - marker: PhantomData, -} - -impl UpgradeInfo for InboundProtocol { - type Info = Bytes; - // This iterator will return either 0 elements if `self.protocol` is `None`, or 1 element if - // it is `Some`. - type InfoIter = std::option::IntoIter; - - fn protocol_info(&self) -> Self::InfoIter { - self.protocol.clone().into_iter() - } -} - -impl InboundUpgrade for InboundProtocol -where - B: Block, - T: AsyncRead + AsyncWrite + Unpin + Send + 'static -{ - type Output = NodeEvent; - type Error = ReadOneError; - type Future = BoxFuture<'static, Result>; - - fn upgrade_inbound(self, mut s: T, _: Self::Info) -> Self::Future { - async move { - let len = self.max_request_len; - let vec = read_one(&mut s, len).await?; - match schema::v1::finality::FinalityProofRequest::decode(&vec[..]) { - Ok(r) => Ok(NodeEvent::Request(r, s)), - Err(e) => Err(ReadOneError::Io(io::Error::new(io::ErrorKind::Other, e))) - } - }.boxed() - } -} - -/// Substream upgrade protocol. -/// -/// Sends a request to remote and awaits the response. -#[derive(Debug, Clone)] -pub struct OutboundProtocol { - /// The serialized protobuf request. - request: Vec, - /// Block hash that has been requested. - block_hash: B::Hash, - /// The max. response length in bytes. - max_response_size: usize, - /// The protocol to use for upgrade negotiation. - protocol: Bytes, -} - -impl UpgradeInfo for OutboundProtocol { - type Info = Bytes; - type InfoIter = iter::Once; - - fn protocol_info(&self) -> Self::InfoIter { - iter::once(self.protocol.clone()) - } -} - -impl OutboundUpgrade for OutboundProtocol -where - B: Block, - T: AsyncRead + AsyncWrite + Unpin + Send + 'static -{ - type Output = NodeEvent; - type Error = ReadOneError; - type Future = BoxFuture<'static, Result>; - - fn upgrade_outbound(self, mut s: T, _: Self::Info) -> Self::Future { - async move { - write_one(&mut s, &self.request).await?; - let vec = read_one(&mut s, self.max_response_size).await?; - - schema::v1::finality::FinalityProofResponse::decode(&vec[..]) - .map(|r| NodeEvent::Response(r, self.block_hash)) - .map_err(|e| { - ReadOneError::Io(io::Error::new(io::ErrorKind::Other, e)) - }) - }.boxed() - } -} diff --git a/client/network/src/gossip.rs b/client/network/src/gossip.rs index 9d20229288a42..ac3f92e9d37aa 100644 --- a/client/network/src/gossip.rs +++ b/client/network/src/gossip.rs @@ -53,8 +53,9 @@ use async_std::sync::{Mutex, MutexGuard}; use futures::prelude::*; use futures::channel::mpsc::{channel, Receiver, Sender}; use libp2p::PeerId; -use sp_runtime::{traits::Block as BlockT, ConsensusEngineId}; +use sp_runtime::traits::Block as BlockT; use std::{ + borrow::Cow, collections::VecDeque, fmt, sync::Arc, @@ -82,7 +83,7 @@ impl QueuedSender { pub fn new( service: Arc>, peer_id: PeerId, - protocol: ConsensusEngineId, + protocol: Cow<'static, str>, queue_size_limit: usize, messages_encode: F ) -> (Self, impl Future + Send + 'static) @@ -193,7 +194,7 @@ async fn create_background_future Vec> mut wait_for_sender: Receiver<()>, service: Arc>, peer_id: PeerId, - protocol: ConsensusEngineId, + protocol: Cow<'static, str>, shared_message_queue: SharedMessageQueue, messages_encode: F, ) { @@ -212,7 +213,7 @@ async fn create_background_future Vec> // Starting from below, we try to send the message. If an error happens when sending, // the only sane option we have is to silently discard the message. - let sender = match service.notification_sender(peer_id.clone(), protocol) { + let sender = match service.notification_sender(peer_id.clone(), protocol.clone()) { Ok(s) => s, Err(_) => continue, }; diff --git a/client/network/src/gossip/tests.rs b/client/network/src/gossip/tests.rs index 0f01ed81bffcb..93b69f7b64c8e 100644 --- a/client/network/src/gossip/tests.rs +++ b/client/network/src/gossip/tests.rs @@ -20,7 +20,7 @@ use crate::{config, gossip::QueuedSender, Event, NetworkService, NetworkWorker}; use futures::prelude::*; use sp_runtime::traits::{Block as BlockT, Header as _}; -use std::{sync::Arc, time::Duration}; +use std::{borrow::Cow, sync::Arc, time::Duration}; use substrate_test_runtime_client::{TestClientBuilder, TestClientBuilderExt as _}; type TestNetworkService = NetworkService< @@ -86,7 +86,6 @@ fn build_test_full_node(config: config::NetworkConfiguration) PassThroughVerifier(false), Box::new(client.clone()), None, - None, &sp_core::testing::TaskExecutor::new(), None, )); @@ -96,8 +95,6 @@ fn build_test_full_node(config: config::NetworkConfiguration) executor: None, network_config: config, chain: client.clone(), - finality_proof_provider: None, - finality_proof_request_builder: None, on_demand: None, transaction_pool: Arc::new(crate::config::EmptyTransactionPool), protocol_id: config::ProtocolId::from("/test-protocol-name"), @@ -120,24 +117,24 @@ fn build_test_full_node(config: config::NetworkConfiguration) (service, event_stream) } -const ENGINE_ID: sp_runtime::ConsensusEngineId = *b"foo\0"; +const PROTOCOL_NAME: Cow<'static, str> = Cow::Borrowed("/foo"); /// Builds two nodes and their associated events stream. -/// The nodes are connected together and have the `ENGINE_ID` protocol registered. +/// The nodes are connected together and have the `PROTOCOL_NAME` protocol registered. fn build_nodes_one_proto() -> (Arc, impl Stream, Arc, impl Stream) { let listen_addr = config::build_multiaddr![Memory(rand::random::())]; let (node1, events_stream1) = build_test_full_node(config::NetworkConfiguration { - notifications_protocols: vec![(ENGINE_ID, From::from("/foo"))], + notifications_protocols: vec![PROTOCOL_NAME], listen_addresses: vec![listen_addr.clone()], transport: config::TransportConfig::MemoryOnly, .. config::NetworkConfiguration::new_local() }); let (node2, events_stream2) = build_test_full_node(config::NetworkConfiguration { - notifications_protocols: vec![(ENGINE_ID, From::from("/foo"))], + notifications_protocols: vec![PROTOCOL_NAME], listen_addresses: vec![], reserved_nodes: vec![config::MultiaddrWithPeerId { multiaddr: listen_addr, @@ -165,7 +162,7 @@ fn basic_works() { Event::NotificationStreamClosed { .. } => panic!(), Event::NotificationsReceived { messages, .. } => { for message in messages { - assert_eq!(message.0, ENGINE_ID); + assert_eq!(message.0, PROTOCOL_NAME); assert_eq!(message.1, &b"message"[..]); received_notifications += 1; } @@ -181,7 +178,7 @@ fn basic_works() { async_std::task::block_on(async move { let (mut sender, bg_future) = - QueuedSender::new(node1, node2_id, ENGINE_ID, NUM_NOTIFS, |msg| msg); + QueuedSender::new(node1, node2_id, PROTOCOL_NAME, NUM_NOTIFS, |msg| msg); async_std::task::spawn(bg_future); // Wait for the `NotificationStreamOpened`. diff --git a/client/network/src/lib.rs b/client/network/src/lib.rs index 3fd01c33dcf5f..b050db8785ac1 100644 --- a/client/network/src/lib.rs +++ b/client/network/src/lib.rs @@ -249,7 +249,6 @@ mod block_requests; mod chain; mod peer_info; mod discovery; -mod finality_requests; mod light_client_handler; mod on_demand_layer; mod protocol; diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index 9403e471b0f27..597031b90182c 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -19,7 +19,7 @@ use crate::{ ExHashT, chain::Client, - config::{BoxFinalityProofRequestBuilder, ProtocolId, TransactionPool, TransactionImportFuture, TransactionImport}, + config::{ProtocolId, TransactionPool, TransactionImportFuture, TransactionImport}, error, utils::{interval, LruHashSet}, }; @@ -37,7 +37,7 @@ use sp_consensus::{ import_queue::{BlockImportResult, BlockImportError, IncomingBlock, Origin} }; use codec::{Decode, DecodeAll, Encode}; -use sp_runtime::{generic::BlockId, ConsensusEngineId, Justification}; +use sp_runtime::{generic::BlockId, Justification}; use sp_runtime::traits::{ Block as BlockT, Header as HeaderT, NumberFor, Zero, CheckedSub }; @@ -131,7 +131,6 @@ struct Metrics { peers: Gauge, queued_blocks: Gauge, fork_targets: Gauge, - finality_proofs: GaugeVec, justifications: GaugeVec, propagated_transactions: Counter, } @@ -165,16 +164,6 @@ impl Metrics { )?; register(g, r)? }, - finality_proofs: { - let g = GaugeVec::new( - Opts::new( - "sync_extra_finality_proofs", - "Number of extra finality proof requests", - ), - &["status"], - )?; - register(g, r)? - }, propagated_transactions: register(Counter::new( "sync_propagated_transactions", "Number of transactions propagated to at least one peer", @@ -231,8 +220,8 @@ pub struct Protocol { transaction_pool: Arc>, /// Handles opening the unique substream and sending and receiving raw messages. behaviour: GenericProto, - /// For each legacy gossiping engine ID, the corresponding new protocol name. - protocol_name_by_engine: HashMap>, + /// List of notifications protocols that have been registered. + notification_protocols: Vec>, /// For each protocol name, the legacy equivalent. legacy_equiv_by_name: HashMap, Fallback>, /// Name of the protocol used for transactions. @@ -252,6 +241,7 @@ struct PacketStats { count_in: u64, count_out: u64, } + /// Peer information #[derive(Debug, Clone)] struct Peer { @@ -349,8 +339,8 @@ fn build_status_message(protocol_config: &ProtocolConfig, chain: &Arc /// Fallback mechanism to use to send a notification if no substream is open. #[derive(Debug, Clone, PartialEq, Eq)] enum Fallback { - /// Use a `Message::Consensus` with the given engine ID. - Consensus(ConsensusEngineId), + /// Formerly-known as `Consensus` messages. Now regular notifications. + Consensus, /// The message is the bytes encoding of a `Transactions` (which is itself defined as a `Vec`). Transactions, /// The message is the bytes encoding of a `BlockAnnounce`. @@ -364,7 +354,6 @@ impl Protocol { local_peer_id: PeerId, chain: Arc>, transaction_pool: Arc>, - finality_proof_request_builder: Option>, protocol_id: ProtocolId, peerset_config: sc_peerset::PeersetConfig, block_announce_validator: Box + Send>, @@ -376,7 +365,6 @@ impl Protocol { config.roles, chain.clone(), &info, - finality_proof_request_builder, block_announce_validator, config.max_parallel_downloads, ); @@ -446,7 +434,7 @@ impl Protocol { transaction_pool, peerset_handle: peerset_handle.clone(), behaviour, - protocol_name_by_engine: HashMap::new(), + notification_protocols: Vec::new(), legacy_equiv_by_name, transactions_protocol, block_announces_protocol, @@ -613,15 +601,14 @@ impl Protocol { warn!(target: "sub-libp2p", "Received unexpected RemoteHeaderResponse"), GenericMessage::RemoteChangesResponse(_) => warn!(target: "sub-libp2p", "Received unexpected RemoteChangesResponse"), - GenericMessage::FinalityProofResponse(_) => - warn!(target: "sub-libp2p", "Received unexpected FinalityProofResponse"), GenericMessage::BlockRequest(_) | - GenericMessage::FinalityProofRequest(_) | GenericMessage::RemoteReadChildRequest(_) | GenericMessage::RemoteCallRequest(_) | GenericMessage::RemoteReadRequest(_) | GenericMessage::RemoteHeaderRequest(_) | - GenericMessage::RemoteChangesRequest(_) => { + GenericMessage::RemoteChangesRequest(_) | + GenericMessage::Consensus(_) | + GenericMessage::ConsensusBatch(_) => { debug!( target: "sub-libp2p", "Received no longer supported legacy request from {:?}", @@ -630,38 +617,6 @@ impl Protocol { self.disconnect_peer(&who); self.peerset_handle.report_peer(who, rep::BAD_PROTOCOL); }, - GenericMessage::Consensus(msg) => - return if self.protocol_name_by_engine.contains_key(&msg.engine_id) { - CustomMessageOutcome::NotificationsReceived { - remote: who, - messages: vec![(msg.engine_id, From::from(msg.data))], - } - } else { - debug!(target: "sync", "Received message on non-registered protocol: {:?}", msg.engine_id); - CustomMessageOutcome::None - }, - GenericMessage::ConsensusBatch(messages) => { - let messages = messages - .into_iter() - .filter_map(|msg| { - if self.protocol_name_by_engine.contains_key(&msg.engine_id) { - Some((msg.engine_id, From::from(msg.data))) - } else { - debug!(target: "sync", "Received message on non-registered protocol: {:?}", msg.engine_id); - None - } - }) - .collect::>(); - - return if !messages.is_empty() { - CustomMessageOutcome::NotificationsReceived { - remote: who, - messages, - } - } else { - CustomMessageOutcome::None - }; - }, } CustomMessageOutcome::None @@ -685,7 +640,7 @@ impl Protocol { // Notify all the notification protocols as closed. CustomMessageOutcome::NotificationStreamClosed { remote: peer, - protocols: self.protocol_name_by_engine.keys().cloned().collect(), + protocols: self.notification_protocols.clone(), } } else { CustomMessageOutcome::None @@ -939,7 +894,7 @@ impl Protocol { // Notify all the notification protocols as open. CustomMessageOutcome::NotificationStreamOpened { remote: who, - protocols: self.protocol_name_by_engine.keys().cloned().collect(), + protocols: self.notification_protocols.clone(), roles: info.roles, notifications_sink, } @@ -952,16 +907,17 @@ impl Protocol { /// returns a list of substreams to open as a result. pub fn register_notifications_protocol<'a>( &'a mut self, - engine_id: ConsensusEngineId, - protocol_name: impl Into>, + protocol: impl Into>, handshake_message: Vec, ) -> impl Iterator + 'a { - let protocol_name = protocol_name.into(); - if self.protocol_name_by_engine.insert(engine_id, protocol_name.clone()).is_some() { - error!(target: "sub-libp2p", "Notifications protocol already registered: {:?}", protocol_name); + let protocol = protocol.into(); + + if self.notification_protocols.iter().any(|p| *p == protocol) { + error!(target: "sub-libp2p", "Notifications protocol already registered: {:?}", protocol); } else { - self.behaviour.register_notif_protocol(protocol_name.clone(), handshake_message); - self.legacy_equiv_by_name.insert(protocol_name, Fallback::Consensus(engine_id)); + self.notification_protocols.push(protocol.clone()); + self.behaviour.register_notif_protocol(protocol.clone(), handshake_message); + self.legacy_equiv_by_name.insert(protocol, Fallback::Consensus); } let behaviour = &self.behaviour; @@ -1342,13 +1298,6 @@ impl Protocol { self.sync.on_justification_import(hash, number, success) } - /// Request a finality proof for the given block. - /// - /// Queues a new finality proof request and tries to dispatch all pending requests. - pub fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor) { - self.sync.request_finality_proof(&hash, number) - } - /// Notify the protocol that we have learned about the existence of nodes. /// /// Can be called multiple times with the same `PeerId`s. @@ -1356,34 +1305,6 @@ impl Protocol { self.behaviour.add_discovered_nodes(peer_ids) } - pub fn finality_proof_import_result( - &mut self, - request_block: (B::Hash, NumberFor), - finalization_result: Result<(B::Hash, NumberFor), ()>, - ) { - self.sync.on_finality_proof_import(request_block, finalization_result) - } - - /// Must be called after a [`CustomMessageOutcome::FinalityProofRequest`] has been emitted, - /// to notify of the response having arrived. - pub fn on_finality_proof_response( - &mut self, - who: PeerId, - response: message::FinalityProofResponse, - ) -> CustomMessageOutcome { - trace!(target: "sync", "Finality proof response from {} for {}", who, response.block); - match self.sync.on_block_finality_proof(who, response) { - Ok(sync::OnBlockFinalityProof::Nothing) => CustomMessageOutcome::None, - Ok(sync::OnBlockFinalityProof::Import { peer, hash, number, proof }) => - CustomMessageOutcome::FinalityProofImport(peer, hash, number, proof), - Err(sync::BadPeer(id, repu)) => { - self.behaviour.disconnect_peer(&id); - self.peerset_handle.report_peer(id, repu); - CustomMessageOutcome::None - } - } - } - fn format_stats(&self) -> String { let mut out = String::new(); for (id, stats) in &self.context_data.stats { @@ -1427,15 +1348,6 @@ impl Protocol { .set(m.justifications.failed_requests.into()); metrics.justifications.with_label_values(&["importing"]) .set(m.justifications.importing_requests.into()); - - metrics.finality_proofs.with_label_values(&["pending"]) - .set(m.finality_proofs.pending_requests.into()); - metrics.finality_proofs.with_label_values(&["active"]) - .set(m.finality_proofs.active_requests.into()); - metrics.finality_proofs.with_label_values(&["failed"]) - .set(m.finality_proofs.failed_requests.into()); - metrics.finality_proofs.with_label_values(&["importing"]) - .set(m.finality_proofs.importing_requests.into()); } } } @@ -1446,24 +1358,23 @@ impl Protocol { pub enum CustomMessageOutcome { BlockImport(BlockOrigin, Vec>), JustificationImport(Origin, B::Hash, NumberFor, Justification), - FinalityProofImport(Origin, B::Hash, NumberFor, Vec), /// Notification protocols have been opened with a remote. NotificationStreamOpened { remote: PeerId, - protocols: Vec, + protocols: Vec>, roles: Roles, notifications_sink: NotificationsSink }, /// The [`NotificationsSink`] of some notification protocols need an update. NotificationStreamReplaced { remote: PeerId, - protocols: Vec, + protocols: Vec>, notifications_sink: NotificationsSink, }, /// Notification protocols have been closed with a remote. - NotificationStreamClosed { remote: PeerId, protocols: Vec }, + NotificationStreamClosed { remote: PeerId, protocols: Vec> }, /// Messages have been received on one or more notifications protocols. - NotificationsReceived { remote: PeerId, messages: Vec<(ConsensusEngineId, Bytes)> }, + NotificationsReceived { remote: PeerId, messages: Vec<(Cow<'static, str>, Bytes)> }, /// A new block request must be emitted. /// You must later call either [`Protocol::on_block_response`] or /// [`Protocol::on_block_request_failed`]. @@ -1471,12 +1382,6 @@ pub enum CustomMessageOutcome { /// must be silently discarded. /// It is the responsibility of the handler to ensure that a timeout exists. BlockRequest { target: PeerId, request: message::BlockRequest }, - /// A new finality proof request must be emitted. - /// Once you have the response, you must call `Protocol::on_finality_proof_response`. - /// It is the responsibility of the handler to ensure that a timeout exists. - /// If the request times out, or the peer responds in an invalid way, the peer has to be - /// disconnect. This will inform the state machine that the request it has emitted is stale. - FinalityProofRequest { target: PeerId, block_hash: B::Hash, request: Vec }, /// Peer has a reported a new head of chain. PeerNewBest(PeerId, NumberFor), None, @@ -1573,14 +1478,6 @@ impl NetworkBehaviour for Protocol { }; self.pending_messages.push_back(event); } - for (id, r) in self.sync.finality_proof_requests() { - let event = CustomMessageOutcome::FinalityProofRequest { - target: id, - block_hash: r.block, - request: r.request, - }; - self.pending_messages.push_back(event); - } if let Poll::Ready(Some((tx_hash, result))) = self.pending_transactions.poll_next_unpin(cx) { if let Some(peers) = self.pending_transactions_peers.remove(&tx_hash) { peers.into_iter().for_each(|p| self.on_handle_transaction_import(p, result)); @@ -1664,7 +1561,7 @@ impl NetworkBehaviour for Protocol { GenericProtoOut::CustomProtocolReplaced { peer_id, notifications_sink, .. } => { CustomMessageOutcome::NotificationStreamReplaced { remote: peer_id, - protocols: self.protocol_name_by_engine.keys().cloned().collect(), + protocols: self.notification_protocols.clone(), notifications_sink, } }, @@ -1675,10 +1572,10 @@ impl NetworkBehaviour for Protocol { self.on_custom_message(peer_id, message), GenericProtoOut::Notification { peer_id, protocol_name, message } => match self.legacy_equiv_by_name.get(&protocol_name) { - Some(Fallback::Consensus(engine_id)) => { + Some(Fallback::Consensus) => { CustomMessageOutcome::NotificationsReceived { remote: peer_id, - messages: vec![(*engine_id, message.freeze())], + messages: vec![(protocol_name, message.freeze())], } } Some(Fallback::Transactions) => { diff --git a/client/network/src/protocol/event.rs b/client/network/src/protocol/event.rs index 637bf805b5024..86cb93bef26dd 100644 --- a/client/network/src/protocol/event.rs +++ b/client/network/src/protocol/event.rs @@ -20,7 +20,7 @@ use bytes::Bytes; use libp2p::core::PeerId; use libp2p::kad::record::Key; -use sp_runtime::ConsensusEngineId; +use std::borrow::Cow; /// Events generated by DHT as a response to get_value and put_value requests. #[derive(Debug, Clone)] @@ -53,7 +53,7 @@ pub enum Event { /// Node we opened the substream with. remote: PeerId, /// The concerned protocol. Each protocol uses a different substream. - engine_id: ConsensusEngineId, + protocol: Cow<'static, str>, /// Role of the remote. role: ObservedRole, }, @@ -64,7 +64,7 @@ pub enum Event { /// Node we closed the substream with. remote: PeerId, /// The concerned protocol. Each protocol uses a different substream. - engine_id: ConsensusEngineId, + protocol: Cow<'static, str>, }, /// Received one or more messages from the given node using the given protocol. @@ -72,7 +72,7 @@ pub enum Event { /// Node we received the message from. remote: PeerId, /// Concerned protocol and associated message. - messages: Vec<(ConsensusEngineId, Bytes)>, + messages: Vec<(Cow<'static, str>, Bytes)>, }, } diff --git a/client/network/src/protocol/generic_proto/handler.rs b/client/network/src/protocol/generic_proto/handler.rs index 0272261f67d57..c8a76c1cc9a4e 100644 --- a/client/network/src/protocol/generic_proto/handler.rs +++ b/client/network/src/protocol/generic_proto/handler.rs @@ -715,7 +715,7 @@ impl ProtocolsHandler for NotifsHandler { }, NotifsHandlerIn::Close => { - for mut substream in self.legacy_substreams.drain() { + for mut substream in self.legacy_substreams.drain(..) { substream.shutdown(); self.legacy_shutdown.push(substream); } diff --git a/client/network/src/protocol/message.rs b/client/network/src/protocol/message.rs index 1cd78c0ed1dda..4213d56bbf022 100644 --- a/client/network/src/protocol/message.rs +++ b/client/network/src/protocol/message.rs @@ -25,7 +25,6 @@ pub use self::generic::{ BlockAnnounce, RemoteCallRequest, RemoteReadRequest, RemoteHeaderRequest, RemoteHeaderResponse, RemoteChangesRequest, RemoteChangesResponse, - FinalityProofRequest, FinalityProofResponse, FromBlock, RemoteReadChildRequest, Roles, }; use sc_client_api::StorageProof; @@ -216,7 +215,7 @@ pub mod generic { #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] pub struct ConsensusMessage { /// Identifies consensus engine. - pub engine_id: ConsensusEngineId, + pub protocol: ConsensusEngineId, /// Message payload. pub data: Vec, } @@ -280,11 +279,10 @@ pub mod generic { RemoteChangesResponse(RemoteChangesResponse), /// Remote child storage read request. RemoteReadChildRequest(RemoteReadChildRequest), - /// Finality proof request. - FinalityProofRequest(FinalityProofRequest), - /// Finality proof response. - FinalityProofResponse(FinalityProofResponse), /// Batch of consensus protocol messages. + // NOTE: index is incremented by 2 due to finality proof related + // messages that were removed. + #[codec(index = "17")] ConsensusBatch(Vec), } @@ -307,8 +305,6 @@ pub mod generic { Message::RemoteChangesRequest(_) => "RemoteChangesRequest", Message::RemoteChangesResponse(_) => "RemoteChangesResponse", Message::RemoteReadChildRequest(_) => "RemoteReadChildRequest", - Message::FinalityProofRequest(_) => "FinalityProofRequest", - Message::FinalityProofResponse(_) => "FinalityProofResponse", Message::ConsensusBatch(_) => "ConsensusBatch", } } @@ -546,26 +542,4 @@ pub mod generic { /// Missing changes tries roots proof. pub roots_proof: StorageProof, } - - #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] - /// Finality proof request. - pub struct FinalityProofRequest { - /// Unique request id. - pub id: RequestId, - /// Hash of the block to request proof for. - pub block: H, - /// Additional data blob (that both requester and provider understood) required for proving finality. - pub request: Vec, - } - - #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] - /// Finality proof response. - pub struct FinalityProofResponse { - /// Id of a request this response was made for. - pub id: RequestId, - /// Hash of the block (the same as in the FinalityProofRequest). - pub block: H, - /// Finality proof (if available). - pub proof: Option>, - } } diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index 03714b05ace0d..ced789446da60 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -35,9 +35,7 @@ use sp_consensus::{BlockOrigin, BlockStatus, import_queue::{IncomingBlock, BlockImportResult, BlockImportError} }; use crate::{ - config::BoxFinalityProofRequestBuilder, - protocol::message::{self, generic::FinalityProofRequest, BlockAnnounce, BlockAttributes, BlockRequest, BlockResponse, - FinalityProofResponse, Roles}, + protocol::message::{self, BlockAnnounce, BlockAttributes, BlockRequest, BlockResponse, Roles}, }; use either::Either; use extra_requests::ExtraRequests; @@ -116,9 +114,6 @@ mod rep { /// Reputation change for peers which send us a block with bad justifications. pub const BAD_JUSTIFICATION: Rep = Rep::new(-(1 << 16), "Bad justification"); - /// Reputation change for peers which send us a block with bad finality proof. - pub const BAD_FINALITY_PROOF: Rep = Rep::new(-(1 << 16), "Bad finality proof"); - /// Reputation change when a peer sent us invlid ancestry result. pub const UNKNOWN_ANCESTOR:Rep = Rep::new(-(1 << 16), "DB Error"); } @@ -185,8 +180,6 @@ pub struct ChainSync { /// What block attributes we require for this node, usually derived from /// what role we are, but could be customized required_block_attributes: message::BlockAttributes, - /// Any extra finality proof requests. - extra_finality_proofs: ExtraRequests, /// Any extra justification requests. extra_justifications: ExtraRequests, /// A set of hashes of blocks that are being downloaded or have been @@ -195,8 +188,6 @@ pub struct ChainSync { /// The best block number that was successfully imported into the chain. /// This can not decrease. best_imported_number: NumberFor, - /// Finality proof handler. - request_builder: Option>, /// Fork sync targets. fork_targets: HashMap>, /// A set of peers for which there might be potential block requests @@ -270,8 +261,6 @@ pub enum PeerSyncState { DownloadingStale(B::Hash), /// Downloading justification for given block hash. DownloadingJustification(B::Hash), - /// Downloading finality proof for given block hash. - DownloadingFinalityProof(B::Hash) } impl PeerSyncState { @@ -402,20 +391,6 @@ pub enum OnBlockJustification { } } -/// Result of [`ChainSync::on_block_finality_proof`]. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum OnBlockFinalityProof { - /// The proof needs no further handling. - Nothing, - /// The proof should be imported. - Import { - peer: PeerId, - hash: B::Hash, - number: NumberFor, - proof: Vec - } -} - /// Result of [`ChainSync::has_slot_for_block_announce_validation`]. enum HasSlotForBlockAnnounceValidation { /// Yes, there is a slot for the block announce validation. @@ -432,7 +407,6 @@ impl ChainSync { role: Roles, client: Arc>, info: &BlockchainInfo, - request_builder: Option>, block_announce_validator: Box + Send>, max_parallel_downloads: u32, ) -> Self { @@ -449,12 +423,10 @@ impl ChainSync { best_queued_hash: info.best_hash, best_queued_number: info.best_number, best_imported_number: info.best_number, - extra_finality_proofs: ExtraRequests::new("finality proof"), extra_justifications: ExtraRequests::new("justification"), role, required_block_attributes, queue_blocks: Default::default(), - request_builder, fork_targets: Default::default(), pending_requests: Default::default(), block_announce_validator, @@ -613,14 +585,6 @@ impl ChainSync { }) } - /// Schedule a finality proof request for the given block. - pub fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor) { - let client = &self.client; - self.extra_finality_proofs.schedule((*hash, number), |base, block| { - is_descendent_of(&**client, base, block) - }) - } - /// Request syncing for the given block from given set of peers. // The implementation is similar to on_block_announce with unknown parent hash. pub fn set_sync_fork_request( @@ -700,30 +664,6 @@ impl ChainSync { }) } - /// Get an iterator over all scheduled finality proof requests. - pub fn finality_proof_requests(&mut self) -> impl Iterator)> + '_ { - let peers = &mut self.peers; - let request_builder = &mut self.request_builder; - let mut matcher = self.extra_finality_proofs.matcher(); - std::iter::from_fn(move || { - if let Some((peer, request)) = matcher.next(&peers) { - peers.get_mut(&peer) - .expect("`Matcher::next` guarantees the `PeerId` comes from the given peers; qed") - .state = PeerSyncState::DownloadingFinalityProof(request.0); - let req = message::generic::FinalityProofRequest { - id: 0, - block: request.0, - request: request_builder.as_mut() - .map(|builder| builder.build_request_data(&request.0)) - .unwrap_or_default() - }; - Some((peer, req)) - } else { - None - } - }) - } - /// Get an iterator over all block requests of all peers. pub fn block_requests(&mut self) -> impl Iterator)> + '_ { if self.pending_requests.is_empty() { @@ -920,8 +860,7 @@ impl ChainSync { } | PeerSyncState::Available - | PeerSyncState::DownloadingJustification(..) - | PeerSyncState::DownloadingFinalityProof(..) => Vec::new() + | PeerSyncState::DownloadingJustification(..) => Vec::new() } } else { // When request.is_none() this is a block announcement. Just accept blocks. @@ -1033,41 +972,6 @@ impl ChainSync { Ok(OnBlockJustification::Nothing) } - /// Handle new finality proof data. - pub fn on_block_finality_proof - (&mut self, who: PeerId, resp: FinalityProofResponse) -> Result, BadPeer> - { - let peer = - if let Some(peer) = self.peers.get_mut(&who) { - peer - } else { - error!(target: "sync", "💔 Called on_block_finality_proof_data with a bad peer ID"); - return Ok(OnBlockFinalityProof::Nothing) - }; - - self.pending_requests.add(&who); - if let PeerSyncState::DownloadingFinalityProof(hash) = peer.state { - peer.state = PeerSyncState::Available; - - // We only request one finality proof at a time. - if hash != resp.block { - info!( - target: "sync", - "💔 Invalid block finality proof provided: requested: {:?} got: {:?}", - hash, - resp.block - ); - return Err(BadPeer(who, rep::BAD_FINALITY_PROOF)); - } - - if let Some((peer, hash, number, p)) = self.extra_finality_proofs.on_response(who, resp.proof) { - return Ok(OnBlockFinalityProof::Import { peer, hash, number, proof: p }) - } - } - - Ok(OnBlockFinalityProof::Nothing) - } - /// A batch of blocks have been processed, with or without errors. /// /// Call this when a batch of blocks have been processed by the import @@ -1122,11 +1026,6 @@ impl ChainSync { } } - if aux.needs_finality_proof { - trace!(target: "sync", "Block imported but requires finality proof {}: {:?}", number, hash); - self.request_finality_proof(&hash, number); - } - if number > self.best_imported_number { self.best_imported_number = number; } @@ -1178,22 +1077,8 @@ impl ChainSync { self.pending_requests.set_all(); } - pub fn on_finality_proof_import(&mut self, req: (B::Hash, NumberFor), res: Result<(B::Hash, NumberFor), ()>) { - self.extra_finality_proofs.try_finalize_root(req, res, true); - self.pending_requests.set_all(); - } - /// Notify about finalization of the given block. pub fn on_block_finalized(&mut self, hash: &B::Hash, number: NumberFor) { - let client = &self.client; - let r = self.extra_finality_proofs.on_block_finalized(hash, number, |base, block| { - is_descendent_of(&**client, base, block) - }); - - if let Err(err) = r { - warn!(target: "sync", "💔 Error cleaning up pending extra finality proof data requests: {:?}", err) - } - let client = &self.client; let r = self.extra_justifications.on_block_finalized(hash, number, |base, block| { is_descendent_of(&**client, base, block) @@ -1506,14 +1391,12 @@ impl ChainSync { self.blocks.clear_peer_download(who); self.peers.remove(who); self.extra_justifications.peer_disconnected(who); - self.extra_finality_proofs.peer_disconnected(who); self.pending_requests.set_all(); } /// Restart the sync process. This will reset all pending block requests and return an iterator /// of new block requests to make to peers. Peers that were downloading finality data (i.e. - /// their state was `DownloadingJustification` or `DownloadingFinalityProof`) are unaffected and - /// will stay in the same state. + /// their state was `DownloadingJustification`) are unaffected and will stay in the same state. fn restart<'a>( &'a mut self, ) -> impl Iterator), BadPeer>> + 'a { @@ -1526,11 +1409,10 @@ impl ChainSync { let old_peers = std::mem::take(&mut self.peers); old_peers.into_iter().filter_map(move |(id, p)| { - // peers that were downloading justifications or finality proofs + // peers that were downloading justifications // should be kept in that state. match p.state { - PeerSyncState::DownloadingJustification(_) - | PeerSyncState::DownloadingFinalityProof(_) => { + PeerSyncState::DownloadingJustification(_) => { self.peers.insert(id, p); return None; } @@ -1570,7 +1452,6 @@ impl ChainSync { Metrics { queued_blocks: self.queue_blocks.len().try_into().unwrap_or(std::u32::MAX), fork_targets: self.fork_targets.len().try_into().unwrap_or(std::u32::MAX), - finality_proofs: self.extra_finality_proofs.metrics(), justifications: self.extra_justifications.metrics(), _priv: () } @@ -1581,7 +1462,6 @@ impl ChainSync { pub(crate) struct Metrics { pub(crate) queued_blocks: u32, pub(crate) fork_targets: u32, - pub(crate) finality_proofs: extra_requests::Metrics, pub(crate) justifications: extra_requests::Metrics, _priv: () } @@ -1835,7 +1715,6 @@ mod test { Roles::AUTHORITY, client.clone(), &info, - None, block_announce_validator, 1, ); @@ -1907,7 +1786,6 @@ mod test { Roles::AUTHORITY, client.clone(), &info, - None, Box::new(DefaultBlockAnnounceValidator), 1, ); @@ -1915,7 +1793,6 @@ mod test { let peer_id1 = PeerId::random(); let peer_id2 = PeerId::random(); let peer_id3 = PeerId::random(); - let peer_id4 = PeerId::random(); let mut new_blocks = |n| { for _ in 0..n { @@ -1928,7 +1805,6 @@ mod test { }; let (b1_hash, b1_number) = new_blocks(50); - let (b2_hash, b2_number) = new_blocks(10); // add 2 peers at blocks that we don't have locally sync.new_peer(peer_id1.clone(), Hash::random(), 42).unwrap(); @@ -1958,38 +1834,16 @@ mod test { PeerSyncState::DownloadingJustification(b1_hash), ); - // add another peer at a known later block - sync.new_peer(peer_id4.clone(), b2_hash, b2_number).unwrap(); - - // we request a finality proof for a block we have locally - sync.request_finality_proof(&b2_hash, b2_number); - - // the finality proof request should be scheduled to peer 4 - // which is at that block - assert!( - sync.finality_proof_requests().any(|(p, r)| { p == peer_id4 && r.block == b2_hash }) - ); - - assert_eq!( - sync.peers.get(&peer_id4).unwrap().state, - PeerSyncState::DownloadingFinalityProof(b2_hash), - ); - // we restart the sync state let block_requests = sync.restart(); // which should make us send out block requests to the first two peers assert!(block_requests.map(|r| r.unwrap()).all(|(p, _)| { p == peer_id1 || p == peer_id2 })); - // peer 3 and 4 should be unaffected as they were downloading finality data + // peer 3 should be unaffected it was downloading finality data assert_eq!( sync.peers.get(&peer_id3).unwrap().state, PeerSyncState::DownloadingJustification(b1_hash), ); - - assert_eq!( - sync.peers.get(&peer_id4).unwrap().state, - PeerSyncState::DownloadingFinalityProof(b2_hash), - ); } } diff --git a/client/network/src/protocol/sync/extra_requests.rs b/client/network/src/protocol/sync/extra_requests.rs index df336c25339fd..79f10c4a3bf80 100644 --- a/client/network/src/protocol/sync/extra_requests.rs +++ b/client/network/src/protocol/sync/extra_requests.rs @@ -528,13 +528,12 @@ mod tests { impl Arbitrary for ArbitraryPeerSyncState { fn arbitrary(g: &mut G) -> Self { - let s = match g.gen::() % 5 { + let s = match g.gen::() % 4 { 0 => PeerSyncState::Available, // TODO: 1 => PeerSyncState::AncestorSearch(g.gen(), AncestorSearchState), 1 => PeerSyncState::DownloadingNew(g.gen::()), 2 => PeerSyncState::DownloadingStale(Hash::random()), - 3 => PeerSyncState::DownloadingJustification(Hash::random()), - _ => PeerSyncState::DownloadingFinalityProof(Hash::random()) + _ => PeerSyncState::DownloadingJustification(Hash::random()), }; ArbitraryPeerSyncState(s) } diff --git a/client/network/src/schema.rs b/client/network/src/schema.rs index 44fbbffd25406..423d3ef5b41e4 100644 --- a/client/network/src/schema.rs +++ b/client/network/src/schema.rs @@ -20,9 +20,6 @@ pub mod v1 { include!(concat!(env!("OUT_DIR"), "/api.v1.rs")); - pub mod finality { - include!(concat!(env!("OUT_DIR"), "/api.v1.finality.rs")); - } pub mod light { include!(concat!(env!("OUT_DIR"), "/api.v1.light.rs")); } diff --git a/client/network/src/schema/finality.v1.proto b/client/network/src/schema/finality.v1.proto deleted file mode 100644 index 843bc4eca0990..0000000000000 --- a/client/network/src/schema/finality.v1.proto +++ /dev/null @@ -1,19 +0,0 @@ -// Schema definition for finality proof request/responses. - -syntax = "proto3"; - -package api.v1.finality; - -// Request a finality proof from a peer. -message FinalityProofRequest { - // SCALE-encoded hash of the block to request. - bytes block_hash = 1; - // Opaque chain-specific additional request data. - bytes request = 2; -} - -// Response to a finality proof request. -message FinalityProofResponse { - // Opaque chain-specific finality proof. Empty if no such proof exists. - bytes proof = 1; // optional -} diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 5fc8485947ff5..8ef76d4850699 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -38,7 +38,7 @@ use crate::{ NetworkState, NotConnectedPeer as NetworkStateNotConnectedPeer, Peer as NetworkStatePeer, }, on_demand_layer::AlwaysBadChecker, - light_client_handler, block_requests, finality_requests, + light_client_handler, block_requests, protocol::{self, event::Event, NotifsHandlerError, NotificationsSink, Ready, sync::SyncState, PeerInfo, Protocol}, transport, ReputationChange, }; @@ -53,10 +53,7 @@ use metrics::{Metrics, MetricSources, Histogram, HistogramVec}; use parking_lot::Mutex; use sc_peerset::PeersetHandle; use sp_consensus::import_queue::{BlockImportError, BlockImportResult, ImportQueue, Link}; -use sp_runtime::{ - traits::{Block as BlockT, NumberFor}, - ConsensusEngineId, -}; +use sp_runtime::traits::{Block as BlockT, NumberFor}; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use std::{ borrow::Cow, @@ -100,9 +97,7 @@ pub struct NetworkService { to_worker: TracingUnboundedSender>, /// For each peer and protocol combination, an object that allows sending notifications to /// that peer. Updated by the [`NetworkWorker`]. - peers_notifications_sinks: Arc>>, - /// For each legacy gossiping engine ID, the corresponding new protocol name. - protocol_name_by_engine: Mutex>>, + peers_notifications_sinks: Arc), NotificationsSink>>>, /// Field extracted from the [`Metrics`] struct and necessary to report the /// notifications-related metrics. notifications_sizes_metric: Option, @@ -253,7 +248,6 @@ impl NetworkWorker { local_peer_id.clone(), params.chain.clone(), params.transaction_pool, - params.finality_proof_request_builder, params.protocol_id.clone(), peerset_config, params.block_announce_validator, @@ -272,10 +266,6 @@ impl NetworkWorker { let config = block_requests::Config::new(¶ms.protocol_id); block_requests::BlockRequests::new(config, params.chain.clone()) }; - let finality_proof_requests = { - let config = finality_requests::Config::new(¶ms.protocol_id); - finality_requests::FinalityProofRequests::new(config, params.finality_proof_provider.clone()) - }; let light_client_handler = { let config = light_client_handler::Config::new(¶ms.protocol_id); light_client_handler::LightClientHandler::new( @@ -315,7 +305,6 @@ impl NetworkWorker { user_agent, local_public, block_requests, - finality_proof_requests, light_client_handler, discovery_config, params.network_config.request_response_protocols, @@ -331,8 +320,8 @@ impl NetworkWorker { } }; - for (engine_id, protocol_name) in ¶ms.network_config.notifications_protocols { - behaviour.register_notifications_protocol(*engine_id, protocol_name.clone()); + for protocol in ¶ms.network_config.notifications_protocols { + behaviour.register_notifications_protocol(protocol.clone()); } let (transport, bandwidth) = { let (config_mem, config_wasm) = match params.network_config.transport { @@ -384,9 +373,6 @@ impl NetworkWorker { let external_addresses = Arc::new(Mutex::new(Vec::new())); let peers_notifications_sinks = Arc::new(Mutex::new(HashMap::new())); - let protocol_name_by_engine = Mutex::new({ - params.network_config.notifications_protocols.iter().cloned().collect() - }); let service = Arc::new(NetworkService { bandwidth, @@ -397,7 +383,6 @@ impl NetworkWorker { local_peer_id, to_worker, peers_notifications_sinks: peers_notifications_sinks.clone(), - protocol_name_by_engine, notifications_sizes_metric: metrics.as_ref().map(|metrics| metrics.notifications_sizes.clone()), _marker: PhantomData, @@ -640,40 +625,32 @@ impl NetworkService { /// The protocol must have been registered with `register_notifications_protocol` or /// [`NetworkConfiguration::notifications_protocols`](crate::config::NetworkConfiguration::notifications_protocols). /// - pub fn write_notification(&self, target: PeerId, engine_id: ConsensusEngineId, message: Vec) { + pub fn write_notification(&self, target: PeerId, protocol: Cow<'static, str>, message: Vec) { // We clone the `NotificationsSink` in order to be able to unlock the network-wide // `peers_notifications_sinks` mutex as soon as possible. let sink = { let peers_notifications_sinks = self.peers_notifications_sinks.lock(); - if let Some(sink) = peers_notifications_sinks.get(&(target, engine_id)) { + if let Some(sink) = peers_notifications_sinks.get(&(target, protocol.clone())) { sink.clone() } else { // Notification silently discarded, as documented. + log::error!( + target: "sub-libp2p", + "Attempted to send notification on unknown protocol: {:?}", + protocol, + ); return; } }; - // Used later for the metrics report. - let message_len = message.len(); - - // Determine the wire protocol name corresponding to this `engine_id`. - let protocol_name = self.protocol_name_by_engine.lock().get(&engine_id).cloned(); - if let Some(protocol_name) = protocol_name { - sink.send_sync_notification(protocol_name, message); - } else { - log::error!( - target: "sub-libp2p", - "Attempted to send notification on unknown protocol: {:?}", - engine_id, - ); - return; - } - if let Some(notifications_sizes_metric) = self.notifications_sizes_metric.as_ref() { notifications_sizes_metric - .with_label_values(&["out", &maybe_utf8_bytes_to_string(&engine_id)]) - .observe(message_len as f64); + .with_label_values(&["out", &protocol]) + .observe(message.len() as f64); } + + // Sending is communicated to the `NotificationsSink`. + sink.send_sync_notification(protocol, message); } /// Obtains a [`NotificationSender`] for a connected peer, if it exists. @@ -746,31 +723,27 @@ impl NetworkService { pub fn notification_sender( &self, target: PeerId, - engine_id: ConsensusEngineId, + protocol: Cow<'static, str>, ) -> Result { // We clone the `NotificationsSink` in order to be able to unlock the network-wide // `peers_notifications_sinks` mutex as soon as possible. let sink = { let peers_notifications_sinks = self.peers_notifications_sinks.lock(); - if let Some(sink) = peers_notifications_sinks.get(&(target, engine_id)) { + if let Some(sink) = peers_notifications_sinks.get(&(target, protocol.clone())) { sink.clone() } else { return Err(NotificationSenderError::Closed); } }; - // Determine the wire protocol name corresponding to this `engine_id`. - let protocol_name = match self.protocol_name_by_engine.lock().get(&engine_id).cloned() { - Some(p) => p, - None => return Err(NotificationSenderError::BadProtocol), - }; + let notification_size_metric = self.notifications_sizes_metric.as_ref().map(|histogram| { + histogram.with_label_values(&["out", &protocol]) + }); Ok(NotificationSender { sink, - protocol_name, - notification_size_metric: self.notifications_sizes_metric.as_ref().map(|histogram| { - histogram.with_label_values(&["out", &maybe_utf8_bytes_to_string(&engine_id)]) - }), + protocol_name: protocol, + notification_size_metric, }) } @@ -841,17 +814,13 @@ impl NetworkService { /// /// Please call `event_stream` before registering a protocol, otherwise you may miss events /// about the protocol that you have registered. - // TODO: remove this method after https://github.com/paritytech/substrate/issues/4587 + // TODO: remove this method after https://github.com/paritytech/substrate/issues/6827 pub fn register_notifications_protocol( &self, - engine_id: ConsensusEngineId, protocol_name: impl Into>, ) { - let protocol_name = protocol_name.into(); - self.protocol_name_by_engine.lock().insert(engine_id, protocol_name.clone()); let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::RegisterNotifProtocol { - engine_id, - protocol_name, + protocol_name: protocol_name.into(), }); } @@ -1209,7 +1178,6 @@ enum ServiceToWorkerMsg { pending_response: oneshot::Sender, RequestFailure>>, }, RegisterNotifProtocol { - engine_id: ConsensusEngineId, protocol_name: Cow<'static, str>, }, DisconnectPeer(PeerId), @@ -1253,7 +1221,7 @@ pub struct NetworkWorker { >, /// For each peer and protocol combination, an object that allows sending notifications to /// that peer. Shared with the [`NetworkService`]. - peers_notifications_sinks: Arc>>, + peers_notifications_sinks: Arc), NotificationsSink>>>, } impl Future for NetworkWorker { @@ -1347,10 +1315,8 @@ impl Future for NetworkWorker { }, } }, - ServiceToWorkerMsg::RegisterNotifProtocol { engine_id, protocol_name } => { - this.network_service - .register_notifications_protocol(engine_id, protocol_name); - }, + ServiceToWorkerMsg::RegisterNotifProtocol { protocol_name } => + this.network_service.register_notifications_protocol(protocol_name), ServiceToWorkerMsg::DisconnectPeer(who) => this.network_service.user_protocol_mut().disconnect_peer(&who), ServiceToWorkerMsg::UpdateChain => @@ -1389,12 +1355,6 @@ impl Future for NetworkWorker { } this.import_queue.import_justification(origin, hash, nb, justification); }, - Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::FinalityProofImport(origin, hash, nb, proof))) => { - if let Some(metrics) = this.metrics.as_ref() { - metrics.import_queue_finality_proofs_submitted.inc(); - } - this.import_queue.import_finality_proof(origin, hash, nb, proof); - }, Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::InboundRequest { protocol, result, .. })) => { if let Some(metrics) = this.metrics.as_ref() { match result { @@ -1474,24 +1434,28 @@ impl Future for NetworkWorker { .inc(); } }, - Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::NotificationStreamOpened { remote, engine_id, notifications_sink, role })) => { + Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::NotificationStreamOpened { + remote, protocol, notifications_sink, role + })) => { if let Some(metrics) = this.metrics.as_ref() { metrics.notifications_streams_opened_total - .with_label_values(&[&maybe_utf8_bytes_to_string(&engine_id)]).inc(); + .with_label_values(&[&protocol]).inc(); } { let mut peers_notifications_sinks = this.peers_notifications_sinks.lock(); - peers_notifications_sinks.insert((remote.clone(), engine_id), notifications_sink); + peers_notifications_sinks.insert((remote.clone(), protocol.clone()), notifications_sink); } this.event_streams.send(Event::NotificationStreamOpened { remote, - engine_id, + protocol, role, }); }, - Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::NotificationStreamReplaced { remote, engine_id, notifications_sink })) => { + Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::NotificationStreamReplaced { + remote, protocol, notifications_sink + })) => { let mut peers_notifications_sinks = this.peers_notifications_sinks.lock(); - if let Some(s) = peers_notifications_sinks.get_mut(&(remote, engine_id)) { + if let Some(s) = peers_notifications_sinks.get_mut(&(remote, protocol)) { *s = notifications_sink; } else { log::error!( @@ -1513,33 +1477,33 @@ impl Future for NetworkWorker { // https://github.com/paritytech/substrate/issues/6403. /*this.event_streams.send(Event::NotificationStreamClosed { remote, - engine_id, + protocol, }); this.event_streams.send(Event::NotificationStreamOpened { remote, - engine_id, + protocol, role, });*/ }, - Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::NotificationStreamClosed { remote, engine_id })) => { + Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::NotificationStreamClosed { remote, protocol })) => { if let Some(metrics) = this.metrics.as_ref() { metrics.notifications_streams_closed_total - .with_label_values(&[&maybe_utf8_bytes_to_string(&engine_id[..])]).inc(); + .with_label_values(&[&protocol[..]]).inc(); } this.event_streams.send(Event::NotificationStreamClosed { remote: remote.clone(), - engine_id, + protocol: protocol.clone(), }); { let mut peers_notifications_sinks = this.peers_notifications_sinks.lock(); - peers_notifications_sinks.remove(&(remote.clone(), engine_id)); + peers_notifications_sinks.remove(&(remote.clone(), protocol)); } }, Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::NotificationsReceived { remote, messages })) => { if let Some(metrics) = this.metrics.as_ref() { - for (engine_id, message) in &messages { + for (protocol, message) in &messages { metrics.notifications_sizes - .with_label_values(&["in", &maybe_utf8_bytes_to_string(engine_id)]) + .with_label_values(&["in", protocol]) .observe(message.len() as f64); } } @@ -1587,11 +1551,11 @@ impl Future for NetworkWorker { let reason = match cause { Some(ConnectionError::IO(_)) => "transport-error", Some(ConnectionError::Handler(NodeHandlerWrapperError::Handler(EitherError::A(EitherError::A( - EitherError::A(EitherError::A(EitherError::A(EitherError::B( - EitherError::A(PingFailure::Timeout)))))))))) => "ping-timeout", + EitherError::A(EitherError::A(EitherError::B( + EitherError::A(PingFailure::Timeout))))))))) => "ping-timeout", Some(ConnectionError::Handler(NodeHandlerWrapperError::Handler(EitherError::A(EitherError::A( - EitherError::A(EitherError::A(EitherError::A(EitherError::A( - NotifsHandlerError::SyncNotificationsClogged))))))))) => "sync-notifications-clogged", + EitherError::A(EitherError::A(EitherError::A( + NotifsHandlerError::SyncNotificationsClogged)))))))) => "sync-notifications-clogged", Some(ConnectionError::Handler(NodeHandlerWrapperError::Handler(_))) => "protocol-error", Some(ConnectionError::Handler(NodeHandlerWrapperError::KeepAliveTimeout)) => "keep-alive-timeout", None => "actively-closed", @@ -1748,17 +1712,6 @@ impl Future for NetworkWorker { impl Unpin for NetworkWorker { } -/// Turns bytes that are potentially UTF-8 into a reasonable representable string. -/// -/// Meant to be used only for debugging or metrics-reporting purposes. -pub(crate) fn maybe_utf8_bytes_to_string(id: &[u8]) -> Cow { - if let Ok(s) = std::str::from_utf8(&id[..]) { - Cow::Borrowed(s) - } else { - Cow::Owned(format!("{:?}", id)) - } -} - /// The libp2p swarm, customized for our needs. type Swarm = libp2p::swarm::Swarm>; @@ -1787,23 +1740,6 @@ impl<'a, B: BlockT, H: ExHashT> Link for NetworkLink<'a, B, H> { fn request_justification(&mut self, hash: &B::Hash, number: NumberFor) { self.protocol.user_protocol_mut().request_justification(hash, number) } - fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor) { - self.protocol.user_protocol_mut().request_finality_proof(hash, number) - } - fn finality_proof_imported( - &mut self, - who: PeerId, - request_block: (B::Hash, NumberFor), - finalization_result: Result<(B::Hash, NumberFor), ()>, - ) { - let success = finalization_result.is_ok(); - self.protocol.user_protocol_mut().finality_proof_import_result(request_block, finalization_result); - if !success { - info!("💔 Invalid finality proof provided by {} for #{}", who, request_block.0); - self.protocol.user_protocol_mut().disconnect_peer(&who); - self.protocol.user_protocol_mut().report_peer(who, ReputationChange::new_fatal("Invalid finality proof")); - } - } } fn ensure_addresses_consistent_with_transport<'a>( diff --git a/client/network/src/service/metrics.rs b/client/network/src/service/metrics.rs index a63ce7a18a519..614c24b522de2 100644 --- a/client/network/src/service/metrics.rs +++ b/client/network/src/service/metrics.rs @@ -56,7 +56,6 @@ pub struct Metrics { pub distinct_peers_connections_closed_total: Counter, pub distinct_peers_connections_opened_total: Counter, pub import_queue_blocks_submitted: Counter, - pub import_queue_finality_proofs_submitted: Counter, pub import_queue_justifications_submitted: Counter, pub incoming_connections_errors_total: CounterVec, pub incoming_connections_total: Counter, @@ -112,10 +111,6 @@ impl Metrics { "import_queue_blocks_submitted", "Number of blocks submitted to the import queue.", )?, registry)?, - import_queue_finality_proofs_submitted: prometheus::register(Counter::new( - "import_queue_finality_proofs_submitted", - "Number of finality proofs submitted to the import queue.", - )?, registry)?, import_queue_justifications_submitted: prometheus::register(Counter::new( "import_queue_justifications_submitted", "Number of justifications submitted to the import queue.", diff --git a/client/network/src/service/out_events.rs b/client/network/src/service/out_events.rs index 1b86a5fa4317d..976548f6ed440 100644 --- a/client/network/src/service/out_events.rs +++ b/client/network/src/service/out_events.rs @@ -33,7 +33,6 @@ //! use crate::Event; -use super::maybe_utf8_bytes_to_string; use futures::{prelude::*, channel::mpsc, ready, stream::FusedStream}; use parking_lot::Mutex; @@ -228,23 +227,23 @@ impl Metrics { .with_label_values(&["dht", "sent", name]) .inc_by(num); } - Event::NotificationStreamOpened { engine_id, .. } => { + Event::NotificationStreamOpened { protocol, .. } => { self.events_total - .with_label_values(&[&format!("notif-open-{:?}", engine_id), "sent", name]) + .with_label_values(&[&format!("notif-open-{:?}", protocol), "sent", name]) .inc_by(num); }, - Event::NotificationStreamClosed { engine_id, .. } => { + Event::NotificationStreamClosed { protocol, .. } => { self.events_total - .with_label_values(&[&format!("notif-closed-{:?}", engine_id), "sent", name]) + .with_label_values(&[&format!("notif-closed-{:?}", protocol), "sent", name]) .inc_by(num); }, Event::NotificationsReceived { messages, .. } => { - for (engine_id, message) in messages { + for (protocol, message) in messages { self.events_total - .with_label_values(&[&format!("notif-{:?}", engine_id), "sent", name]) + .with_label_values(&[&format!("notif-{:?}", protocol), "sent", name]) .inc_by(num); self.notifications_sizes - .with_label_values(&[&maybe_utf8_bytes_to_string(engine_id), "sent", name]) + .with_label_values(&[protocol, "sent", name]) .inc_by(num.saturating_mul(u64::try_from(message.len()).unwrap_or(u64::max_value()))); } }, @@ -258,23 +257,23 @@ impl Metrics { .with_label_values(&["dht", "received", name]) .inc(); } - Event::NotificationStreamOpened { engine_id, .. } => { + Event::NotificationStreamOpened { protocol, .. } => { self.events_total - .with_label_values(&[&format!("notif-open-{:?}", engine_id), "received", name]) + .with_label_values(&[&format!("notif-open-{:?}", protocol), "received", name]) .inc(); }, - Event::NotificationStreamClosed { engine_id, .. } => { + Event::NotificationStreamClosed { protocol, .. } => { self.events_total - .with_label_values(&[&format!("notif-closed-{:?}", engine_id), "received", name]) + .with_label_values(&[&format!("notif-closed-{:?}", protocol), "received", name]) .inc(); }, Event::NotificationsReceived { messages, .. } => { - for (engine_id, message) in messages { + for (protocol, message) in messages { self.events_total - .with_label_values(&[&format!("notif-{:?}", engine_id), "received", name]) + .with_label_values(&[&format!("notif-{:?}", protocol), "received", name]) .inc(); self.notifications_sizes - .with_label_values(&[&maybe_utf8_bytes_to_string(engine_id), "received", name]) + .with_label_values(&[&protocol, "received", name]) .inc_by(u64::try_from(message.len()).unwrap_or(u64::max_value())); } }, diff --git a/client/network/src/service/tests.rs b/client/network/src/service/tests.rs index 4b6f9dd156482..225a3ae98ab5d 100644 --- a/client/network/src/service/tests.rs +++ b/client/network/src/service/tests.rs @@ -21,7 +21,7 @@ use crate::{config, Event, NetworkService, NetworkWorker}; use libp2p::PeerId; use futures::prelude::*; use sp_runtime::traits::{Block as BlockT, Header as _}; -use std::{sync::Arc, time::Duration}; +use std::{borrow::Cow, sync::Arc, time::Duration}; use substrate_test_runtime_client::{TestClientBuilder, TestClientBuilderExt as _}; type TestNetworkService = NetworkService< @@ -87,7 +87,6 @@ fn build_test_full_node(config: config::NetworkConfiguration) PassThroughVerifier(false), Box::new(client.clone()), None, - None, &sp_core::testing::TaskExecutor::new(), None, )); @@ -97,8 +96,6 @@ fn build_test_full_node(config: config::NetworkConfiguration) executor: None, network_config: config, chain: client.clone(), - finality_proof_provider: None, - finality_proof_request_builder: None, on_demand: None, transaction_pool: Arc::new(crate::config::EmptyTransactionPool), protocol_id: config::ProtocolId::from("/test-protocol-name"), @@ -121,24 +118,24 @@ fn build_test_full_node(config: config::NetworkConfiguration) (service, event_stream) } -const ENGINE_ID: sp_runtime::ConsensusEngineId = *b"foo\0"; +const PROTOCOL_NAME: Cow<'static, str> = Cow::Borrowed("/foo"); /// Builds two nodes and their associated events stream. -/// The nodes are connected together and have the `ENGINE_ID` protocol registered. +/// The nodes are connected together and have the `PROTOCOL_NAME` protocol registered. fn build_nodes_one_proto() -> (Arc, impl Stream, Arc, impl Stream) { let listen_addr = config::build_multiaddr![Memory(rand::random::())]; let (node1, events_stream1) = build_test_full_node(config::NetworkConfiguration { - notifications_protocols: vec![(ENGINE_ID, From::from("/foo"))], + notifications_protocols: vec![PROTOCOL_NAME], listen_addresses: vec![listen_addr.clone()], transport: config::TransportConfig::MemoryOnly, .. config::NetworkConfiguration::new_local() }); let (node2, events_stream2) = build_test_full_node(config::NetworkConfiguration { - notifications_protocols: vec![(ENGINE_ID, From::from("/foo"))], + notifications_protocols: vec![PROTOCOL_NAME], listen_addresses: vec![], reserved_nodes: vec![config::MultiaddrWithPeerId { multiaddr: listen_addr, @@ -161,10 +158,10 @@ fn notifications_state_consistent() { // Write some initial notifications that shouldn't get through. for _ in 0..(rand::random::() % 5) { - node1.write_notification(node2.local_peer_id().clone(), ENGINE_ID, b"hello world".to_vec()); + node1.write_notification(node2.local_peer_id().clone(), PROTOCOL_NAME, b"hello world".to_vec()); } for _ in 0..(rand::random::() % 5) { - node2.write_notification(node1.local_peer_id().clone(), ENGINE_ID, b"hello world".to_vec()); + node2.write_notification(node1.local_peer_id().clone(), PROTOCOL_NAME, b"hello world".to_vec()); } async_std::task::block_on(async move { @@ -187,10 +184,10 @@ fn notifications_state_consistent() { // Start by sending a notification from node1 to node2 and vice-versa. Part of the // test consists in ensuring that notifications get ignored if the stream isn't open. if rand::random::() % 5 >= 3 { - node1.write_notification(node2.local_peer_id().clone(), ENGINE_ID, b"hello world".to_vec()); + node1.write_notification(node2.local_peer_id().clone(), PROTOCOL_NAME, b"hello world".to_vec()); } if rand::random::() % 5 >= 3 { - node2.write_notification(node1.local_peer_id().clone(), ENGINE_ID, b"hello world".to_vec()); + node2.write_notification(node1.local_peer_id().clone(), PROTOCOL_NAME, b"hello world".to_vec()); } // Also randomly disconnect the two nodes from time to time. @@ -219,31 +216,31 @@ fn notifications_state_consistent() { }; match next_event { - future::Either::Left(Event::NotificationStreamOpened { remote, engine_id, .. }) => { + future::Either::Left(Event::NotificationStreamOpened { remote, protocol, .. }) => { something_happened = true; assert!(!node1_to_node2_open); node1_to_node2_open = true; assert_eq!(remote, *node2.local_peer_id()); - assert_eq!(engine_id, ENGINE_ID); + assert_eq!(protocol, PROTOCOL_NAME); } - future::Either::Right(Event::NotificationStreamOpened { remote, engine_id, .. }) => { + future::Either::Right(Event::NotificationStreamOpened { remote, protocol, .. }) => { something_happened = true; assert!(!node2_to_node1_open); node2_to_node1_open = true; assert_eq!(remote, *node1.local_peer_id()); - assert_eq!(engine_id, ENGINE_ID); + assert_eq!(protocol, PROTOCOL_NAME); } - future::Either::Left(Event::NotificationStreamClosed { remote, engine_id, .. }) => { + future::Either::Left(Event::NotificationStreamClosed { remote, protocol, .. }) => { assert!(node1_to_node2_open); node1_to_node2_open = false; assert_eq!(remote, *node2.local_peer_id()); - assert_eq!(engine_id, ENGINE_ID); + assert_eq!(protocol, PROTOCOL_NAME); } - future::Either::Right(Event::NotificationStreamClosed { remote, engine_id, .. }) => { + future::Either::Right(Event::NotificationStreamClosed { remote, protocol, .. }) => { assert!(node2_to_node1_open); node2_to_node1_open = false; assert_eq!(remote, *node1.local_peer_id()); - assert_eq!(engine_id, ENGINE_ID); + assert_eq!(protocol, PROTOCOL_NAME); } future::Either::Left(Event::NotificationsReceived { remote, .. }) => { assert!(node1_to_node2_open); @@ -251,7 +248,7 @@ fn notifications_state_consistent() { if rand::random::() % 5 >= 4 { node1.write_notification( node2.local_peer_id().clone(), - ENGINE_ID, + PROTOCOL_NAME, b"hello world".to_vec() ); } @@ -262,7 +259,7 @@ fn notifications_state_consistent() { if rand::random::() % 5 >= 4 { node2.write_notification( node1.local_peer_id().clone(), - ENGINE_ID, + PROTOCOL_NAME, b"hello world".to_vec() ); } @@ -281,7 +278,7 @@ fn lots_of_incoming_peers_works() { let listen_addr = config::build_multiaddr![Memory(rand::random::())]; let (main_node, _) = build_test_full_node(config::NetworkConfiguration { - notifications_protocols: vec![(ENGINE_ID, From::from("/foo"))], + notifications_protocols: vec![PROTOCOL_NAME], listen_addresses: vec![listen_addr.clone()], in_peers: u32::max_value(), transport: config::TransportConfig::MemoryOnly, @@ -298,7 +295,7 @@ fn lots_of_incoming_peers_works() { let main_node_peer_id = main_node_peer_id.clone(); let (_dialing_node, event_stream) = build_test_full_node(config::NetworkConfiguration { - notifications_protocols: vec![(ENGINE_ID, From::from("/foo"))], + notifications_protocols: vec![PROTOCOL_NAME], listen_addresses: vec![], reserved_nodes: vec![config::MultiaddrWithPeerId { multiaddr: listen_addr.clone(), @@ -364,7 +361,7 @@ fn notifications_back_pressure() { Event::NotificationStreamClosed { .. } => panic!(), Event::NotificationsReceived { messages, .. } => { for message in messages { - assert_eq!(message.0, ENGINE_ID); + assert_eq!(message.0, PROTOCOL_NAME); assert_eq!(message.1, format!("hello #{}", received_notifications)); received_notifications += 1; } @@ -389,7 +386,7 @@ fn notifications_back_pressure() { // Sending! for num in 0..TOTAL_NOTIFS { - let notif = node1.notification_sender(node2_id.clone(), ENGINE_ID).unwrap(); + let notif = node1.notification_sender(node2_id.clone(), PROTOCOL_NAME).unwrap(); notif.ready().await.unwrap().send(format!("hello #{}", num)).unwrap(); } diff --git a/client/network/test/src/block_import.rs b/client/network/test/src/block_import.rs index 1d2cd3d687de9..a5d0600abefea 100644 --- a/client/network/test/src/block_import.rs +++ b/client/network/test/src/block_import.rs @@ -107,7 +107,6 @@ fn async_import_queue_drops() { verifier, Box::new(substrate_test_runtime_client::new()), None, - None, &executor, None, ); diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index 587feebe55c14..6950ada4f8458 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -29,7 +29,6 @@ use std::{ use libp2p::build_multiaddr; use log::trace; -use sc_network::config::FinalityProofProvider; use sp_blockchain::{ HeaderBackend, Result as ClientResult, well_known_cache_keys::{self, Id as CacheKeyId}, @@ -44,21 +43,21 @@ use sc_block_builder::{BlockBuilder, BlockBuilderProvider}; use sc_network::config::Role; use sp_consensus::block_validation::{DefaultBlockAnnounceValidator, BlockAnnounceValidator}; use sp_consensus::import_queue::{ - BasicQueue, BoxJustificationImport, Verifier, BoxFinalityProofImport, + BasicQueue, BoxJustificationImport, Verifier, }; use sp_consensus::block_import::{BlockImport, ImportResult}; use sp_consensus::Error as ConsensusError; use sp_consensus::{BlockOrigin, ForkChoiceStrategy, BlockImportParams, BlockCheckParams, JustificationImport}; use futures::prelude::*; use sc_network::{NetworkWorker, NetworkService, config::ProtocolId}; -use sc_network::config::{NetworkConfiguration, TransportConfig, BoxFinalityProofRequestBuilder}; +use sc_network::config::{NetworkConfiguration, TransportConfig}; use libp2p::PeerId; use parking_lot::Mutex; use sp_core::H256; use sc_network::config::ProtocolConfig; use sp_runtime::generic::{BlockId, OpaqueDigestItemId}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use sp_runtime::{ConsensusEngineId, Justification}; +use sp_runtime::Justification; use substrate_test_runtime_client::{self, AccountKeyring}; use sc_service::client::Client; pub use sc_network::config::EmptyTransactionPool; @@ -557,7 +556,7 @@ pub struct FullPeerConfig { /// Block announce validator. pub block_announce_validator: Option + Send + Sync>>, /// List of notification protocols that the network must support. - pub notifications_protocols: Vec<(ConsensusEngineId, Cow<'static, str>)>, + pub notifications_protocols: Vec>, } pub trait TestNetFactory: Sized { @@ -586,20 +585,10 @@ pub trait TestNetFactory: Sized { -> ( BlockImportAdapter, Option>, - Option>, - Option>, Self::PeerData, ) { - (client.as_block_import(), None, None, None, Default::default()) - } - - /// Get finality proof provider (if supported). - fn make_finality_proof_provider( - &self, - _client: PeersClient, - ) -> Option>> { - None + (client.as_block_import(), None, Default::default()) } fn default_config() -> ProtocolConfig { @@ -636,8 +625,6 @@ pub trait TestNetFactory: Sized { let ( block_import, justification_import, - finality_proof_import, - finality_proof_request_builder, data, ) = self.make_block_import(PeersClient::Full(client.clone(), backend.clone())); @@ -652,7 +639,6 @@ pub trait TestNetFactory: Sized { verifier.clone(), Box::new(block_import.clone()), justification_import, - finality_proof_import, &sp_core::testing::TaskExecutor::new(), None, )); @@ -675,10 +661,6 @@ pub trait TestNetFactory: Sized { executor: None, network_config, chain: client.clone(), - finality_proof_provider: self.make_finality_proof_provider( - PeersClient::Full(client.clone(), backend.clone()), - ), - finality_proof_request_builder, on_demand: None, transaction_pool: Arc::new(EmptyTransactionPool), protocol_id: ProtocolId::from("test-protocol-name"), @@ -717,8 +699,6 @@ pub trait TestNetFactory: Sized { let ( block_import, justification_import, - finality_proof_import, - finality_proof_request_builder, data, ) = self.make_block_import(PeersClient::Light(client.clone(), backend.clone())); @@ -733,7 +713,6 @@ pub trait TestNetFactory: Sized { verifier.clone(), Box::new(block_import.clone()), justification_import, - finality_proof_import, &sp_core::testing::TaskExecutor::new(), None, )); @@ -755,10 +734,6 @@ pub trait TestNetFactory: Sized { executor: None, network_config, chain: client.clone(), - finality_proof_provider: self.make_finality_proof_provider( - PeersClient::Light(client.clone(), backend.clone()) - ), - finality_proof_request_builder, on_demand: None, transaction_pool: Arc::new(EmptyTransactionPool), protocol_id: ProtocolId::from("test-protocol-name"), @@ -989,16 +964,12 @@ impl TestNetFactory for JustificationTestNet { -> ( BlockImportAdapter, Option>, - Option>, - Option>, Self::PeerData, ) { ( client.as_block_import(), Some(Box::new(ForceFinalized(client))), - None, - None, Default::default(), ) } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index b85ebde3c1d28..3d0b00820fe6d 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -76,7 +76,7 @@ sc-offchain = { version = "2.0.0", path = "../offchain" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0"} sc-tracing = { version = "2.0.0", path = "../tracing" } sp-tracing = { version = "2.0.0", path = "../../primitives/tracing" } -tracing = "0.1.19" +tracing = "0.1.22" tracing-futures = { version = "0.2.4" } parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 7d613f2bc6292..d9dc0d1c6ba01 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -41,7 +41,7 @@ use futures::{ }; use sc_keystore::LocalKeystore; use log::{info, warn}; -use sc_network::config::{Role, FinalityProofProvider, OnDemand, BoxFinalityProofRequestBuilder}; +use sc_network::config::{Role, OnDemand}; use sc_network::NetworkService; use sp_runtime::generic::BlockId; use sp_runtime::traits::{ @@ -830,10 +830,6 @@ pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl> { pub block_announce_validator_builder: Option) -> Box + Send> + Send >>, - /// An optional finality proof request builder. - pub finality_proof_request_builder: Option>, - /// An optional, shared finality proof request provider. - pub finality_proof_provider: Option>>, } /// Build the network service, the network status sinks and an RPC sender. @@ -858,7 +854,7 @@ pub fn build_network( { let BuildNetworkParams { config, client, transaction_pool, spawn_handle, import_queue, on_demand, - block_announce_validator_builder, finality_proof_request_builder, finality_proof_provider, + block_announce_validator_builder, } = params; let transaction_pool_adapter = Arc::new(TransactionPoolAdapter { @@ -896,8 +892,6 @@ pub fn build_network( }, network_config: config.network.clone(), chain: client.clone(), - finality_proof_provider, - finality_proof_request_builder, on_demand: on_demand, transaction_pool: transaction_pool_adapter as _, import_queue: Box::new(import_queue), diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 8e6b0037bdf93..fd5ad9ebac917 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -73,14 +73,14 @@ pub use sc_executor::NativeExecutionDispatch; pub use std::{ops::Deref, result::Result, sync::Arc}; #[doc(hidden)] pub use sc_network::config::{ - FinalityProofProvider, OnDemand, BoxFinalityProofRequestBuilder, TransactionImport, + OnDemand, TransactionImport, TransactionImportFuture, }; pub use sc_tracing::TracingReceiver; pub use task_manager::SpawnTaskHandle; pub use task_manager::TaskManager; pub use sp_consensus::import_queue::ImportQueue; -pub use self::client::LocalCallExecutor; +pub use self::client::{LocalCallExecutor, ClientConfig}; use sc_client_api::{blockchain::HeaderBackend, BlockchainEvents}; const DEFAULT_PROTOCOL_ID: &str = "sup"; diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index bff7842bec4f5..fab0fe00869c7 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] parking_lot = "0.10.0" futures = "0.3.4" futures-timer = "3.0.1" -wasm-timer = "0.2.0" +wasm-timer = "0.2.5" libp2p = { version = "0.30.1", default-features = false, features = ["dns", "tcp-async-std", "wasm-ext", "websocket"] } log = "0.4.8" pin-project = "0.4.6" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 35db326c94929..4964adafe6492 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -20,7 +20,7 @@ rustc-hash = "1.1.0" serde = "1.0.101" serde_json = "1.0.41" slog = { version = "2.5.2", features = ["nested-values"] } -tracing = "0.1.21" +tracing = "0.1.22" tracing-core = "0.1.17" tracing-subscriber = "0.2.13" sp-tracing = { version = "2.0.0", path = "../../primitives/tracing" } diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS index b195d5c657065..a3837e1677865 100644 --- a/docs/CODEOWNERS +++ b/docs/CODEOWNERS @@ -45,9 +45,6 @@ # Contracts /frame/contracts/ @athei -# EVM -/frame/evm/ @sorpaas - # NPoS and election /frame/staking/ @kianenigma /frame/elections/ @kianenigma diff --git a/docs/README.adoc b/docs/README.adoc index 7f3d50faac7d6..71052420b1aa9 100644 --- a/docs/README.adoc +++ b/docs/README.adoc @@ -308,28 +308,6 @@ cargo run --release \-- \ Additional Substrate CLI usage options are available and may be shown by running `cargo run \-- --help`. -=== WASM binaries - -The WASM binaries are built during the normal `cargo build` process. To control the WASM binary building, -we support multiple environment variables: - -* `SKIP_WASM_BUILD` - Skips building any WASM binary. This is useful when only native should be recompiled. -* `BUILD_DUMMY_WASM_BINARY` - Builds dummy WASM binaries. These dummy binaries are empty and useful - for `cargo check` runs. -* `WASM_BUILD_TYPE` - Sets the build type for building WASM binaries. Supported values are `release` or `debug`. - By default the build type is equal to the build type used by the main build. -* `FORCE_WASM_BUILD` - Can be set to force a WASM build. On subsequent calls the value of the variable - needs to change. As WASM builder instructs `cargo` to watch for file changes - this environment variable should only be required in certain circumstances. -* `WASM_TARGET_DIRECTORY` - Will copy release build WASM binary to the given directory. The path needs - to be absolute. -* `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the wasm binary. -* `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build. - -Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. -Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will -be `NODE_RUNTIME`. - [[flaming-fir]] === Joining the Flaming Fir Testnet diff --git a/frame/balances/src/tests_composite.rs b/frame/balances/src/tests_composite.rs index 88b73b47273eb..fd4ba1fd3c305 100644 --- a/frame/balances/src/tests_composite.rs +++ b/frame/balances/src/tests_composite.rs @@ -27,10 +27,8 @@ use sp_runtime::{ use sp_core::H256; use sp_io; use frame_support::{impl_outer_origin, impl_outer_event, parameter_types}; -use frame_support::traits::Get; use frame_support::weights::{Weight, DispatchInfo, IdentityFee}; use pallet_transaction_payment::CurrencyAdapter; -use std::cell::RefCell; use crate::{GenesisConfig, Module, Trait, decl_tests, tests::CallWithDispatchInfo}; use frame_system as system; @@ -49,15 +47,6 @@ impl_outer_event! { } } -thread_local! { - static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); -} - -pub struct ExistentialDeposit; -impl Get for ExistentialDeposit { - fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) } -} - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Test; @@ -66,6 +55,7 @@ parameter_types! { pub const MaximumBlockWeight: Weight = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub static ExistentialDeposit: u64 = 0; } impl frame_system::Trait for Test { type BaseCallFilter = (); diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index 319fb3640b4c7..c0a5d23ff1a41 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -27,9 +27,8 @@ use sp_runtime::{ use sp_core::H256; use sp_io; use frame_support::{impl_outer_origin, impl_outer_event, parameter_types}; -use frame_support::traits::{Get, StorageMapShim}; +use frame_support::traits::StorageMapShim; use frame_support::weights::{Weight, DispatchInfo, IdentityFee}; -use std::cell::RefCell; use crate::{GenesisConfig, Module, Trait, decl_tests, tests::CallWithDispatchInfo}; use pallet_transaction_payment::CurrencyAdapter; @@ -49,15 +48,6 @@ impl_outer_event! { } } -thread_local! { - static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); -} - -pub struct ExistentialDeposit; -impl Get for ExistentialDeposit { - fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) } -} - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Test; @@ -66,6 +56,7 @@ parameter_types! { pub const MaximumBlockWeight: Weight = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub static ExistentialDeposit: u64 = 0; } impl frame_system::Trait for Test { type BaseCallFilter = (); diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 924ffc8627abc..acd29e468243e 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -linregress = "0.1" +linregress = { version = "0.4.0", optional = true } paste = "0.1" codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } sp-api = { version = "2.0.0", path = "../../primitives/api", default-features = false } @@ -38,4 +38,5 @@ std = [ "sp-std/std", "frame-support/std", "frame-system/std", + "linregress", ] diff --git a/frame/contracts/fixtures/call_return_code.wat b/frame/contracts/fixtures/call_return_code.wat index f7a7ff20a49e3..4e9ab4dd77ce1 100644 --- a/frame/contracts/fixtures/call_return_code.wat +++ b/frame/contracts/fixtures/call_return_code.wat @@ -1,5 +1,5 @@ -;; This calls Django (4) and transfers 100 balance during this call and copies the return code -;; of this call to the output buffer. +;; This calls the supplied dest and transfers 100 balance during this call and copies +;; the return code of this call to the output buffer. ;; It also forwards its input to the callee. (module (import "seal0" "seal_input" (func $seal_input (param i32 i32))) @@ -7,38 +7,36 @@ (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) - ;; [0, 8) address of django - (data (i32.const 0) "\04\00\00\00\00\00\00\00") + ;; [0, 8) 100 balance + (data (i32.const 0) "\64\00\00\00\00\00\00\00") - ;; [8, 16) 100 balance - (data (i32.const 8) "\64\00\00\00\00\00\00\00") + ;; [8, 12) here we store the return code of the transfer - ;; [16, 20) here we store the return code of the transfer + ;; [12, 16) size of the input data + (data (i32.const 12) "\24") - ;; [20, 24) here we store the input data - - ;; [24, 28) size of the input data - (data (i32.const 24) "\04") + ;; [16, inf) here we store the input data + ;; 32 byte dest + 4 byte forward (func (export "deploy")) (func (export "call") - (call $seal_input (i32.const 20) (i32.const 24)) + (call $seal_input (i32.const 16) (i32.const 12)) (i32.store - (i32.const 16) + (i32.const 8) (call $seal_call - (i32.const 0) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. + (i32.const 16) ;; Pointer to "callee" address. + (i32.const 32) ;; Length of "callee" address. (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 8) ;; Pointer to the buffer with value to transfer + (i32.const 0) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 20) ;; Pointer to input data buffer address - (i32.load (i32.const 24)) ;; Length of input data buffer + (i32.const 48) ;; Pointer to input data buffer address + (i32.const 4) ;; Length of input data buffer (i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output (i32.const 0) ;; Ptr to output buffer len ) ) ;; exit with success and take transfer return code to the output buffer - (call $seal_return (i32.const 0) (i32.const 16) (i32.const 4)) + (call $seal_return (i32.const 0) (i32.const 8) (i32.const 4)) ) ) diff --git a/frame/contracts/fixtures/caller_contract.wat b/frame/contracts/fixtures/caller_contract.wat index 408af92e18296..d6564117b721f 100644 --- a/frame/contracts/fixtures/caller_contract.wat +++ b/frame/contracts/fixtures/caller_contract.wat @@ -2,7 +2,9 @@ (import "seal0" "seal_input" (func $seal_input (param i32 i32))) (import "seal0" "seal_balance" (func $seal_balance (param i32 i32))) (import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) - (import "seal0" "seal_instantiate" (func $seal_instantiate (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32) (result i32))) + (import "seal0" "seal_instantiate" (func $seal_instantiate + (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32) + )) (import "seal0" "seal_println" (func $seal_println (param i32 i32))) (import "env" "memory" (memory 1 1)) @@ -71,6 +73,8 @@ (i32.const 0) ;; Length is ignored in this case (i32.const 4294967295) ;; u32 max sentinel value: do not copy output (i32.const 0) ;; Length is ignored in this case + (i32.const 0) ;; salt_ptr + (i32.const 0) ;; salt_le ) ) @@ -98,6 +102,9 @@ (i32.const 0) ;; Length is ignored in this case (i32.const 4294967295) ;; u32 max sentinel value: do not copy output (i32.const 0) ;; Length is ignored in this case + (i32.const 0) ;; salt_ptr + (i32.const 0) ;; salt_le + ) ) @@ -114,7 +121,7 @@ ;; Length of the output buffer (i32.store (i32.sub (get_local $sp) (i32.const 4)) - (i32.const 8) + (i32.const 256) ) ;; Deploy the contract successfully. @@ -131,6 +138,8 @@ (i32.sub (get_local $sp) (i32.const 4)) ;; Pointer to the address buffer length (i32.const 4294967295) ;; u32 max sentinel value: do not copy output (i32.const 0) ;; Length is ignored in this case + (i32.const 0) ;; salt_ptr + (i32.const 0) ;; salt_le ) ) @@ -142,7 +151,7 @@ ;; Check that address has the expected length (call $assert - (i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 4))) (i32.const 8)) + (i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 4))) (i32.const 32)) ) ;; Check that balance has been deducted. @@ -169,7 +178,7 @@ (set_local $exit_code (call $seal_call (i32.const 16) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. + (i32.const 32) ;; Length of "callee" address. (i64.const 0) ;; How much gas to devote for the execution. 0 = all. (i32.const 0) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer. @@ -205,7 +214,7 @@ (set_local $exit_code (call $seal_call (i32.const 16) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. + (i32.const 32) ;; Length of "callee" address. (i64.const 1) ;; Supply too little gas (i32.const 0) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer. @@ -242,7 +251,7 @@ (set_local $exit_code (call $seal_call (i32.const 16) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. + (i32.const 32) ;; Length of "callee" address. (i64.const 0) ;; How much gas to devote for the execution. 0 = all. (i32.const 0) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer. diff --git a/frame/contracts/fixtures/destroy_and_transfer.wat b/frame/contracts/fixtures/destroy_and_transfer.wat index 3220f4e612d7d..7e1d84f3cf98a 100644 --- a/frame/contracts/fixtures/destroy_and_transfer.wat +++ b/frame/contracts/fixtures/destroy_and_transfer.wat @@ -4,7 +4,9 @@ (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) (import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) (import "seal0" "seal_transfer" (func $seal_transfer (param i32 i32 i32 i32) (result i32))) - (import "seal0" "seal_instantiate" (func $seal_instantiate (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32) (result i32))) + (import "seal0" "seal_instantiate" (func $seal_instantiate + (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32) + )) (import "env" "memory" (memory 1 1)) ;; [0, 8) Endowment to send when creating contract. @@ -16,14 +18,18 @@ ;; [48, 80) Buffer where to store the input to the contract - ;; [80, 88) Buffer where to store the address of the instantiated contract - ;; [88, 96) Size of the buffer - (data (i32.const 88) "\08") + (data (i32.const 88) "\FF") ;; [96, 100) Size of the input buffer (data (i32.const 96) "\20") + ;; [100, 132) Buffer where to store the address of the instantiated contract + + ;; [132, 134) Salt + (data (i32.const 132) "\47\11") + + (func $assert (param i32) (block $ok (br_if $ok @@ -54,10 +60,12 @@ (i32.const 8) ;; Length of the buffer with value to transfer. (i32.const 0) ;; Pointer to input data buffer address (i32.const 0) ;; Length of input data buffer - (i32.const 80) ;; Buffer where to store address of new contract + (i32.const 100) ;; Buffer where to store address of new contract (i32.const 88) ;; Pointer to the length of the buffer (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this cas + (i32.const 0) ;; Length is ignored in this case + (i32.const 132) ;; salt_ptr + (i32.const 2) ;; salt_len ) (i32.const 0) ) @@ -67,15 +75,15 @@ (call $assert (i32.eq (i32.load (i32.const 88)) - (i32.const 8) + (i32.const 32) ) ) ;; Store the return address. (call $seal_set_storage (i32.const 16) ;; Pointer to the key - (i32.const 80) ;; Pointer to the value - (i32.const 8) ;; Length of the value + (i32.const 100) ;; Pointer to the value + (i32.const 32) ;; Length of the value ) ) @@ -85,7 +93,7 @@ (i32.eq (call $seal_get_storage (i32.const 16) ;; Pointer to the key - (i32.const 80) ;; Pointer to the value + (i32.const 100) ;; Pointer to the value (i32.const 88) ;; Pointer to the len of the value ) (i32.const 0) @@ -94,7 +102,7 @@ (call $assert (i32.eq (i32.load (i32.const 88)) - (i32.const 8) + (i32.const 32) ) ) @@ -102,8 +110,8 @@ (call $assert (i32.eq (call $seal_call - (i32.const 80) ;; Pointer to destination address - (i32.const 8) ;; Length of destination address + (i32.const 100) ;; Pointer to destination address + (i32.const 32) ;; Length of destination address (i64.const 0) ;; How much gas to devote for the execution. 0 = all. (i32.const 0) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer @@ -121,8 +129,8 @@ (call $assert (i32.eq (call $seal_call - (i32.const 80) ;; Pointer to destination address - (i32.const 8) ;; Length of destination address + (i32.const 100) ;; Pointer to destination address + (i32.const 32) ;; Length of destination address (i64.const 0) ;; How much gas to devote for the execution. 0 = all. (i32.const 8) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer @@ -141,8 +149,8 @@ (call $assert (i32.eq (call $seal_transfer - (i32.const 80) ;; Pointer to destination address - (i32.const 8) ;; Length of destination address + (i32.const 100) ;; Pointer to destination address + (i32.const 32) ;; Length of destination address (i32.const 0) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer ) diff --git a/frame/contracts/fixtures/drain.wat b/frame/contracts/fixtures/drain.wat index 9180047f5d015..546026ac95986 100644 --- a/frame/contracts/fixtures/drain.wat +++ b/frame/contracts/fixtures/drain.wat @@ -38,7 +38,7 @@ (i32.eq (call $seal_transfer (i32.const 16) ;; Pointer to destination address - (i32.const 8) ;; Length of destination address + (i32.const 32) ;; Length of destination address (i32.const 0) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer ) diff --git a/frame/contracts/fixtures/instantiate_return_code.wat b/frame/contracts/fixtures/instantiate_return_code.wat index 20ab96d88ad2e..cead1f1c9fa40 100644 --- a/frame/contracts/fixtures/instantiate_return_code.wat +++ b/frame/contracts/fixtures/instantiate_return_code.wat @@ -1,47 +1,49 @@ -;; This instantiats Charlie (3) and transfers 100 balance during this call and copies the return code +;; This instantiats a contract and transfers 100 balance during this call and copies the return code ;; of this call to the output buffer. ;; The first 32 byte of input is the code hash to instantiate ;; The rest of the input is forwarded to the constructor of the callee (module (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_instantiate" (func $seal_instantiate (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32) (result i32))) + (import "seal0" "seal_instantiate" (func $seal_instantiate + (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32) + )) (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) - ;; [0, 8) address of django - (data (i32.const 0) "\04\00\00\00\00\00\00\00") + ;; [0, 8) 100 balance + (data (i32.const 0) "\64\00\00\00\00\00\00\00") - ;; [8, 16) 100 balance - (data (i32.const 8) "\64\00\00\00\00\00\00\00") + ;; [8, 12) here we store the return code of the transfer - ;; [16, 20) here we store the return code of the transfer + ;; [12, 16) size of the input buffer + (data (i32.const 12) "\24") - ;; [20, 24) size of the input buffer - (data (i32.const 20) "\FF") - - ;; [24, inf) input buffer + ;; [16, inf) input buffer + ;; 32 bye code hash + 4 byte forward (func (export "deploy")) (func (export "call") - (call $seal_input (i32.const 24) (i32.const 20)) + (call $seal_input (i32.const 16) (i32.const 12)) (i32.store - (i32.const 16) + (i32.const 8) (call $seal_instantiate - (i32.const 24) ;; Pointer to the code hash. + (i32.const 16) ;; Pointer to the code hash. (i32.const 32) ;; Length of the code hash. (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 8) ;; Pointer to the buffer with value to transfer + (i32.const 0) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 56) ;; Pointer to input data buffer address - (i32.sub (i32.load (i32.const 20)) (i32.const 32)) ;; Length of input data buffer + (i32.const 48) ;; Pointer to input data buffer address + (i32.const 4) ;; Length of input data buffer (i32.const 0xffffffff) ;; u32 max sentinel value: do not copy address (i32.const 0) ;; Length is ignored in this case (i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output (i32.const 0) ;; Length is ignored in this case + (i32.const 0) ;; salt_ptr + (i32.const 0) ;; salt_len ) ) ;; exit with success and take transfer return code to the output buffer - (call $seal_return (i32.const 0) (i32.const 16) (i32.const 4)) + (call $seal_return (i32.const 0) (i32.const 8) (i32.const 4)) ) ) diff --git a/frame/contracts/fixtures/restoration.wat b/frame/contracts/fixtures/restoration.wat index 3c15f7ae0881e..3462af2870816 100644 --- a/frame/contracts/fixtures/restoration.wat +++ b/frame/contracts/fixtures/restoration.wat @@ -19,20 +19,19 @@ (func (export "call") ;; copy code hash to contract memory - (call $seal_input (i32.const 264) (i32.const 304)) + (call $seal_input (i32.const 308) (i32.const 304)) (call $assert (i32.eq (i32.load (i32.const 304)) - (i32.const 32) + (i32.const 64) ) ) - (call $seal_restore_to ;; Pointer and length of the encoded dest buffer. - (i32.const 256) - (i32.const 8) + (i32.const 340) + (i32.const 32) ;; Pointer and length of the encoded code hash buffer - (i32.const 264) + (i32.const 308) (i32.const 32) ;; Pointer and length of the encoded rent_allowance buffer (i32.const 296) @@ -65,14 +64,12 @@ ;; Buffer that has ACL storage keys. (data (i32.const 100) "\01") - ;; Address of bob - (data (i32.const 256) "\02\00\00\00\00\00\00\00") - - ;; [264, 296) Code hash of SET_RENT (copied here by seal_input) - ;; [296, 304) Rent allowance (data (i32.const 296) "\32\00\00\00\00\00\00\00") - ;; [304, 308) Size of SET_RENT buffer - (data (i32.const 304) "\20") + ;; [304, 308) Size of the buffer that holds code_hash + addr + (data (i32.const 304) "\40") + + ;; [308, 340) code hash of bob (copied by seal_input) + ;; [340, 372) addr of bob (copied by seal_input) ) diff --git a/frame/contracts/fixtures/self_destruct.wat b/frame/contracts/fixtures/self_destruct.wat index 6898e746b0836..b8a37306e2011 100644 --- a/frame/contracts/fixtures/self_destruct.wat +++ b/frame/contracts/fixtures/self_destruct.wat @@ -5,20 +5,23 @@ (import "seal0" "seal_terminate" (func $seal_terminate (param i32 i32))) (import "env" "memory" (memory 1 1)) - ;; [0, 8) reserved for $seal_address output + ;; [0, 32) reserved for $seal_address output - ;; [8, 16) length of the buffer - (data (i32.const 8) "\08") + ;; [32, 36) length of the buffer + (data (i32.const 32) "\20") - ;; [16, 24) Address of django - (data (i32.const 16) "\04\00\00\00\00\00\00\00") + ;; [36, 68) Address of django + (data (i32.const 36) + "\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04" + "\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04" + ) - ;; [24, 32) reserved for output of $seal_input + ;; [68, 72) reserved for output of $seal_input - ;; [32, 36) length of the buffer - (data (i32.const 32) "\04") + ;; [72, 76) length of the buffer + (data (i32.const 72) "\04") - ;; [36, inf) zero initialized + ;; [76, inf) zero initialized (func $assert (param i32) (block $ok @@ -36,16 +39,16 @@ ;; This should trap instead of self-destructing since a contract cannot be removed live in ;; the execution stack cannot be removed. If the recursive call traps, then trap here as ;; well. - (call $seal_input (i32.const 24) (i32.const 32)) - (if (i32.load (i32.const 32)) + (call $seal_input (i32.const 68) (i32.const 72)) + (if (i32.load (i32.const 72)) (then - (call $seal_address (i32.const 0) (i32.const 8)) + (call $seal_address (i32.const 0) (i32.const 32)) ;; Expect address to be 8 bytes. (call $assert (i32.eq - (i32.load (i32.const 8)) - (i32.const 8) + (i32.load (i32.const 32)) + (i32.const 32) ) ) @@ -54,9 +57,9 @@ (i32.eq (call $seal_call (i32.const 0) ;; Pointer to own address - (i32.const 8) ;; Length of own address + (i32.const 32) ;; Length of own address (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 36) ;; Pointer to the buffer with value to transfer + (i32.const 76) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer (i32.const 0) ;; Pointer to input data buffer address (i32.const 0) ;; Length of input data buffer @@ -70,8 +73,8 @@ (else ;; Try to terminate and give balance to django. (call $seal_terminate - (i32.const 16) ;; Pointer to beneficiary address - (i32.const 8) ;; Length of beneficiary address + (i32.const 36) ;; Pointer to beneficiary address + (i32.const 32) ;; Length of beneficiary address ) (unreachable) ;; seal_terminate never returns ) diff --git a/frame/contracts/fixtures/self_destructing_constructor.wat b/frame/contracts/fixtures/self_destructing_constructor.wat index ab8c289f1b564..85fce511e21b9 100644 --- a/frame/contracts/fixtures/self_destructing_constructor.wat +++ b/frame/contracts/fixtures/self_destructing_constructor.wat @@ -15,7 +15,7 @@ ;; Self-destruct by sending full balance to the 0 address. (call $seal_terminate (i32.const 0) ;; Pointer to destination address - (i32.const 8) ;; Length of destination address + (i32.const 32) ;; Length of destination address ) ) diff --git a/frame/contracts/fixtures/set_rent.wat b/frame/contracts/fixtures/set_rent.wat index a09d3dc4bd47a..1c6b512cc77ac 100644 --- a/frame/contracts/fixtures/set_rent.wat +++ b/frame/contracts/fixtures/set_rent.wat @@ -26,7 +26,7 @@ (func $call_2 (call $assert (i32.eq - (call $seal_transfer (i32.const 68) (i32.const 8) (i32.const 76) (i32.const 8)) + (call $seal_transfer (i32.const 136) (i32.const 32) (i32.const 100) (i32.const 8)) (i32.const 0) ) ) @@ -47,10 +47,11 @@ ;; Dispatch the call according to input size (func (export "call") (local $input_size i32) - (i32.store (i32.const 64) (i32.const 64)) - (call $seal_input (i32.const 1024) (i32.const 64)) + ;; 4 byte i32 for br_table followed by 32 byte destination for transfer + (i32.store (i32.const 128) (i32.const 36)) + (call $seal_input (i32.const 132) (i32.const 128)) (set_local $input_size - (i32.load (i32.const 64)) + (i32.load (i32.const 132)) ) (block $IF_ELSE (block $IF_2 @@ -81,25 +82,24 @@ (i32.const 0) (i32.const 4) ) + (i32.store (i32.const 128) (i32.const 64)) (call $seal_input - (i32.const 0) - (i32.const 64) + (i32.const 104) + (i32.const 100) ) (call $seal_set_rent_allowance - (i32.const 0) - (i32.load (i32.const 64)) + (i32.const 104) + (i32.load (i32.const 128)) ) ) ;; Encoding of 10 in balance (data (i32.const 0) "\28") - ;; Size of the buffer at address 0 - (data (i32.const 64) "\40") + ;; encoding of 50 balance + (data (i32.const 100) "\32") - ;; encoding of Charlies's account id - (data (i32.const 68) "\03") + ;; [128, 132) size of seal input buffer - ;; encoding of 50 balance - (data (i32.const 76) "\32") + ;; [132, inf) output buffer for seal input ) diff --git a/frame/contracts/fixtures/transfer_return_code.wat b/frame/contracts/fixtures/transfer_return_code.wat index 7a1bec9adf38c..50098851dcf81 100644 --- a/frame/contracts/fixtures/transfer_return_code.wat +++ b/frame/contracts/fixtures/transfer_return_code.wat @@ -5,27 +5,30 @@ (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) - ;; [0, 8) zero-adress - (data (i32.const 0) "\00\00\00\00\00\00\00\00") + ;; [0, 32) zero-adress + (data (i32.const 0) + "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" + "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" + ) - ;; [8, 16) 100 balance - (data (i32.const 8) "\64\00\00\00\00\00\00\00") + ;; [32, 40) 100 balance + (data (i32.const 32) "\64\00\00\00\00\00\00\00") - ;; [16, 20) here we store the return code of the transfer + ;; [40, 44) here we store the return code of the transfer (func (export "deploy")) (func (export "call") (i32.store - (i32.const 16) + (i32.const 40) (call $seal_transfer (i32.const 0) ;; ptr to destination address - (i32.const 8) ;; length of destination address - (i32.const 8) ;; ptr to value to transfer + (i32.const 32) ;; length of destination address + (i32.const 32) ;; ptr to value to transfer (i32.const 8) ;; length of value to transfer ) ) ;; exit with success and take transfer return code to the output buffer - (call $seal_return (i32.const 0) (i32.const 16) (i32.const 4)) + (call $seal_return (i32.const 0) (i32.const 40) (i32.const 4)) ) ) diff --git a/frame/contracts/src/benchmarking/code.rs b/frame/contracts/src/benchmarking/code.rs index cb5052042aab2..f879d2eed5548 100644 --- a/frame/contracts/src/benchmarking/code.rs +++ b/frame/contracts/src/benchmarking/code.rs @@ -29,6 +29,7 @@ use crate::Module as Contracts; use parity_wasm::elements::{Instruction, Instructions, FuncBody, ValueType, BlockType}; use pwasm_utils::stack_height::inject_limiter; +use sp_core::crypto::UncheckedFrom; use sp_runtime::traits::Hash; use sp_sandbox::{EnvironmentDefinitionBuilder, Memory}; use sp_std::{prelude::*, convert::TryFrom}; @@ -86,7 +87,11 @@ pub struct ImportedMemory { } impl ImportedMemory { - pub fn max() -> Self { + pub fn max() -> Self + where + T: Trait, + T::AccountId: UncheckedFrom + AsRef<[u8]>, + { let pages = max_pages::(); Self { min_pages: pages, max_pages: pages } } @@ -106,7 +111,11 @@ pub struct WasmModule { memory: Option, } -impl From for WasmModule { +impl From for WasmModule +where + T: Trait, + T::AccountId: UncheckedFrom + AsRef<[u8]>, +{ fn from(def: ModuleDefinition) -> Self { // internal functions start at that offset. let func_offset = u32::try_from(def.imported_functions.len()).unwrap(); @@ -216,7 +225,11 @@ impl From for WasmModule { } } -impl WasmModule { +impl WasmModule +where + T: Trait, + T::AccountId: UncheckedFrom + AsRef<[u8]>, +{ /// Creates a wasm module with an empty `call` and `deploy` function and nothing else. pub fn dummy() -> Self { ModuleDefinition::default().into() @@ -470,6 +483,10 @@ pub mod body { } /// The maximum amount of pages any contract is allowed to have according to the current `Schedule`. -pub fn max_pages() -> u32 { +pub fn max_pages() -> u32 +where + T: Trait, + T::AccountId: UncheckedFrom + AsRef<[u8]>, +{ Contracts::::current_schedule().limits.memory_pages } diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index dd9e89d6f35ab..2e15542368a56 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -25,7 +25,9 @@ mod sandbox; use crate::{ *, Module as Contracts, exec::StorageKey, + rent::Rent, schedule::{API_BENCHMARK_BATCH_SIZE, INSTR_BENCHMARK_BATCH_SIZE}, + storage::Storage, }; use self::{ code::{ @@ -75,7 +77,11 @@ impl Endow { } } -impl Contract { +impl Contract +where + T: Trait, + T::AccountId: UncheckedFrom + AsRef<[u8]>, +{ /// Create new contract and use a default account id as instantiator. fn new( module: WasmModule, @@ -123,7 +129,8 @@ impl Contract { Endow::Max => (0u32.into(), Endow::max::()), }; T::Currency::make_free_balance_be(&caller, caller_funding::()); - let addr = T::DetermineContractAddress::contract_address_for(&module.hash, &data, &caller); + let salt = vec![0xff]; + let addr = Contracts::::contract_address(&caller, &module.hash, &salt); // The default block number is zero. The benchmarking system bumps the block number // to one for the benchmarking closure when it is set to zero. In order to prevent this @@ -139,6 +146,7 @@ impl Contract { Weight::max_value(), module.hash, data, + salt, )?; let result = Contract { @@ -160,7 +168,7 @@ impl Contract { fn store(&self, items: &Vec<(StorageKey, Vec)>) -> Result<(), &'static str> { let info = self.alive_info()?; for item in items { - crate::storage::write_contract_storage::( + Storage::::write( &self.account_id, &info.trie_id, &item.0, @@ -192,7 +200,7 @@ impl Contract { /// Get the block number when this contract will be evicted. Returns an error when /// the rent collection won't happen because the contract has to much endowment. fn eviction_at(&self) -> Result { - let projection = crate::rent::compute_rent_projection::(&self.account_id) + let projection = Rent::::compute_projection(&self.account_id) .map_err(|_| "Invalid acc for rent")?; match projection { RentProjection::EvictionAt(at) => Ok(at), @@ -211,7 +219,11 @@ struct Tombstone { storage: Vec<(StorageKey, Vec)>, } -impl Tombstone { +impl Tombstone +where + T: Trait, + T::AccountId: UncheckedFrom + AsRef<[u8]>, +{ /// Create and evict a new contract with the supplied storage item count and size each. fn new(stor_num: u32, stor_size: u32) -> Result { let contract = Contract::::new(WasmModule::dummy(), vec![], Endow::CollectRent)?; @@ -220,7 +232,7 @@ impl Tombstone { System::::set_block_number( contract.eviction_at()? + T::SignedClaimHandicap::get() + 5u32.into() ); - crate::rent::collect_rent::(&contract.account_id); + Rent::::collect(&contract.account_id); contract.ensure_tombstone()?; Ok(Tombstone { @@ -250,6 +262,11 @@ fn caller_funding() -> BalanceOf { } benchmarks! { + where_clause { where + T::AccountId: UncheckedFrom, + T::AccountId: AsRef<[u8]>, + } + _ { } @@ -276,17 +293,20 @@ benchmarks! { // The size of the input data influences the runtime because it is hashed in order to determine // the contract address. // `n`: Size of the data passed to constructor in kilobytes. + // `s`: Size of the salt in kilobytes. instantiate { let n in 0 .. code::max_pages::() * 64; + let s in 0 .. code::max_pages::() * 64; let data = vec![42u8; (n * 1024) as usize]; + let salt = vec![42u8; (s * 1024) as usize]; let endowment = Config::::subsistence_threshold_uncached(); let caller = whitelisted_caller(); T::Currency::make_free_balance_be(&caller, caller_funding::()); let WasmModule { code, hash, .. } = WasmModule::::dummy_with_mem(); let origin = RawOrigin::Signed(caller.clone()); - let addr = T::DetermineContractAddress::contract_address_for(&hash, &data, &caller); + let addr = Contracts::::contract_address(&caller, &hash, &salt); Contracts::::put_code_raw(code)?; - }: _(origin, endowment, Weight::max_value(), hash, data) + }: _(origin, endowment, Weight::max_value(), hash, data, salt) verify { // endowment was removed from the caller assert_eq!(T::Currency::free_balance(&caller), caller_funding::() - endowment); @@ -1000,7 +1020,7 @@ benchmarks! { let instance = Contract::::new(code, vec![], Endow::Max)?; let trie_id = instance.alive_info()?.trie_id; for key in keys { - crate::storage::write_contract_storage::( + Storage::::write( &instance.account_id, &trie_id, key.as_slice().try_into().map_err(|e| "Key has wrong length")?, @@ -1045,7 +1065,7 @@ benchmarks! { let instance = Contract::::new(code, vec![], Endow::Max)?; let trie_id = instance.alive_info()?.trie_id; for key in keys { - crate::storage::write_contract_storage::( + Storage::::write( &instance.account_id, &trie_id, key.as_slice().try_into().map_err(|e| "Key has wrong length")?, @@ -1089,7 +1109,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![], Endow::Max)?; let trie_id = instance.alive_info()?.trie_id; - crate::storage::write_contract_storage::( + Storage::::write( &instance.account_id, &trie_id, key.as_slice().try_into().map_err(|e| "Key has wrong length")?, @@ -1341,7 +1361,9 @@ benchmarks! { ValueType::I32, ValueType::I32, ValueType::I32, - ValueType::I32 + ValueType::I32, + ValueType::I32, + ValueType::I32, ], return_type: Some(ValueType::I32), }], @@ -1371,6 +1393,8 @@ benchmarks! { Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr Regular(Instruction::I32Const(0)), // output_len_ptr + Regular(Instruction::I32Const(0)), // salt_ptr + Regular(Instruction::I32Const(0)), // salt_ptr_len Regular(Instruction::Call(0)), Regular(Instruction::Drop), ])), @@ -1381,8 +1405,8 @@ benchmarks! { let callee = instance.addr.clone(); let addresses = hashes .iter() - .map(|hash| T::DetermineContractAddress::contract_address_for( - hash, &[], &instance.account_id + .map(|hash| Contracts::::contract_address( + &instance.account_id, hash, &[], )) .collect::>(); @@ -1398,9 +1422,10 @@ benchmarks! { } } - seal_instantiate_per_input_output_kb { + seal_instantiate_per_input_output_salt_kb { let i in 0 .. (code::max_pages::() - 1) * 64; let o in 0 .. (code::max_pages::() - 1) * 64; + let s in 0 .. (code::max_pages::() - 1) * 64; let callee_code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -1458,7 +1483,9 @@ benchmarks! { ValueType::I32, ValueType::I32, ValueType::I32, - ValueType::I32 + ValueType::I32, + ValueType::I32, + ValueType::I32, ], return_type: Some(ValueType::I32), }], @@ -1496,6 +1523,8 @@ benchmarks! { Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr Regular(Instruction::I32Const(output_offset as i32)), // output_ptr Regular(Instruction::I32Const(output_len_offset as i32)), // output_len_ptr + Counter(input_offset as u32, input_len as u32), // salt_ptr + Regular(Instruction::I32Const((s * 1024).max(input_len as u32) as i32)), // salt_len Regular(Instruction::Call(0)), Regular(Instruction::I32Eqz), Regular(Instruction::If(BlockType::NoResult)), @@ -2401,6 +2430,8 @@ mod tests { create_test!(seal_transfer); create_test!(seal_call); create_test!(seal_call_per_transfer_input_output_kb); + create_test!(seal_instantiate); + create_test!(seal_instantiate_per_input_output_salt_kb); create_test!(seal_clear_storage); create_test!(seal_hash_sha2_256); create_test!(seal_hash_sha2_256_per_kb); diff --git a/frame/contracts/src/benchmarking/sandbox.rs b/frame/contracts/src/benchmarking/sandbox.rs index 1d93db19ee59d..76cebfaf1ed6f 100644 --- a/frame/contracts/src/benchmarking/sandbox.rs +++ b/frame/contracts/src/benchmarking/sandbox.rs @@ -19,8 +19,11 @@ ///! sandbox to execute the wasm code. This is because we do not need the full ///! environment that provides the seal interface as imported functions. -use super::code::WasmModule; -use super::Trait; +use super::{ + Trait, + code::WasmModule, +}; +use sp_core::crypto::UncheckedFrom; use sp_sandbox::{EnvironmentDefinitionBuilder, Instance, Memory}; /// Minimal execution environment without any exported functions. @@ -36,7 +39,11 @@ impl Sandbox { } } -impl From<&WasmModule> for Sandbox { +impl From<&WasmModule> for Sandbox +where + T: Trait, + T::AccountId: UncheckedFrom + AsRef<[u8]>, +{ /// Creates an instance from the supplied module and supplies as much memory /// to the instance as the module declares as imported. fn from(module: &WasmModule) -> Self { diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index f93f262d821e9..73e1f564498dd 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -15,10 +15,11 @@ // along with Substrate. If not, see . use crate::{ - CodeHash, Config, ContractAddressFor, Event, RawEvent, Trait, - TrieId, BalanceOf, ContractInfo, TrieIdGenerator, - gas::GasMeter, rent, storage, Error, ContractInfoOf + CodeHash, Config, Event, RawEvent, Trait, Module as Contracts, + TrieId, BalanceOf, ContractInfo, gas::GasMeter, rent::Rent, storage::{self, Storage}, + Error, ContractInfoOf }; +use sp_core::crypto::UncheckedFrom; use sp_std::prelude::*; use sp_runtime::traits::{Bounded, Zero, Convert, Saturating}; use frame_support::{ @@ -75,6 +76,7 @@ pub trait Ext { value: BalanceOf, gas_meter: &mut GasMeter, input_data: Vec, + salt: &[u8], ) -> Result<(AccountIdOf, ExecReturnValue), ExecError>; /// Transfer some amount of funds into the specified account. @@ -118,7 +120,7 @@ pub trait Ext { code_hash: CodeHash, rent_allowance: BalanceOf, delta: Vec, - ) -> Result<(), &'static str>; + ) -> Result<(), DispatchError>; /// Returns a reference to the account id of the caller. fn caller(&self) -> &AccountIdOf; @@ -215,6 +217,7 @@ pub struct ExecutionContext<'a, T: Trait + 'a, V, L> { impl<'a, T, E, V, L> ExecutionContext<'a, T, V, L> where T: Trait, + T::AccountId: UncheckedFrom + AsRef<[u8]>, L: Loader, V: Vm, { @@ -264,12 +267,12 @@ where Err(Error::::MaxCallDepthReached)? } - // Assumption: `collect_rent` doesn't collide with overlay because - // `collect_rent` will be done on first call and destination contract and balance + // Assumption: `collect` doesn't collide with overlay because + // `collect` will be done on first call and destination contract and balance // cannot be changed before the first call // We do not allow 'calling' plain accounts. For transfering value // `seal_transfer` must be used. - let contract = if let Some(ContractInfo::Alive(info)) = rent::collect_rent::(&dest) { + let contract = if let Some(ContractInfo::Alive(info)) = Rent::::collect(&dest) { info } else { Err(Error::::NotCallable)? @@ -308,6 +311,7 @@ where gas_meter: &mut GasMeter, code_hash: &CodeHash, input_data: Vec, + salt: &[u8], ) -> Result<(T::AccountId, ExecReturnValue), ExecError> { if self.depth == self.config.max_depth as usize { Err(Error::::MaxCallDepthReached)? @@ -315,19 +319,15 @@ where let transactor_kind = self.transactor_kind(); let caller = self.self_account.clone(); - let dest = T::DetermineContractAddress::contract_address_for( - code_hash, - &input_data, - &caller, - ); + let dest = Contracts::::contract_address(&caller, code_hash, salt); // TrieId has not been generated yet and storage is empty since contract is new. // // Generate it now. - let dest_trie_id = ::TrieIdGenerator::trie_id(&dest); + let dest_trie_id = Storage::::generate_trie_id(&dest); let output = self.with_nested_context(dest.clone(), dest_trie_id, |nested| { - storage::place_contract::( + Storage::::place_contract( &dest, nested .self_trie_id @@ -444,7 +444,10 @@ fn transfer<'a, T: Trait, V: Vm, L: Loader>( dest: &T::AccountId, value: BalanceOf, ctx: &mut ExecutionContext<'a, T, V, L>, -) -> Result<(), DispatchError> { +) -> Result<(), DispatchError> +where + T::AccountId: UncheckedFrom + AsRef<[u8]>, +{ use self::TransferCause::*; use self::TransactorKind::*; @@ -491,6 +494,7 @@ struct CallContext<'a, 'b: 'a, T: Trait + 'b, V: Vm + 'b, L: Loader> { impl<'a, 'b: 'a, T, E, V, L> Ext for CallContext<'a, 'b, T, V, L> where T: Trait + 'b, + T::AccountId: UncheckedFrom + AsRef<[u8]>, V: Vm, L: Loader, { @@ -503,7 +507,7 @@ where expect can't fail;\ qed", ); - storage::read_contract_storage(trie_id, key) + Storage::::read(trie_id, key) } fn set_storage(&mut self, key: StorageKey, value: Option>) { @@ -514,12 +518,12 @@ where qed", ); if let Err(storage::ContractAbsentError) = - storage::write_contract_storage::(&self.ctx.self_account, trie_id, &key, value) + Storage::::write(&self.ctx.self_account, trie_id, &key, value) { panic!( "the contract must be in the alive state within the `CallContext`;\ the contract cannot be absent in storage; - write_contract_storage cannot return `None`; + write cannot return `None`; qed" ); } @@ -531,8 +535,9 @@ where endowment: BalanceOf, gas_meter: &mut GasMeter, input_data: Vec, + salt: &[u8], ) -> Result<(AccountIdOf, ExecReturnValue), ExecError> { - self.ctx.instantiate(endowment, gas_meter, code_hash, input_data) + self.ctx.instantiate(endowment, gas_meter, code_hash, input_data, salt) } fn transfer( @@ -558,9 +563,7 @@ where let value = T::Currency::free_balance(&self_id); if let Some(caller_ctx) = self.ctx.caller { if caller_ctx.is_live(&self_id) { - return Err(DispatchError::Other( - "Cannot terminate a contract that is present on the call stack", - )); + return Err(Error::::ReentranceDenied.into()); } } transfer( @@ -576,7 +579,7 @@ where a contract has a trie id;\ this can't be None; qed", ); - storage::destroy_contract::(&self_id, self_trie_id); + Storage::::destroy_contract(&self_id, self_trie_id); Ok(()) } @@ -596,16 +599,14 @@ where code_hash: CodeHash, rent_allowance: BalanceOf, delta: Vec, - ) -> Result<(), &'static str> { + ) -> Result<(), DispatchError> { if let Some(caller_ctx) = self.ctx.caller { if caller_ctx.is_live(&self.ctx.self_account) { - return Err( - "Cannot perform restoration of a contract that is present on the call stack", - ); + return Err(Error::::ReentranceDenied.into()); } } - let result = crate::rent::restore_to::( + let result = Rent::::restore_to( self.ctx.self_account.clone(), dest.clone(), code_hash.clone(), @@ -667,7 +668,7 @@ where fn set_rent_allowance(&mut self, rent_allowance: BalanceOf) { if let Err(storage::ContractAbsentError) = - storage::set_rent_allowance::(&self.ctx.self_account, rent_allowance) + Storage::::set_rent_allowance(&self.ctx.self_account, rent_allowance) { panic!( "`self_account` points to an alive contract within the `CallContext`; @@ -677,7 +678,7 @@ where } fn rent_allowance(&self) -> BalanceOf { - storage::rent_allowance::(&self.ctx.self_account) + Storage::::rent_allowance(&self.ctx.self_account) .unwrap_or_else(|_| >::max_value()) // Must never be triggered actually } @@ -711,23 +712,21 @@ fn deposit_event( mod tests { use super::{ BalanceOf, Event, ExecResult, ExecutionContext, Ext, Loader, - RawEvent, Vm, ReturnFlags, ExecError, ErrorOrigin + RawEvent, Vm, ReturnFlags, ExecError, ErrorOrigin, AccountIdOf, }; use crate::{ gas::GasMeter, tests::{ExtBuilder, Test, MetaEvent}, exec::ExecReturnValue, CodeHash, Config, gas::Gas, - storage, Error + storage::Storage, + tests::{ALICE, BOB, CHARLIE}, + Error, }; use crate::tests::test_utils::{place_contract, set_balance, get_balance}; use sp_runtime::DispatchError; use assert_matches::assert_matches; use std::{cell::RefCell, collections::HashMap, marker::PhantomData, rc::Rc}; - const ALICE: u64 = 1; - const BOB: u64 = 2; - const CHARLIE: u64 = 3; - const GAS_LIMIT: Gas = 10_000_000_000; fn events() -> Vec> { @@ -869,7 +868,7 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); - let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + let mut ctx = ExecutionContext::top_level(origin.clone(), &cfg, &vm, &loader); set_balance(&origin, 100); set_balance(&dest, 0); @@ -902,13 +901,13 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); - let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + let mut ctx = ExecutionContext::top_level(origin.clone(), &cfg, &vm, &loader); place_contract(&BOB, return_ch); set_balance(&origin, 100); set_balance(&dest, 0); let output = ctx.call( - dest, + dest.clone(), 55, &mut GasMeter::::new(GAS_LIMIT), vec![], @@ -932,7 +931,7 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); - let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + let mut ctx = ExecutionContext::top_level(origin.clone(), &cfg, &vm, &loader); set_balance(&origin, 0); let result = super::transfer( @@ -1061,6 +1060,7 @@ mod tests { &mut GasMeter::::new(GAS_LIMIT), &input_data_ch, vec![1, 2, 3, 4], + &[], ); assert_matches!(result, Ok(_)); }); @@ -1120,13 +1120,13 @@ mod tests { let vm = MockVm::new(); - let witnessed_caller_bob = RefCell::new(None::); - let witnessed_caller_charlie = RefCell::new(None::); + let witnessed_caller_bob = RefCell::new(None::>); + let witnessed_caller_charlie = RefCell::new(None::>); let mut loader = MockLoader::empty(); let bob_ch = loader.insert(|ctx| { // Record the caller for bob. - *witnessed_caller_bob.borrow_mut() = Some(*ctx.ext.caller()); + *witnessed_caller_bob.borrow_mut() = Some(ctx.ext.caller().clone()); // Call into CHARLIE contract. assert_matches!( @@ -1137,19 +1137,19 @@ mod tests { }); let charlie_ch = loader.insert(|ctx| { // Record the caller for charlie. - *witnessed_caller_charlie.borrow_mut() = Some(*ctx.ext.caller()); + *witnessed_caller_charlie.borrow_mut() = Some(ctx.ext.caller().clone()); exec_success() }); ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); - let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + let mut ctx = ExecutionContext::top_level(origin.clone(), &cfg, &vm, &loader); place_contract(&dest, bob_ch); place_contract(&CHARLIE, charlie_ch); let result = ctx.call( - dest, + dest.clone(), 0, &mut GasMeter::::new(GAS_LIMIT), vec![], @@ -1217,6 +1217,7 @@ mod tests { &mut GasMeter::::new(GAS_LIMIT), &dummy_ch, vec![], + &[], ), Err(_) ); @@ -1243,13 +1244,14 @@ mod tests { &mut GasMeter::::new(GAS_LIMIT), &dummy_ch, vec![], + &[], ), Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address ); // Check that the newly created account has the expected code hash and // there are instantiation event. - assert_eq!(storage::code_hash::(&instantiated_contract_address).unwrap(), dummy_ch); + assert_eq!(Storage::::code_hash(&instantiated_contract_address).unwrap(), dummy_ch); assert_eq!(&events(), &[ RawEvent::Instantiated(ALICE, instantiated_contract_address) ]); @@ -1276,12 +1278,13 @@ mod tests { &mut GasMeter::::new(GAS_LIMIT), &dummy_ch, vec![], + &[], ), Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address ); // Check that the account has not been created. - assert!(storage::code_hash::(&instantiated_contract_address).is_err()); + assert!(Storage::::code_hash(&instantiated_contract_address).is_err()); assert!(events().is_empty()); }); } @@ -1292,7 +1295,7 @@ mod tests { let mut loader = MockLoader::empty(); let dummy_ch = loader.insert(|_| exec_success()); - let instantiated_contract_address = Rc::new(RefCell::new(None::)); + let instantiated_contract_address = Rc::new(RefCell::new(None::>)); let instantiator_ch = loader.insert({ let dummy_ch = dummy_ch.clone(); let instantiated_contract_address = Rc::clone(&instantiated_contract_address); @@ -1302,7 +1305,8 @@ mod tests { &dummy_ch, Config::::subsistence_threshold_uncached(), ctx.gas_meter, - vec![] + vec![], + &[48, 49, 50], ).unwrap(); *instantiated_contract_address.borrow_mut() = address.into(); @@ -1326,7 +1330,7 @@ mod tests { // Check that the newly created account has the expected code hash and // there are instantiation event. - assert_eq!(storage::code_hash::(&instantiated_contract_address).unwrap(), dummy_ch); + assert_eq!(Storage::::code_hash(&instantiated_contract_address).unwrap(), dummy_ch); assert_eq!(&events(), &[ RawEvent::Instantiated(BOB, instantiated_contract_address) ]); @@ -1350,7 +1354,8 @@ mod tests { &dummy_ch, 15u64, ctx.gas_meter, - vec![] + vec![], + &[], ), Err(ExecError { error: DispatchError::Other("It's a trap!"), @@ -1405,6 +1410,7 @@ mod tests { &mut GasMeter::::new(GAS_LIMIT), &terminate_ch, vec![], + &[], ), Err(Error::::NewContractNotFunded.into()) ); @@ -1437,6 +1443,7 @@ mod tests { &mut GasMeter::::new(GAS_LIMIT), &rent_allowance_ch, vec![], + &[], ); assert_matches!(result, Ok(_)); }); diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index f43bfd0ebdb6f..65995afb73d6a 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -93,14 +93,18 @@ pub mod weights; #[cfg(test)] mod tests; -use crate::exec::ExecutionContext; -use crate::wasm::{WasmLoader, WasmVm}; -use crate::weights::WeightInfo; - -pub use crate::gas::{Gas, GasMeter}; -pub use crate::wasm::ReturnCode as RuntimeReturnCode; -pub use crate::schedule::{Schedule, HostFnWeights, InstructionWeights, Limits}; - +pub use crate::{ + gas::{Gas, GasMeter}, + wasm::ReturnCode as RuntimeReturnCode, + weights::WeightInfo, + schedule::{Schedule, HostFnWeights, InstructionWeights, Limits}, +}; +use crate::{ + exec::ExecutionContext, + wasm::{WasmLoader, WasmVm}, + rent::Rent, + storage::Storage, +}; use sp_core::crypto::UncheckedFrom; use sp_std::{prelude::*, marker::PhantomData, fmt::Debug}; use codec::{Codec, Encode, Decode}; @@ -112,7 +116,7 @@ use sp_runtime::{ }; use frame_support::{ decl_module, decl_event, decl_storage, decl_error, ensure, - parameter_types, storage::child::ChildInfo, + storage::child::ChildInfo, dispatch::{DispatchResult, DispatchResultWithPostInfo}, traits::{OnUnbalanced, Currency, Get, Time, Randomness}, }; @@ -125,11 +129,6 @@ use frame_support::weights::Weight; pub type CodeHash = ::Hash; pub type TrieId = Vec; -/// A function that generates an `AccountId` for a contract upon instantiation. -pub trait ContractAddressFor { - fn contract_address_for(code_hash: &CodeHash, data: &[u8], origin: &AccountId) -> AccountId; -} - /// Information for managing an account and its sub trie abstraction. /// This is the required info to cache for an account #[derive(Encode, Decode, RuntimeDebug)] @@ -257,66 +256,11 @@ impl From> for ContractInfo { } } -/// Get a trie id (trie id must be unique and collision resistant depending upon its context). -/// Note that it is different than encode because trie id should be collision resistant -/// (being a proper unique identifier). -pub trait TrieIdGenerator { - /// Get a trie id for an account, using reference to parent account trie id to ensure - /// uniqueness of trie id. - /// - /// The implementation must ensure every new trie id is unique: two consecutive calls with the - /// same parameter needs to return different trie id values. - fn trie_id(account_id: &AccountId) -> TrieId; -} - -/// Get trie id from `account_id`. -pub struct TrieIdFromParentCounter(PhantomData); - -/// This generator uses inner counter for account id and applies the hash over `AccountId + -/// accountid_counter`. -impl TrieIdGenerator for TrieIdFromParentCounter -where - T::AccountId: AsRef<[u8]> -{ - fn trie_id(account_id: &T::AccountId) -> TrieId { - // Note that skipping a value due to error is not an issue here. - // We only need uniqueness, not sequence. - let new_seed = AccountCounter::mutate(|v| { - *v = v.wrapping_add(1); - *v - }); - - let mut buf = Vec::new(); - buf.extend_from_slice(account_id.as_ref()); - buf.extend_from_slice(&new_seed.to_le_bytes()[..]); - T::Hashing::hash(&buf[..]).as_ref().into() - } -} - pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; pub type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; -parameter_types! { - /// A reasonable default value for [`Trait::SignedClaimedHandicap`]. - pub const DefaultSignedClaimHandicap: u32 = 2; - /// A reasonable default value for [`Trait::TombstoneDeposit`]. - pub const DefaultTombstoneDeposit: u32 = 16; - /// A reasonable default value for [`Trait::StorageSizeOffset`]. - pub const DefaultStorageSizeOffset: u32 = 8; - /// A reasonable default value for [`Trait::RentByteFee`]. - pub const DefaultRentByteFee: u32 = 4; - /// A reasonable default value for [`Trait::RentDepositOffset`]. - pub const DefaultRentDepositOffset: u32 = 1000; - /// A reasonable default value for [`Trait::SurchargeReward`]. - pub const DefaultSurchargeReward: u32 = 150; - /// A reasonable default value for [`Trait::MaxDepth`]. - pub const DefaultMaxDepth: u32 = 32; - /// A reasonable default value for [`Trait::MaxValueSize`]. - pub const DefaultMaxValueSize: u32 = 16_384; -} - pub trait Trait: frame_system::Trait { type Time: Time; type Randomness: Randomness; @@ -327,12 +271,6 @@ pub trait Trait: frame_system::Trait { /// The overarching event type. type Event: From> + Into<::Event>; - /// A function type to get the contract address given the instantiator. - type DetermineContractAddress: ContractAddressFor, Self::AccountId>; - - /// trie id generator - type TrieIdGenerator: TrieIdGenerator; - /// Handler for rent payments. type RentPayment: OnUnbalanced>; @@ -383,32 +321,13 @@ pub trait Trait: frame_system::Trait { type WeightInfo: WeightInfo; } -/// Simple contract address determiner. -/// -/// Address calculated from the code (of the constructor), input data to the constructor, -/// and the account id that requested the account creation. -/// -/// Formula: `blake2_256(blake2_256(code) + blake2_256(data) + origin)` -pub struct SimpleAddressDeterminer(PhantomData); -impl ContractAddressFor, T::AccountId> for SimpleAddressDeterminer -where - T::AccountId: UncheckedFrom + AsRef<[u8]> -{ - fn contract_address_for(code_hash: &CodeHash, data: &[u8], origin: &T::AccountId) -> T::AccountId { - let data_hash = T::Hashing::hash(data); - - let mut buf = Vec::new(); - buf.extend_from_slice(code_hash.as_ref()); - buf.extend_from_slice(data_hash.as_ref()); - buf.extend_from_slice(origin.as_ref()); - - UncheckedFrom::unchecked_from(T::Hashing::hash(&buf[..])) - } -} - decl_error! { /// Error for the contracts module. - pub enum Error for Module { + pub enum Error for Module + where + T::AccountId: UncheckedFrom, + T::AccountId: AsRef<[u8]>, + { /// A new schedule must have a greater version than the current one. InvalidScheduleVersion, /// An origin must be signed or inherent and auxiliary sender only provided on inherent. @@ -455,12 +374,21 @@ decl_error! { ContractTrapped, /// The size defined in `T::MaxValueSize` was exceeded. ValueTooLarge, + /// The action performed is not allowed while the contract performing it is already + /// on the call stack. Those actions are contract self destruction and restoration + /// of a tombstone. + ReentranceDenied, } } decl_module! { /// Contracts module. - pub struct Module for enum Call where origin: ::Origin { + pub struct Module for enum Call + where + origin: T::Origin, + T::AccountId: UncheckedFrom, + T::AccountId: AsRef<[u8]>, + { type Error = Error; /// Number of block delay an extrinsic claim surcharge has. @@ -563,29 +491,38 @@ decl_module! { gas_meter.into_dispatch_result(result) } - /// Instantiates a new contract from the `codehash` generated by `put_code`, optionally transferring some balance. + /// Instantiates a new contract from the `code_hash` generated by `put_code`, + /// optionally transferring some balance. + /// + /// The supplied `salt` is used for contract address deriviation. See `fn contract_address`. /// /// Instantiation is executed as follows: /// - /// - The destination address is computed based on the sender and hash of the code. + /// - The destination address is computed based on the sender, code_hash and the salt. /// - The smart-contract account is created at the computed address. /// - The `ctor_code` is executed in the context of the newly-created account. Buffer returned /// after the execution is saved as the `code` of the account. That code will be invoked /// upon any call received by this account. /// - The contract is initialized. - #[weight = T::WeightInfo::instantiate(data.len() as u32 / 1024).saturating_add(*gas_limit)] + #[weight = + T::WeightInfo::instantiate( + data.len() as u32 / 1024, + salt.len() as u32 / 1024, + ).saturating_add(*gas_limit) + ] pub fn instantiate( origin, #[compact] endowment: BalanceOf, #[compact] gas_limit: Gas, code_hash: CodeHash, - data: Vec + data: Vec, + salt: Vec, ) -> DispatchResultWithPostInfo { let origin = ensure_signed(origin)?; let mut gas_meter = GasMeter::new(gas_limit); let result = Self::execute_wasm(origin, &mut gas_meter, |ctx, gas_meter| { - ctx.instantiate(endowment, gas_meter, &code_hash, data) + ctx.instantiate(endowment, gas_meter, &code_hash, data, &salt) .map(|(_address, output)| output) }); gas_meter.into_dispatch_result(result) @@ -619,7 +556,7 @@ decl_module! { }; // If poking the contract has lead to eviction of the contract, give out the rewards. - if rent::snitch_contract_should_be_evicted::(&dest, handicap) { + if Rent::::snitch_contract_should_be_evicted(&dest, handicap) { T::Currency::deposit_into_existing(&rewarded, T::SurchargeReward::get())?; } } @@ -627,7 +564,10 @@ decl_module! { } /// Public APIs provided by the contracts module. -impl Module { +impl Module +where + T::AccountId: UncheckedFrom + AsRef<[u8]>, +{ /// Perform a call to a specified contract. /// /// This function is similar to `Self::call`, but doesn't perform any address lookups and better @@ -659,12 +599,12 @@ impl Module { .get_alive() .ok_or(ContractAccessError::IsTombstone)?; - let maybe_value = storage::read_contract_storage(&contract_info.trie_id, &key); + let maybe_value = Storage::::read(&contract_info.trie_id, &key); Ok(maybe_value) } pub fn rent_projection(address: T::AccountId) -> RentProjectionResult { - rent::compute_rent_projection::(&address) + Rent::::compute_projection(&address) } /// Put code for benchmarks which does not check or instrument the code. @@ -674,9 +614,34 @@ impl Module { let result = wasm::save_code_raw::(code, &schedule); result.map(|_| ()).map_err(Into::into) } + + /// Determine the address of a contract, + /// + /// This is the address generation function used by contract instantation. Its result + /// is only dependend on its inputs. It can therefore be used to reliably predict the + /// address of a contract. This is akin to the formular of eth's CRATE2 opcode. There + /// is no CREATE equivalent because CREATE2 is strictly more powerful. + /// + /// Formula: `hash(deploying_address ++ code_hash ++ salt)` + pub fn contract_address( + deploying_address: &T::AccountId, + code_hash: &CodeHash, + salt: &[u8], + ) -> T::AccountId + { + let buf: Vec<_> = deploying_address.as_ref().iter() + .chain(code_hash.as_ref()) + .chain(salt) + .cloned() + .collect(); + UncheckedFrom::unchecked_from(T::Hashing::hash(&buf)) + } } -impl Module { +impl Module +where + T::AccountId: UncheckedFrom + AsRef<[u8]>, +{ fn execute_wasm( origin: T::AccountId, gas_meter: &mut GasMeter, @@ -734,7 +699,10 @@ decl_event! { } decl_storage! { - trait Store for Module as Contracts { + trait Store for Module as Contracts + where + T::AccountId: UncheckedFrom + AsRef<[u8]> + { /// Current cost schedule for contracts. CurrentSchedule get(fn current_schedule) config(): Schedule = Default::default(); /// A mapping from an original code hash to the original code, untouched by instrumentation. @@ -762,7 +730,10 @@ pub struct Config { pub max_value_size: u32, } -impl Config { +impl Config +where + T::AccountId: UncheckedFrom + AsRef<[u8]> +{ fn preload() -> Config { Config { schedule: >::current_schedule(), diff --git a/frame/contracts/src/rent.rs b/frame/contracts/src/rent.rs index 3dc473363190b..a8886b990a95f 100644 --- a/frame/contracts/src/rent.rs +++ b/frame/contracts/src/rent.rs @@ -18,15 +18,19 @@ use crate::{ AliveContractInfo, BalanceOf, ContractInfo, ContractInfoOf, Module, RawEvent, - TombstoneContractInfo, Trait, CodeHash, Config + TombstoneContractInfo, Trait, CodeHash, Config, Error, }; use sp_std::prelude::*; use sp_io::hashing::blake2_256; +use sp_core::crypto::UncheckedFrom; use frame_support::storage::child; use frame_support::traits::{Currency, ExistenceRequirement, Get, OnUnbalanced, WithdrawReasons}; use frame_support::StorageMap; use pallet_contracts_primitives::{ContractAccessError, RentProjection, RentProjectionResult}; -use sp_runtime::traits::{Bounded, CheckedDiv, CheckedMul, SaturatedConversion, Saturating, Zero}; +use sp_runtime::{ + DispatchError, + traits::{Bounded, CheckedDiv, CheckedMul, SaturatedConversion, Saturating, Zero}, +}; /// The amount to charge. /// @@ -82,405 +86,412 @@ enum Verdict { Charge { amount: OutstandingAmount }, } -/// Returns a fee charged per block from the contract. -/// -/// This function accounts for the storage rent deposit. I.e. if the contract possesses enough funds -/// then the fee can drop to zero. -fn compute_fee_per_block( - free_balance: &BalanceOf, - contract: &AliveContractInfo, -) -> BalanceOf { - let free_storage = free_balance - .checked_div(&T::RentDepositOffset::get()) - .unwrap_or_else(Zero::zero); - - // For now, we treat every empty KV pair as if it was one byte long. - let empty_pairs_equivalent = contract.empty_pair_count; - - let effective_storage_size = >::from( - contract.storage_size + T::StorageSizeOffset::get() + empty_pairs_equivalent, - ) - .saturating_sub(free_storage); - - effective_storage_size - .checked_mul(&T::RentByteFee::get()) - .unwrap_or_else(|| >::max_value()) -} +pub struct Rent(sp_std::marker::PhantomData); -/// Returns amount of funds available to consume by rent mechanism. -/// -/// Rent mechanism cannot consume more than `rent_allowance` set by the contract and it cannot make -/// the balance lower than [`subsistence_threshold`]. -/// -/// In case the toal_balance is below the subsistence threshold, this function returns `None`. -fn rent_budget( - total_balance: &BalanceOf, - free_balance: &BalanceOf, - contract: &AliveContractInfo, -) -> Option> { - let subsistence_threshold = Config::::subsistence_threshold_uncached(); - // Reserved balance contributes towards the subsistence threshold to stay consistent - // with the existential deposit where the reserved balance is also counted. - if *total_balance < subsistence_threshold { - return None; +impl Rent +where + T: Trait, + T::AccountId: UncheckedFrom + AsRef<[u8]> +{ + /// Returns a fee charged per block from the contract. + /// + /// This function accounts for the storage rent deposit. I.e. if the contract possesses enough funds + /// then the fee can drop to zero. + fn compute_fee_per_block( + free_balance: &BalanceOf, + contract: &AliveContractInfo + ) -> BalanceOf { + let free_storage = free_balance + .checked_div(&T::RentDepositOffset::get()) + .unwrap_or_else(Zero::zero); + + // For now, we treat every empty KV pair as if it was one byte long. + let empty_pairs_equivalent = contract.empty_pair_count; + + let effective_storage_size = >::from( + contract.storage_size + T::StorageSizeOffset::get() + empty_pairs_equivalent, + ) + .saturating_sub(free_storage); + + effective_storage_size + .checked_mul(&T::RentByteFee::get()) + .unwrap_or_else(|| >::max_value()) } - // However, reserved balance cannot be charged so we need to use the free balance - // to calculate the actual budget (which can be 0). - let rent_allowed_to_charge = free_balance.saturating_sub(subsistence_threshold); - Some(>::min( - contract.rent_allowance, - rent_allowed_to_charge, - )) -} + /// Returns amount of funds available to consume by rent mechanism. + /// + /// Rent mechanism cannot consume more than `rent_allowance` set by the contract and it cannot make + /// the balance lower than [`subsistence_threshold`]. + /// + /// In case the toal_balance is below the subsistence threshold, this function returns `None`. + fn rent_budget( + total_balance: &BalanceOf, + free_balance: &BalanceOf, + contract: &AliveContractInfo, + ) -> Option> { + let subsistence_threshold = Config::::subsistence_threshold_uncached(); + // Reserved balance contributes towards the subsistence threshold to stay consistent + // with the existential deposit where the reserved balance is also counted. + if *total_balance < subsistence_threshold { + return None; + } -/// Consider the case for rent payment of the given account and returns a `Verdict`. -/// -/// Use `handicap` in case you want to change the reference block number. (To get more details see -/// `snitch_contract_should_be_evicted` ). -fn consider_case( - account: &T::AccountId, - current_block_number: T::BlockNumber, - handicap: T::BlockNumber, - contract: &AliveContractInfo, -) -> Verdict { - // How much block has passed since the last deduction for the contract. - let blocks_passed = { - // Calculate an effective block number, i.e. after adjusting for handicap. - let effective_block_number = current_block_number.saturating_sub(handicap); - effective_block_number.saturating_sub(contract.deduct_block) - }; - if blocks_passed.is_zero() { - // Rent has already been paid - return Verdict::Exempt; + // However, reserved balance cannot be charged so we need to use the free balance + // to calculate the actual budget (which can be 0). + let rent_allowed_to_charge = free_balance.saturating_sub(subsistence_threshold); + Some(>::min( + contract.rent_allowance, + rent_allowed_to_charge, + )) } - let total_balance = T::Currency::total_balance(account); - let free_balance = T::Currency::free_balance(account); + /// Consider the case for rent payment of the given account and returns a `Verdict`. + /// + /// Use `handicap` in case you want to change the reference block number. (To get more details see + /// `snitch_contract_should_be_evicted` ). + fn consider_case( + account: &T::AccountId, + current_block_number: T::BlockNumber, + handicap: T::BlockNumber, + contract: &AliveContractInfo, + ) -> Verdict { + // How much block has passed since the last deduction for the contract. + let blocks_passed = { + // Calculate an effective block number, i.e. after adjusting for handicap. + let effective_block_number = current_block_number.saturating_sub(handicap); + effective_block_number.saturating_sub(contract.deduct_block) + }; + if blocks_passed.is_zero() { + // Rent has already been paid + return Verdict::Exempt; + } - // An amount of funds to charge per block for storage taken up by the contract. - let fee_per_block = compute_fee_per_block::(&free_balance, contract); - if fee_per_block.is_zero() { - // The rent deposit offset reduced the fee to 0. This means that the contract - // gets the rent for free. - return Verdict::Exempt; - } + let total_balance = T::Currency::total_balance(account); + let free_balance = T::Currency::free_balance(account); - let rent_budget = match rent_budget::(&total_balance, &free_balance, contract) { - Some(rent_budget) => rent_budget, - None => { - // The contract's total balance is already below subsistence threshold. That - // indicates that the contract cannot afford to leave a tombstone. - // - // So cleanly wipe the contract. - return Verdict::Kill; + // An amount of funds to charge per block for storage taken up by the contract. + let fee_per_block = Self::compute_fee_per_block(&free_balance, contract); + if fee_per_block.is_zero() { + // The rent deposit offset reduced the fee to 0. This means that the contract + // gets the rent for free. + return Verdict::Exempt; } - }; - - let dues = fee_per_block - .checked_mul(&blocks_passed.saturated_into::().into()) - .unwrap_or_else(|| >::max_value()); - let insufficient_rent = rent_budget < dues; - - // If the rent payment cannot be withdrawn due to locks on the account balance, then evict the - // account. - // - // NOTE: This seems problematic because it provides a way to tombstone an account while - // avoiding the last rent payment. In effect, someone could retroactively set rent_allowance - // for their contract to 0. - let dues_limited = dues.min(rent_budget); - let can_withdraw_rent = T::Currency::ensure_can_withdraw( - account, - dues_limited, - WithdrawReasons::FEE, - free_balance.saturating_sub(dues_limited), - ) - .is_ok(); - - if insufficient_rent || !can_withdraw_rent { - // The contract cannot afford the rent payment and has a balance above the subsistence - // threshold, so it leaves a tombstone. - let amount = if can_withdraw_rent { - Some(OutstandingAmount::new(dues_limited)) - } else { - None + + let rent_budget = match Self::rent_budget(&total_balance, &free_balance, contract) { + Some(rent_budget) => rent_budget, + None => { + // The contract's total balance is already below subsistence threshold. That + // indicates that the contract cannot afford to leave a tombstone. + // + // So cleanly wipe the contract. + return Verdict::Kill; + } + }; + + let dues = fee_per_block + .checked_mul(&blocks_passed.saturated_into::().into()) + .unwrap_or_else(|| >::max_value()); + let insufficient_rent = rent_budget < dues; + + // If the rent payment cannot be withdrawn due to locks on the account balance, then evict the + // account. + // + // NOTE: This seems problematic because it provides a way to tombstone an account while + // avoiding the last rent payment. In effect, someone could retroactively set rent_allowance + // for their contract to 0. + let dues_limited = dues.min(rent_budget); + let can_withdraw_rent = T::Currency::ensure_can_withdraw( + account, + dues_limited, + WithdrawReasons::FEE, + free_balance.saturating_sub(dues_limited), + ) + .is_ok(); + + if insufficient_rent || !can_withdraw_rent { + // The contract cannot afford the rent payment and has a balance above the subsistence + // threshold, so it leaves a tombstone. + let amount = if can_withdraw_rent { + Some(OutstandingAmount::new(dues_limited)) + } else { + None + }; + return Verdict::Evict { amount }; + } + + return Verdict::Charge { + // We choose to use `dues_limited` here instead of `dues` just to err on the safer side. + amount: OutstandingAmount::new(dues_limited), }; - return Verdict::Evict { amount }; } - return Verdict::Charge { - // We choose to use `dues_limited` here instead of `dues` just to err on the safer side. - amount: OutstandingAmount::new(dues_limited), - }; -} + /// Enacts the given verdict and returns the updated `ContractInfo`. + /// + /// `alive_contract_info` should be from the same address as `account`. + fn enact_verdict( + account: &T::AccountId, + alive_contract_info: AliveContractInfo, + current_block_number: T::BlockNumber, + verdict: Verdict, + ) -> Option> { + match verdict { + Verdict::Exempt => return Some(ContractInfo::Alive(alive_contract_info)), + Verdict::Kill => { + >::remove(account); + child::kill_storage( + &alive_contract_info.child_trie_info(), + ); + >::deposit_event(RawEvent::Evicted(account.clone(), false)); + None + } + Verdict::Evict { amount } => { + if let Some(amount) = amount { + amount.withdraw(account); + } + + // Note: this operation is heavy. + let child_storage_root = child::root( + &alive_contract_info.child_trie_info(), + ); + + let tombstone = >::new( + &child_storage_root[..], + alive_contract_info.code_hash, + ); + let tombstone_info = ContractInfo::Tombstone(tombstone); + >::insert(account, &tombstone_info); + + child::kill_storage( + &alive_contract_info.child_trie_info(), + ); + + >::deposit_event(RawEvent::Evicted(account.clone(), true)); + Some(tombstone_info) + } + Verdict::Charge { amount } => { + let contract_info = ContractInfo::Alive(AliveContractInfo:: { + rent_allowance: alive_contract_info.rent_allowance - amount.peek(), + deduct_block: current_block_number, + ..alive_contract_info + }); + >::insert(account, &contract_info); -/// Enacts the given verdict and returns the updated `ContractInfo`. -/// -/// `alive_contract_info` should be from the same address as `account`. -fn enact_verdict( - account: &T::AccountId, - alive_contract_info: AliveContractInfo, - current_block_number: T::BlockNumber, - verdict: Verdict, -) -> Option> { - match verdict { - Verdict::Exempt => return Some(ContractInfo::Alive(alive_contract_info)), - Verdict::Kill => { - >::remove(account); - child::kill_storage( - &alive_contract_info.child_trie_info(), - ); - >::deposit_event(RawEvent::Evicted(account.clone(), false)); - None - } - Verdict::Evict { amount } => { - if let Some(amount) = amount { amount.withdraw(account); + Some(contract_info) } + } + } - // Note: this operation is heavy. - let child_storage_root = child::root( - &alive_contract_info.child_trie_info(), - ); - - let tombstone = >::new( - &child_storage_root[..], - alive_contract_info.code_hash, - ); - let tombstone_info = ContractInfo::Tombstone(tombstone); - >::insert(account, &tombstone_info); + /// Make account paying the rent for the current block number + /// + /// NOTE this function performs eviction eagerly. All changes are read and written directly to + /// storage. + pub fn collect(account: &T::AccountId) -> Option> { + let contract_info = >::get(account); + let alive_contract_info = match contract_info { + None | Some(ContractInfo::Tombstone(_)) => return contract_info, + Some(ContractInfo::Alive(contract)) => contract, + }; - child::kill_storage( - &alive_contract_info.child_trie_info(), - ); + let current_block_number = >::block_number(); + let verdict = Self::consider_case( + account, + current_block_number, + Zero::zero(), + &alive_contract_info, + ); + Self::enact_verdict(account, alive_contract_info, current_block_number, verdict) + } - >::deposit_event(RawEvent::Evicted(account.clone(), true)); - Some(tombstone_info) - } - Verdict::Charge { amount } => { - let contract_info = ContractInfo::Alive(AliveContractInfo:: { - rent_allowance: alive_contract_info.rent_allowance - amount.peek(), - deduct_block: current_block_number, - ..alive_contract_info - }); - >::insert(account, &contract_info); - - amount.withdraw(account); - Some(contract_info) + /// Process a report that a contract under the given address should be evicted. + /// + /// Enact the eviction right away if the contract should be evicted and return true. + /// Otherwise, **do nothing** and return false. + /// + /// The `handicap` parameter gives a way to check the rent to a moment in the past instead + /// of current block. E.g. if the contract is going to be evicted at the current block, + /// `handicap = 1` can defer the eviction for 1 block. This is useful to handicap certain snitchers + /// relative to others. + /// + /// NOTE this function performs eviction eagerly. All changes are read and written directly to + /// storage. + pub fn snitch_contract_should_be_evicted( + account: &T::AccountId, + handicap: T::BlockNumber, + ) -> bool { + let contract_info = >::get(account); + let alive_contract_info = match contract_info { + None | Some(ContractInfo::Tombstone(_)) => return false, + Some(ContractInfo::Alive(contract)) => contract, + }; + let current_block_number = >::block_number(); + let verdict = Self::consider_case( + account, + current_block_number, + handicap, + &alive_contract_info, + ); + + // Enact the verdict only if the contract gets removed. + match verdict { + Verdict::Kill | Verdict::Evict { .. } => { + Self::enact_verdict(account, alive_contract_info, current_block_number, verdict); + true + } + _ => false, } } -} -/// Make account paying the rent for the current block number -/// -/// NOTE this function performs eviction eagerly. All changes are read and written directly to -/// storage. -pub fn collect_rent(account: &T::AccountId) -> Option> { - let contract_info = >::get(account); - let alive_contract_info = match contract_info { - None | Some(ContractInfo::Tombstone(_)) => return contract_info, - Some(ContractInfo::Alive(contract)) => contract, - }; - - let current_block_number = >::block_number(); - let verdict = consider_case::( - account, - current_block_number, - Zero::zero(), - &alive_contract_info, - ); - enact_verdict(account, alive_contract_info, current_block_number, verdict) -} + /// Returns the projected time a given contract will be able to sustain paying its rent. The + /// returned projection is relevant for the current block, i.e. it is as if the contract was + /// accessed at the beginning of the current block. Returns `None` in case if the contract was + /// evicted before or as a result of the rent collection. + /// + /// The returned value is only an estimation. It doesn't take into account any top ups, changing the + /// rent allowance, or any problems coming from withdrawing the dues. + /// + /// NOTE that this is not a side-effect free function! It will actually collect rent and then + /// compute the projection. This function is only used for implementation of an RPC method through + /// `RuntimeApi` meaning that the changes will be discarded anyway. + pub fn compute_projection( + account: &T::AccountId, + ) -> RentProjectionResult { + let contract_info = >::get(account); + let alive_contract_info = match contract_info { + None | Some(ContractInfo::Tombstone(_)) => return Err(ContractAccessError::IsTombstone), + Some(ContractInfo::Alive(contract)) => contract, + }; + let current_block_number = >::block_number(); + let verdict = Self::consider_case( + account, + current_block_number, + Zero::zero(), + &alive_contract_info, + ); + let new_contract_info = + Self::enact_verdict(account, alive_contract_info, current_block_number, verdict); + + // Check what happened after enaction of the verdict. + let alive_contract_info = match new_contract_info { + None | Some(ContractInfo::Tombstone(_)) => return Err(ContractAccessError::IsTombstone), + Some(ContractInfo::Alive(contract)) => contract, + }; -/// Process a report that a contract under the given address should be evicted. -/// -/// Enact the eviction right away if the contract should be evicted and return true. -/// Otherwise, **do nothing** and return false. -/// -/// The `handicap` parameter gives a way to check the rent to a moment in the past instead -/// of current block. E.g. if the contract is going to be evicted at the current block, -/// `handicap = 1` can defer the eviction for 1 block. This is useful to handicap certain snitchers -/// relative to others. -/// -/// NOTE this function performs eviction eagerly. All changes are read and written directly to -/// storage. -pub fn snitch_contract_should_be_evicted( - account: &T::AccountId, - handicap: T::BlockNumber, -) -> bool { - let contract_info = >::get(account); - let alive_contract_info = match contract_info { - None | Some(ContractInfo::Tombstone(_)) => return false, - Some(ContractInfo::Alive(contract)) => contract, - }; - let current_block_number = >::block_number(); - let verdict = consider_case::( - account, - current_block_number, - handicap, - &alive_contract_info, - ); - - // Enact the verdict only if the contract gets removed. - match verdict { - Verdict::Kill | Verdict::Evict { .. } => { - enact_verdict(account, alive_contract_info, current_block_number, verdict); - true + // Compute how much would the fee per block be with the *updated* balance. + let total_balance = T::Currency::total_balance(account); + let free_balance = T::Currency::free_balance(account); + let fee_per_block = Self::compute_fee_per_block(&free_balance, &alive_contract_info); + if fee_per_block.is_zero() { + return Ok(RentProjection::NoEviction); } - _ => false, - } -} -/// Returns the projected time a given contract will be able to sustain paying its rent. The -/// returned projection is relevant for the current block, i.e. it is as if the contract was -/// accessed at the beginning of the current block. Returns `None` in case if the contract was -/// evicted before or as a result of the rent collection. -/// -/// The returned value is only an estimation. It doesn't take into account any top ups, changing the -/// rent allowance, or any problems coming from withdrawing the dues. -/// -/// NOTE that this is not a side-effect free function! It will actually collect rent and then -/// compute the projection. This function is only used for implementation of an RPC method through -/// `RuntimeApi` meaning that the changes will be discarded anyway. -pub fn compute_rent_projection( - account: &T::AccountId, -) -> RentProjectionResult { - let contract_info = >::get(account); - let alive_contract_info = match contract_info { - None | Some(ContractInfo::Tombstone(_)) => return Err(ContractAccessError::IsTombstone), - Some(ContractInfo::Alive(contract)) => contract, - }; - let current_block_number = >::block_number(); - let verdict = consider_case::( - account, - current_block_number, - Zero::zero(), - &alive_contract_info, - ); - let new_contract_info = - enact_verdict(account, alive_contract_info, current_block_number, verdict); - - // Check what happened after enaction of the verdict. - let alive_contract_info = match new_contract_info { - None | Some(ContractInfo::Tombstone(_)) => return Err(ContractAccessError::IsTombstone), - Some(ContractInfo::Alive(contract)) => contract, - }; - - // Compute how much would the fee per block be with the *updated* balance. - let total_balance = T::Currency::total_balance(account); - let free_balance = T::Currency::free_balance(account); - let fee_per_block = compute_fee_per_block::(&free_balance, &alive_contract_info); - if fee_per_block.is_zero() { - return Ok(RentProjection::NoEviction); + // Then compute how much the contract will sustain under these circumstances. + let rent_budget = Self::rent_budget(&total_balance, &free_balance, &alive_contract_info).expect( + "the contract exists and in the alive state; + the updated balance must be greater than subsistence deposit; + this function doesn't return `None`; + qed + ", + ); + let blocks_left = match rent_budget.checked_div(&fee_per_block) { + Some(blocks_left) => blocks_left, + None => { + // `fee_per_block` is not zero here, so `checked_div` can return `None` if + // there is an overflow. This cannot happen with integers though. Return + // `NoEviction` here just in case. + return Ok(RentProjection::NoEviction); + } + }; + + let blocks_left = blocks_left.saturated_into::().into(); + Ok(RentProjection::EvictionAt( + current_block_number + blocks_left, + )) } - // Then compute how much the contract will sustain under these circumstances. - let rent_budget = rent_budget::(&total_balance, &free_balance, &alive_contract_info).expect( - "the contract exists and in the alive state; - the updated balance must be greater than subsistence deposit; - this function doesn't return `None`; - qed - ", - ); - let blocks_left = match rent_budget.checked_div(&fee_per_block) { - Some(blocks_left) => blocks_left, - None => { - // `fee_per_block` is not zero here, so `checked_div` can return `None` if - // there is an overflow. This cannot happen with integers though. Return - // `NoEviction` here just in case. - return Ok(RentProjection::NoEviction); + /// Restores the destination account using the origin as prototype. + /// + /// The restoration will be performed iff: + /// - origin exists and is alive, + /// - the origin's storage is not written in the current block + /// - the restored account has tombstone + /// - the tombstone matches the hash of the origin storage root, and code hash. + /// + /// Upon succesful restoration, `origin` will be destroyed, all its funds are transferred to + /// the restored account. The restored account will inherit the last write block and its last + /// deduct block will be set to the current block. + pub fn restore_to( + origin: T::AccountId, + dest: T::AccountId, + code_hash: CodeHash, + rent_allowance: BalanceOf, + delta: Vec, + ) -> Result<(), DispatchError> { + let mut origin_contract = >::get(&origin) + .and_then(|c| c.get_alive()) + .ok_or(Error::::InvalidSourceContract)?; + + let child_trie_info = origin_contract.child_trie_info(); + + let current_block = >::block_number(); + + if origin_contract.last_write == Some(current_block) { + return Err(Error::::InvalidContractOrigin.into()); } - }; - let blocks_left = blocks_left.saturated_into::().into(); - Ok(RentProjection::EvictionAt( - current_block_number + blocks_left, - )) -} + let dest_tombstone = >::get(&dest) + .and_then(|c| c.get_tombstone()) + .ok_or(Error::::InvalidDestinationContract)?; -/// Restores the destination account using the origin as prototype. -/// -/// The restoration will be performed iff: -/// - origin exists and is alive, -/// - the origin's storage is not written in the current block -/// - the restored account has tombstone -/// - the tombstone matches the hash of the origin storage root, and code hash. -/// -/// Upon succesful restoration, `origin` will be destroyed, all its funds are transferred to -/// the restored account. The restored account will inherit the last write block and its last -/// deduct block will be set to the current block. -pub fn restore_to( - origin: T::AccountId, - dest: T::AccountId, - code_hash: CodeHash, - rent_allowance: BalanceOf, - delta: Vec, -) -> Result<(), &'static str> { - let mut origin_contract = >::get(&origin) - .and_then(|c| c.get_alive()) - .ok_or("Cannot restore from inexisting or tombstone contract")?; - - let child_trie_info = origin_contract.child_trie_info(); - - let current_block = >::block_number(); - - if origin_contract.last_write == Some(current_block) { - return Err("Origin TrieId written in the current block"); - } + let last_write = if !delta.is_empty() { + Some(current_block) + } else { + origin_contract.last_write + }; - let dest_tombstone = >::get(&dest) - .and_then(|c| c.get_tombstone()) - .ok_or("Cannot restore to inexisting or alive contract")?; - - let last_write = if !delta.is_empty() { - Some(current_block) - } else { - origin_contract.last_write - }; - - let key_values_taken = delta.iter() - .filter_map(|key| { - child::get_raw(&child_trie_info, &blake2_256(key)).map(|value| { - child::kill(&child_trie_info, &blake2_256(key)); - (key, value) + let key_values_taken = delta.iter() + .filter_map(|key| { + child::get_raw(&child_trie_info, &blake2_256(key)).map(|value| { + child::kill(&child_trie_info, &blake2_256(key)); + (key, value) + }) }) - }) - .collect::>(); - - let tombstone = >::new( - // This operation is cheap enough because last_write (delta not included) - // is not this block as it has been checked earlier. - &child::root(&child_trie_info)[..], - code_hash, - ); - - if tombstone != dest_tombstone { - for (key, value) in key_values_taken { - child::put_raw(&child_trie_info, &blake2_256(key), &value); + .collect::>(); + + let tombstone = >::new( + // This operation is cheap enough because last_write (delta not included) + // is not this block as it has been checked earlier. + &child::root(&child_trie_info)[..], + code_hash, + ); + + if tombstone != dest_tombstone { + for (key, value) in key_values_taken { + child::put_raw(&child_trie_info, &blake2_256(key), &value); + } + return Err(Error::::InvalidTombstone.into()); } - return Err("Tombstones don't match"); + origin_contract.storage_size -= key_values_taken.iter() + .map(|(_, value)| value.len() as u32) + .sum::(); + + >::remove(&origin); + >::insert(&dest, ContractInfo::Alive(AliveContractInfo:: { + trie_id: origin_contract.trie_id, + storage_size: origin_contract.storage_size, + empty_pair_count: origin_contract.empty_pair_count, + total_pair_count: origin_contract.total_pair_count, + code_hash, + rent_allowance, + deduct_block: current_block, + last_write, + })); + + let origin_free_balance = T::Currency::free_balance(&origin); + T::Currency::make_free_balance_be(&origin, >::zero()); + T::Currency::deposit_creating(&dest, origin_free_balance); + + Ok(()) } - - origin_contract.storage_size -= key_values_taken.iter() - .map(|(_, value)| value.len() as u32) - .sum::(); - - >::remove(&origin); - >::insert(&dest, ContractInfo::Alive(AliveContractInfo:: { - trie_id: origin_contract.trie_id, - storage_size: origin_contract.storage_size, - empty_pair_count: origin_contract.empty_pair_count, - total_pair_count: origin_contract.total_pair_count, - code_hash, - rent_allowance, - deduct_block: current_block, - last_write, - })); - - let origin_free_balance = T::Currency::free_balance(&origin); - T::Currency::make_free_balance_be(&origin, >::zero()); - T::Currency::deposit_creating(&dest, origin_free_balance); - - Ok(()) } diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index 9196e011f5bbb..dc98f8fac2f7e 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -302,6 +302,9 @@ pub struct HostFnWeights { /// Weight per output byte received through `seal_instantiate`. pub instantiate_per_output_byte: Weight, + /// Weight per salt byte supplied to `seal_instantiate`. + pub instantiate_per_salt_byte: Weight, + /// Weight of calling `seal_hash_sha_256`. pub hash_sha2_256: Weight, @@ -571,8 +574,9 @@ impl Default for HostFnWeights { call_per_input_byte: cost_byte_batched_args!(seal_call_per_transfer_input_output_kb, 0, 1, 0), call_per_output_byte: cost_byte_batched_args!(seal_call_per_transfer_input_output_kb, 0, 0, 1), instantiate: cost_batched!(seal_instantiate), - instantiate_per_input_byte: cost_byte_batched_args!(seal_instantiate_per_input_output_kb, 1, 0), - instantiate_per_output_byte: cost_byte_batched_args!(seal_instantiate_per_input_output_kb, 0, 1), + instantiate_per_input_byte: cost_byte_batched_args!(seal_instantiate_per_input_output_salt_kb, 1, 0, 0), + instantiate_per_output_byte: cost_byte_batched_args!(seal_instantiate_per_input_output_salt_kb, 0, 1, 0), + instantiate_per_salt_byte: cost_byte_batched_args!(seal_instantiate_per_input_output_salt_kb, 0, 0, 1), hash_sha2_256: cost_batched!(seal_hash_sha2_256), hash_sha2_256_per_byte: cost_byte_batched!(seal_hash_sha2_256_per_kb), hash_keccak_256: cost_batched!(seal_hash_keccak_256), diff --git a/frame/contracts/src/storage.rs b/frame/contracts/src/storage.rs index 3740952778fd3..acd788796150d 100644 --- a/frame/contracts/src/storage.rs +++ b/frame/contracts/src/storage.rs @@ -19,10 +19,13 @@ use crate::{ exec::{AccountIdOf, StorageKey}, AliveContractInfo, BalanceOf, CodeHash, ContractInfo, ContractInfoOf, Trait, TrieId, + AccountCounter, }; use sp_std::prelude::*; +use sp_std::marker::PhantomData; use sp_io::hashing::blake2_256; use sp_runtime::traits::Bounded; +use sp_core::crypto::UncheckedFrom; use frame_support::{storage::child, StorageMap}; /// An error that means that the account requested either doesn't exist or represents a tombstone @@ -30,167 +33,196 @@ use frame_support::{storage::child, StorageMap}; #[cfg_attr(test, derive(PartialEq, Eq, Debug))] pub struct ContractAbsentError; -/// Reads a storage kv pair of a contract. -/// -/// The read is performed from the `trie_id` only. The `address` is not necessary. If the contract -/// doesn't store under the given `key` `None` is returned. -pub fn read_contract_storage(trie_id: &TrieId, key: &StorageKey) -> Option> { - child::get_raw(&crate::child_trie_info(&trie_id), &blake2_256(key)) -} - -/// Update a storage entry into a contract's kv storage. -/// -/// If the `opt_new_value` is `None` then the kv pair is removed. -/// -/// This function also updates the bookkeeping info such as: number of total non-empty pairs a -/// contract owns, the last block the storage was written to, etc. That's why, in contrast to -/// `read_contract_storage`, this function also requires the `account` ID. -/// -/// If the contract specified by the id `account` doesn't exist `Err` is returned.` -pub fn write_contract_storage( - account: &AccountIdOf, - trie_id: &TrieId, - key: &StorageKey, - opt_new_value: Option>, -) -> Result<(), ContractAbsentError> { - let mut new_info = match >::get(account) { - Some(ContractInfo::Alive(alive)) => alive, - None | Some(ContractInfo::Tombstone(_)) => return Err(ContractAbsentError), - }; - - let hashed_key = blake2_256(key); - let child_trie_info = &crate::child_trie_info(&trie_id); - - // In order to correctly update the book keeping we need to fetch the previous - // value of the key-value pair. - // - // It might be a bit more clean if we had an API that supported getting the size - // of the value without going through the loading of it. But at the moment of - // writing, there is no such API. - // - // That's not a show stopper in any case, since the performance cost is - // dominated by the trie traversal anyway. - let opt_prev_value = child::get_raw(&child_trie_info, &hashed_key); - - // Update the total number of KV pairs and the number of empty pairs. - match (&opt_prev_value, &opt_new_value) { - (Some(prev_value), None) => { - new_info.total_pair_count -= 1; - if prev_value.is_empty() { - new_info.empty_pair_count -= 1; - } - }, - (None, Some(new_value)) => { - new_info.total_pair_count += 1; - if new_value.is_empty() { - new_info.empty_pair_count += 1; - } - }, - (Some(prev_value), Some(new_value)) => { - if prev_value.is_empty() { - new_info.empty_pair_count -= 1; - } - if new_value.is_empty() { - new_info.empty_pair_count += 1; +pub struct Storage(PhantomData); + +impl Storage +where + T: Trait, + T::AccountId: UncheckedFrom + AsRef<[u8]> +{ + /// Reads a storage kv pair of a contract. + /// + /// The read is performed from the `trie_id` only. The `address` is not necessary. If the contract + /// doesn't store under the given `key` `None` is returned. + pub fn read(trie_id: &TrieId, key: &StorageKey) -> Option> { + child::get_raw(&crate::child_trie_info(&trie_id), &blake2_256(key)) + } + + /// Update a storage entry into a contract's kv storage. + /// + /// If the `opt_new_value` is `None` then the kv pair is removed. + /// + /// This function also updates the bookkeeping info such as: number of total non-empty pairs a + /// contract owns, the last block the storage was written to, etc. That's why, in contrast to + /// `read`, this function also requires the `account` ID. + /// + /// If the contract specified by the id `account` doesn't exist `Err` is returned.` + pub fn write( + account: &AccountIdOf, + trie_id: &TrieId, + key: &StorageKey, + opt_new_value: Option>, + ) -> Result<(), ContractAbsentError> { + let mut new_info = match >::get(account) { + Some(ContractInfo::Alive(alive)) => alive, + None | Some(ContractInfo::Tombstone(_)) => return Err(ContractAbsentError), + }; + + let hashed_key = blake2_256(key); + let child_trie_info = &crate::child_trie_info(&trie_id); + + // In order to correctly update the book keeping we need to fetch the previous + // value of the key-value pair. + // + // It might be a bit more clean if we had an API that supported getting the size + // of the value without going through the loading of it. But at the moment of + // writing, there is no such API. + // + // That's not a show stopper in any case, since the performance cost is + // dominated by the trie traversal anyway. + let opt_prev_value = child::get_raw(&child_trie_info, &hashed_key); + + // Update the total number of KV pairs and the number of empty pairs. + match (&opt_prev_value, &opt_new_value) { + (Some(prev_value), None) => { + new_info.total_pair_count -= 1; + if prev_value.is_empty() { + new_info.empty_pair_count -= 1; + } + }, + (None, Some(new_value)) => { + new_info.total_pair_count += 1; + if new_value.is_empty() { + new_info.empty_pair_count += 1; + } + }, + (Some(prev_value), Some(new_value)) => { + if prev_value.is_empty() { + new_info.empty_pair_count -= 1; + } + if new_value.is_empty() { + new_info.empty_pair_count += 1; + } } + (None, None) => {} + } + + // Update the total storage size. + let prev_value_len = opt_prev_value + .as_ref() + .map(|old_value| old_value.len() as u32) + .unwrap_or(0); + let new_value_len = opt_new_value + .as_ref() + .map(|new_value| new_value.len() as u32) + .unwrap_or(0); + new_info.storage_size = new_info + .storage_size + .saturating_add(new_value_len) + .saturating_sub(prev_value_len); + + new_info.last_write = Some(>::block_number()); + >::insert(&account, ContractInfo::Alive(new_info)); + + // Finally, perform the change on the storage. + match opt_new_value { + Some(new_value) => child::put_raw(&child_trie_info, &hashed_key, &new_value[..]), + None => child::kill(&child_trie_info, &hashed_key), } - (None, None) => {} + + Ok(()) } - // Update the total storage size. - let prev_value_len = opt_prev_value - .as_ref() - .map(|old_value| old_value.len() as u32) - .unwrap_or(0); - let new_value_len = opt_new_value - .as_ref() - .map(|new_value| new_value.len() as u32) - .unwrap_or(0); - new_info.storage_size = new_info - .storage_size - .saturating_add(new_value_len) - .saturating_sub(prev_value_len); - - new_info.last_write = Some(>::block_number()); - >::insert(&account, ContractInfo::Alive(new_info)); - - // Finally, perform the change on the storage. - match opt_new_value { - Some(new_value) => child::put_raw(&child_trie_info, &hashed_key, &new_value[..]), - None => child::kill(&child_trie_info, &hashed_key), + /// Returns the rent allowance set for the contract give by the account id. + pub fn rent_allowance( + account: &AccountIdOf, + ) -> Result, ContractAbsentError> + { + >::get(account) + .and_then(|i| i.as_alive().map(|i| i.rent_allowance)) + .ok_or(ContractAbsentError) } - Ok(()) -} - -/// Returns the rent allowance set for the contract give by the account id. -pub fn rent_allowance( - account: &AccountIdOf, -) -> Result, ContractAbsentError> { - >::get(account) - .and_then(|i| i.as_alive().map(|i| i.rent_allowance)) - .ok_or(ContractAbsentError) -} - -/// Set the rent allowance for the contract given by the account id. -/// -/// Returns `Err` if the contract doesn't exist or is a tombstone. -pub fn set_rent_allowance( - account: &AccountIdOf, - rent_allowance: BalanceOf, -) -> Result<(), ContractAbsentError> { - >::mutate(account, |maybe_contract_info| match maybe_contract_info { - Some(ContractInfo::Alive(ref mut alive_info)) => { - alive_info.rent_allowance = rent_allowance; - Ok(()) - } - _ => Err(ContractAbsentError), - }) -} - -/// Returns the code hash of the contract specified by `account` ID. -#[cfg(test)] -pub fn code_hash(account: &AccountIdOf) -> Result, ContractAbsentError> { - >::get(account) - .and_then(|i| i.as_alive().map(|i| i.code_hash)) - .ok_or(ContractAbsentError) -} - -/// Creates a new contract descriptor in the storage with the given code hash at the given address. -/// -/// Returns `Err` if there is already a contract (or a tombstone) exists at the given address. -pub fn place_contract( - account: &AccountIdOf, - trie_id: TrieId, - ch: CodeHash, -) -> Result<(), &'static str> { - >::mutate(account, |maybe_contract_info| { - if maybe_contract_info.is_some() { - return Err("Alive contract or tombstone already exists"); - } + /// Set the rent allowance for the contract given by the account id. + /// + /// Returns `Err` if the contract doesn't exist or is a tombstone. + pub fn set_rent_allowance( + account: &AccountIdOf, + rent_allowance: BalanceOf, + ) -> Result<(), ContractAbsentError> { + >::mutate(account, |maybe_contract_info| match maybe_contract_info { + Some(ContractInfo::Alive(ref mut alive_info)) => { + alive_info.rent_allowance = rent_allowance; + Ok(()) + } + _ => Err(ContractAbsentError), + }) + } - *maybe_contract_info = Some( - AliveContractInfo:: { - code_hash: ch, - storage_size: 0, - trie_id, - deduct_block: >::block_number(), - rent_allowance: >::max_value(), - empty_pair_count: 0, - total_pair_count: 0, - last_write: None, + /// Creates a new contract descriptor in the storage with the given code hash at the given address. + /// + /// Returns `Err` if there is already a contract (or a tombstone) exists at the given address. + pub fn place_contract( + account: &AccountIdOf, + trie_id: TrieId, + ch: CodeHash, + ) -> Result<(), &'static str> { + >::mutate(account, |maybe_contract_info| { + if maybe_contract_info.is_some() { + return Err("Alive contract or tombstone already exists"); } - .into(), - ); - Ok(()) - }) -} - -/// Removes the contract and all the storage associated with it. -/// -/// This function doesn't affect the account. -pub fn destroy_contract(address: &AccountIdOf, trie_id: &TrieId) { - >::remove(address); - child::kill_storage(&crate::child_trie_info(&trie_id)); -} + *maybe_contract_info = Some( + AliveContractInfo:: { + code_hash: ch, + storage_size: 0, + trie_id, + deduct_block: >::block_number(), + rent_allowance: >::max_value(), + empty_pair_count: 0, + total_pair_count: 0, + last_write: None, + } + .into(), + ); + + Ok(()) + }) + } + + /// Removes the contract and all the storage associated with it. + /// + /// This function doesn't affect the account. + pub fn destroy_contract(address: &AccountIdOf, trie_id: &TrieId) { + >::remove(address); + child::kill_storage(&crate::child_trie_info(&trie_id)); + } + + /// This generator uses inner counter for account id and applies the hash over `AccountId + + /// accountid_counter`. + pub fn generate_trie_id(account_id: &AccountIdOf) -> TrieId { + use frame_support::StorageValue; + use sp_runtime::traits::Hash; + // Note that skipping a value due to error is not an issue here. + // We only need uniqueness, not sequence. + let new_seed = AccountCounter::mutate(|v| { + *v = v.wrapping_add(1); + *v + }); + + let buf: Vec<_> = account_id.as_ref().iter() + .chain(&new_seed.to_le_bytes()) + .cloned() + .collect(); + T::Hashing::hash(&buf).as_ref().into() + } + + /// Returns the code hash of the contract specified by `account` ID. + #[cfg(test)] + pub fn code_hash(account: &AccountIdOf) -> Result, ContractAbsentError> + { + >::get(account) + .and_then(|i| i.as_alive().map(|i| i.code_hash)) + .ok_or(ContractAbsentError) + } +} \ No newline at end of file diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index c2d9ed6642559..6a0476096c8c0 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -15,26 +15,26 @@ // along with Substrate. If not, see . use crate::{ - BalanceOf, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig, Module, - RawAliveContractInfo, RawEvent, Trait, TrieId, Schedule, TrieIdGenerator, gas::Gas, - Error, Config, RuntimeReturnCode, + BalanceOf, ContractInfo, ContractInfoOf, GenesisConfig, Module, + RawAliveContractInfo, RawEvent, Trait, Schedule, gas::Gas, + Error, Config, RuntimeReturnCode, storage::Storage, + exec::AccountIdOf, }; use assert_matches::assert_matches; -use hex_literal::*; use codec::Encode; use sp_runtime::{ Perbill, traits::{BlakeTwo256, Hash, IdentityLookup, Convert}, testing::{Header, H256}, + AccountId32, }; use frame_support::{ assert_ok, assert_err_ignore_postinfo, impl_outer_dispatch, impl_outer_event, - impl_outer_origin, parameter_types, StorageMap, StorageValue, - traits::{Currency, Get, ReservableCurrency}, + impl_outer_origin, parameter_types, StorageMap, + traits::{Currency, ReservableCurrency}, weights::{Weight, PostDispatchInfo}, dispatch::DispatchErrorWithPostInfo, }; -use std::cell::RefCell; use frame_system::{self as system, EventRecord, Phase}; mod contracts { @@ -67,28 +67,30 @@ impl_outer_dispatch! { #[macro_use] pub mod test_utils { use super::{Test, Balances}; - use crate::{ContractInfoOf, TrieIdGenerator, CodeHash}; - use crate::storage::{write_contract_storage, read_contract_storage}; - use crate::exec::StorageKey; + use crate::{ + ContractInfoOf, CodeHash, + storage::Storage, + exec::{StorageKey, AccountIdOf}, + }; use frame_support::{StorageMap, traits::Currency}; - pub fn set_storage(addr: &u64, key: &StorageKey, value: Option>) { + pub fn set_storage(addr: &AccountIdOf, key: &StorageKey, value: Option>) { let contract_info = >::get(&addr).unwrap().get_alive().unwrap(); - write_contract_storage::(&1, &contract_info.trie_id, key, value).unwrap(); + Storage::::write(addr, &contract_info.trie_id, key, value).unwrap(); } - pub fn get_storage(addr: &u64, key: &StorageKey) -> Option> { + pub fn get_storage(addr: &AccountIdOf, key: &StorageKey) -> Option> { let contract_info = >::get(&addr).unwrap().get_alive().unwrap(); - read_contract_storage(&contract_info.trie_id, key) + Storage::::read(&contract_info.trie_id, key) } - pub fn place_contract(address: &u64, code_hash: CodeHash) { - let trie_id = ::TrieIdGenerator::trie_id(address); - crate::storage::place_contract::(&address, trie_id, code_hash).unwrap() + pub fn place_contract(address: &AccountIdOf, code_hash: CodeHash) { + let trie_id = Storage::::generate_trie_id(address); + Storage::::place_contract(&address, trie_id, code_hash).unwrap() } - pub fn set_balance(who: &u64, amount: u64) { + pub fn set_balance(who: &AccountIdOf, amount: u64) { let imbalance = Balances::deposit_creating(who, amount); drop(imbalance); } - pub fn get_balance(who: &u64) -> u64 { + pub fn get_balance(who: &AccountIdOf) -> u64 { Balances::free_balance(who) } macro_rules! assert_return_code { @@ -99,15 +101,6 @@ pub mod test_utils { } } -thread_local! { - static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); -} - -pub struct ExistentialDeposit; -impl Get for ExistentialDeposit { - fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) } -} - #[derive(Clone, Eq, PartialEq, Debug)] pub struct Test; parameter_types! { @@ -115,6 +108,7 @@ parameter_types! { pub const MaximumBlockWeight: Weight = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub static ExistentialDeposit: u64 = 0; } impl frame_system::Trait for Test { type BaseCallFilter = (); @@ -124,7 +118,7 @@ impl frame_system::Trait for Test { type Hash = H256; type Call = Call; type Hashing = BlakeTwo256; - type AccountId = u64; + type AccountId = AccountId32; type Lookup = IdentityLookup; type Header = Header; type Event = MetaEvent; @@ -186,9 +180,7 @@ impl Trait for Test { type Time = Timestamp; type Randomness = Randomness; type Currency = Balances; - type DetermineContractAddress = DummyContractAddressFor; type Event = MetaEvent; - type TrieIdGenerator = DummyTrieIdGenerator; type RentPayment = (); type SignedClaimHandicap = SignedClaimHandicap; type TombstoneDeposit = TombstoneDeposit; @@ -208,32 +200,10 @@ type Contracts = Module; type System = frame_system::Module; type Randomness = pallet_randomness_collective_flip::Module; -pub struct DummyContractAddressFor; -impl ContractAddressFor for DummyContractAddressFor { - fn contract_address_for(_code_hash: &H256, _data: &[u8], origin: &u64) -> u64 { - *origin + 1 - } -} - -pub struct DummyTrieIdGenerator; -impl TrieIdGenerator for DummyTrieIdGenerator { - fn trie_id(account_id: &u64) -> TrieId { - let new_seed = super::AccountCounter::mutate(|v| { - *v = v.wrapping_add(1); - *v - }); - - let mut res = vec![]; - res.extend_from_slice(&new_seed.to_le_bytes()); - res.extend_from_slice(&account_id.to_le_bytes()); - res - } -} - -const ALICE: u64 = 1; -const BOB: u64 = 2; -const CHARLIE: u64 = 3; -const DJANGO: u64 = 4; +pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); +pub const BOB: AccountId32 = AccountId32::new([2u8; 32]); +pub const CHARLIE: AccountId32 = AccountId32::new([3u8; 32]); +pub const DJANGO: AccountId32 = AccountId32::new([4u8; 32]); const GAS_LIMIT: Gas = 10_000_000_000; @@ -318,8 +288,8 @@ fn account_removal_does_not_remove_storage() { use self::test_utils::{set_storage, get_storage}; ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - let trie_id1 = ::TrieIdGenerator::trie_id(&1); - let trie_id2 = ::TrieIdGenerator::trie_id(&2); + let trie_id1 = Storage::::generate_trie_id(&ALICE); + let trie_id2 = Storage::::generate_trie_id(&BOB); let key1 = &[1; 32]; let key2 = &[2; 32]; @@ -408,17 +378,21 @@ fn instantiate_and_call_and_deposit_event() { GAS_LIMIT, code_hash.into(), vec![], + vec![], ); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); pretty_assertions::assert_eq!(System::events(), vec![ EventRecord { phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), + event: MetaEvent::system(frame_system::RawEvent::NewAccount(ALICE.clone())), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + event: MetaEvent::balances( + pallet_balances::RawEvent::Endowed(ALICE, 1_000_000) + ), topics: vec![], }, EventRecord { @@ -428,37 +402,39 @@ fn instantiate_and_call_and_deposit_event() { }, EventRecord { phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)), + event: MetaEvent::system(frame_system::RawEvent::NewAccount(addr.clone())), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: MetaEvent::balances( - pallet_balances::RawEvent::Endowed(BOB, subsistence) + pallet_balances::RawEvent::Endowed(addr.clone(), subsistence) ), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: MetaEvent::balances( - pallet_balances::RawEvent::Transfer(ALICE, BOB, subsistence) + pallet_balances::RawEvent::Transfer(ALICE, addr.clone(), subsistence) ), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::ContractExecution(BOB, vec![1, 2, 3, 4])), + event: MetaEvent::contracts( + RawEvent::ContractExecution(addr.clone(), vec![1, 2, 3, 4]) + ), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)), + event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, addr.clone())), topics: vec![], } ]); assert_ok!(creation); - assert!(ContractInfoOf::::contains_key(BOB)); + assert!(ContractInfoOf::::contains_key(&addr)); }); } @@ -479,16 +455,21 @@ fn deposit_event_max_value_limit() { GAS_LIMIT, code_hash.into(), vec![], + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + let bob_contract = ContractInfoOf::::get(addr.clone()) + .unwrap() + .get_alive() + .unwrap(); assert_eq!(bob_contract.rent_allowance, >::max_value()); // Call contract with allowed storage value. assert_ok!(Contracts::call( Origin::signed(ALICE), - BOB, + addr.clone(), 0, GAS_LIMIT * 2, // we are copying a huge buffer, ::MaxValueSize::get().encode(), @@ -498,7 +479,7 @@ fn deposit_event_max_value_limit() { assert_err_ignore_postinfo!( Contracts::call( Origin::signed(ALICE), - BOB, + addr, 0, GAS_LIMIT, (::MaxValueSize::get() + 1).encode(), @@ -526,14 +507,16 @@ fn run_out_of_gas() { GAS_LIMIT, code_hash.into(), vec![], + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Call the contract with a fixed gas limit. It must run out of gas because it just // loops forever. assert_err_ignore_postinfo!( Contracts::call( Origin::signed(ALICE), - BOB, // newly created account + addr, // newly created account 0, 67_500_000, vec![], @@ -545,21 +528,19 @@ fn run_out_of_gas() { /// Input data for each call in set_rent code mod call { - pub fn set_storage_4_byte() -> Vec { vec![] } - pub fn remove_storage_4_byte() -> Vec { vec![0] } - pub fn transfer() -> Vec { vec![0, 0] } - pub fn null() -> Vec { vec![0, 0, 0] } + use super::{AccountIdOf, Test}; + pub fn set_storage_4_byte() -> Vec { 0u32.to_le_bytes().to_vec() } + pub fn remove_storage_4_byte() -> Vec { 1u32.to_le_bytes().to_vec() } + pub fn transfer(to: &AccountIdOf) -> Vec { + 2u32.to_le_bytes().iter().chain(AsRef::<[u8]>::as_ref(to)).cloned().collect() + } + pub fn null() -> Vec { 3u32.to_le_bytes().to_vec() } } /// Test correspondence of set_rent code and its hash. /// Also test that encoded extrinsic in code correspond to the correct transfer #[test] fn test_set_rent_code_and_hash() { - // This test can fail due to the encoding changes. In case it becomes too annoying - // let's rewrite so as we use this module controlled call or we serialize it in runtime. - let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50))); - assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); - let (wasm, code_hash) = compile_module::("set_rent").unwrap(); ExtBuilder::default() @@ -574,12 +555,14 @@ fn test_set_rent_code_and_hash() { assert_eq!(System::events(), vec![ EventRecord { phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), + event: MetaEvent::system(frame_system::RawEvent::NewAccount(ALICE)), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed( + ALICE, 1_000_000 + )), topics: vec![], }, EventRecord { @@ -608,9 +591,11 @@ fn storage_size() { 30_000, GAS_LIMIT, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance + ::Balance::from(1_000u32).encode(), // rent allowance + vec![], )); - let bob_contract = ContractInfoOf::::get(BOB) + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); + let bob_contract = ContractInfoOf::::get(&addr) .unwrap() .get_alive() .unwrap(); @@ -629,12 +614,12 @@ fn storage_size() { assert_ok!(Contracts::call( Origin::signed(ALICE), - BOB, + addr.clone(), 0, GAS_LIMIT, call::set_storage_4_byte() )); - let bob_contract = ContractInfoOf::::get(BOB) + let bob_contract = ContractInfoOf::::get(&addr) .unwrap() .get_alive() .unwrap(); @@ -653,12 +638,12 @@ fn storage_size() { assert_ok!(Contracts::call( Origin::signed(ALICE), - BOB, + addr.clone(), 0, GAS_LIMIT, call::remove_storage_4_byte() )); - let bob_contract = ContractInfoOf::::get(BOB) + let bob_contract = ContractInfoOf::::get(&addr) .unwrap() .get_alive() .unwrap(); @@ -692,8 +677,10 @@ fn empty_kv_pairs() { GAS_LIMIT, code_hash.into(), vec![], + vec![], )); - let bob_contract = ContractInfoOf::::get(BOB) + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); + let bob_contract = ContractInfoOf::::get(&addr) .unwrap() .get_alive() .unwrap(); @@ -738,90 +725,98 @@ fn deduct_blocks() { Origin::signed(ALICE), 30_000, GAS_LIMIT, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance + ::Balance::from(1_000u32).encode(), // rent allowance + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + let bob_contract = ContractInfoOf::::get(&addr).unwrap().get_alive().unwrap(); assert_eq!(bob_contract.rent_allowance, 1_000); // Advance 4 blocks initialize_block(5); // Trigger rent through call - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); + assert_ok!( + Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, call::null()) + ); // Check result let rent = (8 + 4 - 3) // storage size = size_offset + deploy_set_storage - deposit_offset * 4 // rent byte price * 4; // blocks to rent - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + let bob_contract = ContractInfoOf::::get(&addr).unwrap().get_alive().unwrap(); assert_eq!(bob_contract.rent_allowance, 1_000 - rent); assert_eq!(bob_contract.deduct_block, 5); - assert_eq!(Balances::free_balance(BOB), 30_000 - rent); + assert_eq!(Balances::free_balance(&addr), 30_000 - rent); // Advance 7 blocks more initialize_block(12); // Trigger rent through call - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); + assert_ok!( + Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, call::null()) + ); // Check result let rent_2 = (8 + 4 - 2) // storage size = size_offset + deploy_set_storage - deposit_offset * 4 // rent byte price * 7; // blocks to rent - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + let bob_contract = ContractInfoOf::::get(&addr).unwrap().get_alive().unwrap(); assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); assert_eq!(bob_contract.deduct_block, 12); - assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); + assert_eq!(Balances::free_balance(&addr), 30_000 - rent - rent_2); // Second call on same block should have no effect on rent - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); + assert_ok!( + Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, call::null()) + ); - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + let bob_contract = ContractInfoOf::::get(&addr).unwrap().get_alive().unwrap(); assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); assert_eq!(bob_contract.deduct_block, 12); - assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); + assert_eq!(Balances::free_balance(&addr), 30_000 - rent - rent_2); }); } #[test] fn call_contract_removals() { - removals(|| { + removals(|addr| { // Call on already-removed account might fail, and this is fine. - let _ = Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()); + let _ = Contracts::call(Origin::signed(ALICE), addr, 0, GAS_LIMIT, call::null()); true }); } #[test] fn inherent_claim_surcharge_contract_removals() { - removals(|| Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok()); + removals(|addr| Contracts::claim_surcharge(Origin::none(), addr, Some(ALICE)).is_ok()); } #[test] fn signed_claim_surcharge_contract_removals() { - removals(|| Contracts::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok()); + removals(|addr| Contracts::claim_surcharge(Origin::signed(ALICE), addr, None).is_ok()); } #[test] fn claim_surcharge_malus() { // Test surcharge malus for inherent - claim_surcharge(4, || Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok(), true); - claim_surcharge(3, || Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok(), true); - claim_surcharge(2, || Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok(), true); - claim_surcharge(1, || Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok(), false); + claim_surcharge(4, |addr| Contracts::claim_surcharge(Origin::none(), addr, Some(ALICE)).is_ok(), true); + claim_surcharge(3, |addr| Contracts::claim_surcharge(Origin::none(), addr, Some(ALICE)).is_ok(), true); + claim_surcharge(2, |addr| Contracts::claim_surcharge(Origin::none(), addr, Some(ALICE)).is_ok(), true); + claim_surcharge(1, |addr| Contracts::claim_surcharge(Origin::none(), addr, Some(ALICE)).is_ok(), false); // Test surcharge malus for signed - claim_surcharge(4, || Contracts::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), true); - claim_surcharge(3, || Contracts::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), false); - claim_surcharge(2, || Contracts::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), false); - claim_surcharge(1, || Contracts::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), false); + claim_surcharge(4, |addr| Contracts::claim_surcharge(Origin::signed(ALICE), addr, None).is_ok(), true); + claim_surcharge(3, |addr| Contracts::claim_surcharge(Origin::signed(ALICE), addr, None).is_ok(), false); + claim_surcharge(2, |addr| Contracts::claim_surcharge(Origin::signed(ALICE), addr, None).is_ok(), false); + claim_surcharge(1, |addr| Contracts::claim_surcharge(Origin::signed(ALICE), addr, None).is_ok(), false); } /// Claim surcharge with the given trigger_call at the given blocks. /// If `removes` is true then assert that the contract is a tombstone. -fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool) { +fn claim_surcharge(blocks: u64, trigger_call: impl Fn(AccountIdOf) -> bool, removes: bool) { let (wasm, code_hash) = compile_module::("set_rent").unwrap(); ExtBuilder::default() @@ -835,19 +830,21 @@ fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool) Origin::signed(ALICE), 100, GAS_LIMIT, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance + ::Balance::from(1_000u32).encode(), // rent allowance + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Advance blocks initialize_block(blocks); // Trigger rent through call - assert!(trigger_call()); + assert!(trigger_call(addr.clone())); if removes { - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + assert!(ContractInfoOf::::get(&addr).unwrap().get_tombstone().is_some()); } else { - assert!(ContractInfoOf::::get(BOB).unwrap().get_alive().is_some()); + assert!(ContractInfoOf::::get(&addr).unwrap().get_alive().is_some()); } }); } @@ -857,7 +854,7 @@ fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool) /// * if allowance is exceeded /// * if balance is reached and balance < subsistence threshold /// * this case cannot be triggered by a contract: we check whether a tombstone is left -fn removals(trigger_call: impl Fn() -> bool) { +fn removals(trigger_call: impl Fn(AccountIdOf) -> bool) { let (wasm, code_hash) = compile_module::("set_rent").unwrap(); // Balance reached and superior to subsistence threshold @@ -872,31 +869,33 @@ fn removals(trigger_call: impl Fn() -> bool) { Origin::signed(ALICE), 100, GAS_LIMIT, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance + ::Balance::from(1_000u32).encode(), // rent allowance + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); let subsistence_threshold = 50 /*existential_deposit*/ + 16 /*tombstone_deposit*/; // Trigger rent must have no effect - assert!(trigger_call()); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); - assert_eq!(Balances::free_balance(BOB), 100); + assert!(trigger_call(addr.clone())); + assert_eq!(ContractInfoOf::::get(&addr).unwrap().get_alive().unwrap().rent_allowance, 1_000); + assert_eq!(Balances::free_balance(&addr), 100); // Advance blocks initialize_block(10); // Trigger rent through call - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(Balances::free_balance(BOB), subsistence_threshold); + assert!(trigger_call(addr.clone())); + assert!(ContractInfoOf::::get(&addr).unwrap().get_tombstone().is_some()); + assert_eq!(Balances::free_balance(&addr), subsistence_threshold); // Advance blocks initialize_block(20); // Trigger rent must have no effect - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(Balances::free_balance(BOB), subsistence_threshold); + assert!(trigger_call(addr.clone())); + assert!(ContractInfoOf::::get(&addr).unwrap().get_tombstone().is_some()); + assert_eq!(Balances::free_balance(&addr), subsistence_threshold); }); // Allowance exceeded @@ -912,43 +911,45 @@ fn removals(trigger_call: impl Fn() -> bool) { 1_000, GAS_LIMIT, code_hash.into(), - ::Balance::from(100u32).encode() // rent allowance + ::Balance::from(100u32).encode(), // rent allowance + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Trigger rent must have no effect - assert!(trigger_call()); + assert!(trigger_call(addr.clone())); assert_eq!( - ContractInfoOf::::get(BOB) + ContractInfoOf::::get(&addr) .unwrap() .get_alive() .unwrap() .rent_allowance, 100 ); - assert_eq!(Balances::free_balance(BOB), 1_000); + assert_eq!(Balances::free_balance(&addr), 1_000); // Advance blocks initialize_block(10); // Trigger rent through call - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB) + assert!(trigger_call(addr.clone())); + assert!(ContractInfoOf::::get(&addr) .unwrap() .get_tombstone() .is_some()); // Balance should be initial balance - initial rent_allowance - assert_eq!(Balances::free_balance(BOB), 900); + assert_eq!(Balances::free_balance(&addr), 900); // Advance blocks initialize_block(20); // Trigger rent must have no effect - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB) + assert!(trigger_call(addr.clone())); + assert!(ContractInfoOf::::get(&addr) .unwrap() .get_tombstone() .is_some()); - assert_eq!(Balances::free_balance(BOB), 900); + assert_eq!(Balances::free_balance(&addr), 900); }); // Balance reached and inferior to subsistence threshold @@ -966,13 +967,15 @@ fn removals(trigger_call: impl Fn() -> bool) { 50 + subsistence_threshold, GAS_LIMIT, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance + ::Balance::from(1_000u32).encode(), // rent allowance + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Trigger rent must have no effect - assert!(trigger_call()); + assert!(trigger_call(addr.clone())); assert_eq!( - ContractInfoOf::::get(BOB) + ContractInfoOf::::get(&addr) .unwrap() .get_alive() .unwrap() @@ -980,43 +983,43 @@ fn removals(trigger_call: impl Fn() -> bool) { 1_000 ); assert_eq!( - Balances::free_balance(BOB), + Balances::free_balance(&addr), 50 + subsistence_threshold, ); // Transfer funds assert_ok!(Contracts::call( Origin::signed(ALICE), - BOB, + addr.clone(), 0, GAS_LIMIT, - call::transfer() + call::transfer(&BOB), )); assert_eq!( - ContractInfoOf::::get(BOB) + ContractInfoOf::::get(&addr) .unwrap() .get_alive() .unwrap() .rent_allowance, 1_000 ); - assert_eq!(Balances::free_balance(BOB), subsistence_threshold); + assert_eq!(Balances::free_balance(&addr), subsistence_threshold); // Advance blocks initialize_block(10); // Trigger rent through call - assert!(trigger_call()); - assert_matches!(ContractInfoOf::::get(BOB), Some(ContractInfo::Tombstone(_))); - assert_eq!(Balances::free_balance(BOB), subsistence_threshold); + assert!(trigger_call(addr.clone())); + assert_matches!(ContractInfoOf::::get(&addr), Some(ContractInfo::Tombstone(_))); + assert_eq!(Balances::free_balance(&addr), subsistence_threshold); // Advance blocks initialize_block(20); // Trigger rent must have no effect - assert!(trigger_call()); - assert_matches!(ContractInfoOf::::get(BOB), Some(ContractInfo::Tombstone(_))); - assert_eq!(Balances::free_balance(BOB), subsistence_threshold); + assert!(trigger_call(addr.clone())); + assert_matches!(ContractInfoOf::::get(&addr), Some(ContractInfo::Tombstone(_))); + assert_eq!(Balances::free_balance(&addr), subsistence_threshold); }); } @@ -1036,32 +1039,36 @@ fn call_removed_contract() { Origin::signed(ALICE), 100, GAS_LIMIT, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance + ::Balance::from(1_000u32).encode(), // rent allowance + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Calling contract should succeed. - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); + assert_ok!( + Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, call::null()) + ); // Advance blocks initialize_block(10); // Calling contract should remove contract and fail. assert_err_ignore_postinfo!( - Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()), + Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, call::null()), Error::::NotCallable ); // Calling a contract that is about to evict shall emit an event. assert_eq!(System::events(), vec![ EventRecord { phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)), + event: MetaEvent::contracts(RawEvent::Evicted(addr.clone(), true)), topics: vec![], }, ]); // Subsequent contract calls should also fail. assert_err_ignore_postinfo!( - Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()), + Contracts::call(Origin::signed(ALICE), addr, 0, GAS_LIMIT, call::null()), Error::::NotCallable ); }) @@ -1084,20 +1091,24 @@ fn default_rent_allowance_on_instantiate() { GAS_LIMIT, code_hash.into(), vec![], + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + let bob_contract = ContractInfoOf::::get(&addr).unwrap().get_alive().unwrap(); assert_eq!(bob_contract.rent_allowance, >::max_value()); // Advance blocks initialize_block(5); // Trigger rent through call - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); + assert_ok!( + Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, call::null()) + ); // Check contract is still alive - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive(); + let bob_contract = ContractInfoOf::::get(&addr).unwrap().get_alive(); assert!(bob_contract.is_some()) }); } @@ -1139,12 +1150,12 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: assert_eq!(System::events(), vec![ EventRecord { phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), + event: MetaEvent::system(frame_system::RawEvent::NewAccount(ALICE)), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(ALICE, 1_000_000)), topics: vec![], }, EventRecord { @@ -1166,18 +1177,20 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: 30_000, GAS_LIMIT, set_rent_code_hash.into(), - ::Balance::from(0u32).encode() + ::Balance::from(0u32).encode(), + vec![], )); + let addr_bob = Contracts::contract_address(&ALICE, &set_rent_code_hash, &[]); // Check if `BOB` was created successfully and that the rent allowance is // set to 0. - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + let bob_contract = ContractInfoOf::::get(&addr_bob).unwrap().get_alive().unwrap(); assert_eq!(bob_contract.rent_allowance, 0); if test_different_storage { assert_ok!(Contracts::call( Origin::signed(ALICE), - BOB, 0, GAS_LIMIT, + addr_bob.clone(), 0, GAS_LIMIT, call::set_storage_4_byte()) ); } @@ -1188,15 +1201,17 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: // Call `BOB`, which makes it pay rent. Since the rent allowance is set to 0 // we expect that it will get removed leaving tombstone. assert_err_ignore_postinfo!( - Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()), + Contracts::call( + Origin::signed(ALICE), addr_bob.clone(), 0, GAS_LIMIT, call::null() + ), Error::::NotCallable ); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + assert!(ContractInfoOf::::get(&addr_bob).unwrap().get_tombstone().is_some()); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::Initialization, event: MetaEvent::contracts( - RawEvent::Evicted(BOB.clone(), true) + RawEvent::Evicted(addr_bob.clone(), true) ), topics: vec![], }, @@ -1212,13 +1227,16 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: 30_000, GAS_LIMIT, restoration_code_hash.into(), - ::Balance::from(0u32).encode() + ::Balance::from(0u32).encode(), + vec![], )); + let addr_django = Contracts::contract_address(&CHARLIE, &restoration_code_hash, &[]); // Before performing a call to `DJANGO` save its original trie id. - let django_trie_id = ContractInfoOf::::get(DJANGO).unwrap() + let django_trie_id = ContractInfoOf::::get(&addr_django).unwrap() .get_alive().unwrap().trie_id; + // The trie is regarded as 'dirty' when it was written to in the current block. if !test_restore_to_with_dirty_storage { // Advance 1 block, to the 6th. initialize_block(6); @@ -1229,37 +1247,43 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: let perform_the_restoration = || { Contracts::call( Origin::signed(ALICE), - DJANGO, + addr_django.clone(), 0, GAS_LIMIT, - set_rent_code_hash.as_ref().to_vec(), + set_rent_code_hash + .as_ref() + .iter() + .chain(AsRef::<[u8]>::as_ref(&addr_bob)) + .cloned() + .collect(), ) }; if test_different_storage || test_restore_to_with_dirty_storage { // Parametrization of the test imply restoration failure. Check that `DJANGO` aka // restoration contract is still in place and also that `BOB` doesn't exist. - - assert_err_ignore_postinfo!( - perform_the_restoration(), - Error::::ContractTrapped, - ); - - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - let django_contract = ContractInfoOf::::get(DJANGO).unwrap() + let result = perform_the_restoration(); + assert!(ContractInfoOf::::get(&addr_bob).unwrap().get_tombstone().is_some()); + let django_contract = ContractInfoOf::::get(&addr_django).unwrap() .get_alive().unwrap(); assert_eq!(django_contract.storage_size, 8); assert_eq!(django_contract.trie_id, django_trie_id); assert_eq!(django_contract.deduct_block, System::block_number()); match (test_different_storage, test_restore_to_with_dirty_storage) { (true, false) => { + assert_err_ignore_postinfo!( + result, Error::::InvalidTombstone, + ); assert_eq!(System::events(), vec![]); } (_, true) => { + assert_err_ignore_postinfo!( + result, Error::::InvalidContractOrigin, + ); pretty_assertions::assert_eq!(System::events(), vec![ EventRecord { phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)), + event: MetaEvent::contracts(RawEvent::Evicted(addr_bob, true)), topics: vec![], }, EventRecord { @@ -1274,24 +1298,24 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: }, EventRecord { phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(DJANGO)), + event: MetaEvent::system(frame_system::RawEvent::NewAccount(addr_django.clone())), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(DJANGO, 30_000)), + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(addr_django.clone(), 30_000)), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: MetaEvent::balances( - pallet_balances::RawEvent::Transfer(CHARLIE, DJANGO, 30_000) + pallet_balances::RawEvent::Transfer(CHARLIE, addr_django.clone(), 30_000) ), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Instantiated(CHARLIE, DJANGO)), + event: MetaEvent::contracts(RawEvent::Instantiated(CHARLIE, addr_django.clone())), topics: vec![], }, ]); @@ -1303,24 +1327,24 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: // Here we expect that the restoration is succeeded. Check that the restoration // contract `DJANGO` ceased to exist and that `BOB` returned back. - println!("{:?}", ContractInfoOf::::get(BOB)); - let bob_contract = ContractInfoOf::::get(BOB).unwrap() + println!("{:?}", ContractInfoOf::::get(&addr_bob)); + let bob_contract = ContractInfoOf::::get(&addr_bob).unwrap() .get_alive().unwrap(); assert_eq!(bob_contract.rent_allowance, 50); assert_eq!(bob_contract.storage_size, 4); assert_eq!(bob_contract.trie_id, django_trie_id); assert_eq!(bob_contract.deduct_block, System::block_number()); - assert!(ContractInfoOf::::get(DJANGO).is_none()); + assert!(ContractInfoOf::::get(&addr_django).is_none()); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::Initialization, - event: MetaEvent::system(system::RawEvent::KilledAccount(DJANGO)), + event: MetaEvent::system(system::RawEvent::KilledAccount(addr_django.clone())), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: MetaEvent::contracts( - RawEvent::Restored(DJANGO, BOB, bob_contract.code_hash, 50) + RawEvent::Restored(addr_django, addr_bob, bob_contract.code_hash, 50) ), topics: vec![], }, @@ -1346,16 +1370,18 @@ fn storage_max_value_limit() { GAS_LIMIT, code_hash.into(), vec![], + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + let bob_contract = ContractInfoOf::::get(&addr).unwrap().get_alive().unwrap(); assert_eq!(bob_contract.rent_allowance, >::max_value()); // Call contract with allowed storage value. assert_ok!(Contracts::call( Origin::signed(ALICE), - BOB, + addr.clone(), 0, GAS_LIMIT * 2, // we are copying a huge buffer ::MaxValueSize::get().encode(), @@ -1365,7 +1391,7 @@ fn storage_max_value_limit() { assert_err_ignore_postinfo!( Contracts::call( Origin::signed(ALICE), - BOB, + addr, 0, GAS_LIMIT, (::MaxValueSize::get() + 1).encode(), @@ -1395,13 +1421,15 @@ fn deploy_and_call_other_contract() { GAS_LIMIT, caller_code_hash.into(), vec![], + vec![], )); + let addr = Contracts::contract_address(&ALICE, &caller_code_hash, &[]); // Call BOB contract, which attempts to instantiate and call the callee contract and // makes various assertions on the results from those calls. assert_ok!(Contracts::call( Origin::signed(ALICE), - BOB, + addr, 0, GAS_LIMIT, callee_code_hash.as_ref().to_vec(), @@ -1426,11 +1454,13 @@ fn cannot_self_destruct_through_draning() { GAS_LIMIT, code_hash.into(), vec![], + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Check that the BOB contract has been instantiated. assert_matches!( - ContractInfoOf::::get(BOB), + ContractInfoOf::::get(&addr), Some(ContractInfo::Alive(_)) ); @@ -1439,7 +1469,7 @@ fn cannot_self_destruct_through_draning() { assert_ok!( Contracts::call( Origin::signed(ALICE), - BOB, + addr, 0, GAS_LIMIT, vec![], @@ -1465,11 +1495,13 @@ fn cannot_self_destruct_while_live() { GAS_LIMIT, code_hash.into(), vec![], + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Check that the BOB contract has been instantiated. assert_matches!( - ContractInfoOf::::get(BOB), + ContractInfoOf::::get(&addr), Some(ContractInfo::Alive(_)) ); @@ -1478,7 +1510,7 @@ fn cannot_self_destruct_while_live() { assert_err_ignore_postinfo!( Contracts::call( Origin::signed(ALICE), - BOB, + addr.clone(), 0, GAS_LIMIT, vec![0], @@ -1488,7 +1520,7 @@ fn cannot_self_destruct_while_live() { // Check that BOB is still alive. assert_matches!( - ContractInfoOf::::get(BOB), + ContractInfoOf::::get(&addr), Some(ContractInfo::Alive(_)) ); }); @@ -1511,11 +1543,13 @@ fn self_destruct_works() { GAS_LIMIT, code_hash.into(), vec![], + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Check that the BOB contract has been instantiated. assert_matches!( - ContractInfoOf::::get(BOB), + ContractInfoOf::::get(&addr), Some(ContractInfo::Alive(_)) ); @@ -1523,7 +1557,7 @@ fn self_destruct_works() { assert_matches!( Contracts::call( Origin::signed(ALICE), - BOB, + addr.clone(), 0, GAS_LIMIT, vec![], @@ -1532,7 +1566,7 @@ fn self_destruct_works() { ); // Check that account is gone - assert!(ContractInfoOf::::get(BOB).is_none()); + assert!(ContractInfoOf::::get(&addr).is_none()); // check that the beneficiary (django) got remaining balance assert_eq!(Balances::free_balance(DJANGO), 100_000); @@ -1563,25 +1597,30 @@ fn destroy_contract_and_transfer_funds() { GAS_LIMIT, caller_code_hash.into(), callee_code_hash.as_ref().to_vec(), + vec![], )); + let addr_bob = Contracts::contract_address(&ALICE, &caller_code_hash, &[]); + let addr_charlie = Contracts::contract_address( + &addr_bob, &callee_code_hash, &[0x47, 0x11] + ); // Check that the CHARLIE contract has been instantiated. assert_matches!( - ContractInfoOf::::get(CHARLIE), + ContractInfoOf::::get(&addr_charlie), Some(ContractInfo::Alive(_)) ); // Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct. assert_ok!(Contracts::call( Origin::signed(ALICE), - BOB, + addr_bob, 0, GAS_LIMIT, - CHARLIE.encode(), + addr_charlie.encode(), )); // Check that CHARLIE has moved on to the great beyond (ie. died). - assert!(ContractInfoOf::::get(CHARLIE).is_none()); + assert!(ContractInfoOf::::get(&addr_charlie).is_none()); }); } @@ -1603,6 +1642,7 @@ fn cannot_self_destruct_in_constructor() { GAS_LIMIT, code_hash.into(), vec![], + vec![], ), Error::::NewContractNotFunded, ); @@ -1627,7 +1667,9 @@ fn crypto_hashes() { GAS_LIMIT, code_hash.into(), vec![], + vec![], )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Perform the call. let input = b"_DEAD_BEEF"; use sp_io::hashing::*; @@ -1651,7 +1693,7 @@ fn crypto_hashes() { params.extend_from_slice(input); let result = >::bare_call( ALICE, - BOB, + addr.clone(), 0, GAS_LIMIT, params, @@ -1678,13 +1720,15 @@ fn transfer_return_code() { GAS_LIMIT, code_hash.into(), vec![], + vec![], ), ); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // Contract has only the minimal balance so any transfer will return BelowSubsistence. let result = Contracts::bare_call( ALICE, - BOB, + addr.clone(), 0, GAS_LIMIT, vec![], @@ -1694,11 +1738,11 @@ fn transfer_return_code() { // Contract has enough total balance in order to not go below the subsistence // threshold when transfering 100 balance but this balance is reserved so // the transfer still fails but with another return code. - Balances::make_free_balance_be(&BOB, subsistence + 100); - Balances::reserve(&BOB, subsistence + 100).unwrap(); + Balances::make_free_balance_be(&addr, subsistence + 100); + Balances::reserve(&addr, subsistence + 100).unwrap(); let result = Contracts::bare_call( ALICE, - BOB, + addr, 0, GAS_LIMIT, vec![], @@ -1725,16 +1769,18 @@ fn call_return_code() { GAS_LIMIT, caller_hash.into(), vec![0], + vec![], ), ); + let addr_bob = Contracts::contract_address(&ALICE, &caller_hash, &[]); // Contract calls into Django which is no valid contract let result = Contracts::bare_call( ALICE, - BOB, + addr_bob.clone(), 0, GAS_LIMIT, - vec![0], + AsRef::<[u8]>::as_ref(&DJANGO).to_vec(), ).exec_result.unwrap(); assert_return_code!(result, RuntimeReturnCode::NotCallable); @@ -1745,51 +1791,53 @@ fn call_return_code() { GAS_LIMIT, callee_hash.into(), vec![0], + vec![], ), ); + let addr_django = Contracts::contract_address(&CHARLIE, &callee_hash, &[]); // Contract has only the minimal balance so any transfer will return BelowSubsistence. let result = Contracts::bare_call( ALICE, - BOB, + addr_bob.clone(), 0, GAS_LIMIT, - vec![0], + AsRef::<[u8]>::as_ref(&addr_django).iter().chain(&0u32.to_le_bytes()).cloned().collect(), ).exec_result.unwrap(); assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold); // Contract has enough total balance in order to not go below the subsistence // threshold when transfering 100 balance but this balance is reserved so // the transfer still fails but with another return code. - Balances::make_free_balance_be(&BOB, subsistence + 100); - Balances::reserve(&BOB, subsistence + 100).unwrap(); + Balances::make_free_balance_be(&addr_bob, subsistence + 100); + Balances::reserve(&addr_bob, subsistence + 100).unwrap(); let result = Contracts::bare_call( ALICE, - BOB, + addr_bob.clone(), 0, GAS_LIMIT, - vec![0], + AsRef::<[u8]>::as_ref(&addr_django).iter().chain(&0u32.to_le_bytes()).cloned().collect(), ).exec_result.unwrap(); assert_return_code!(result, RuntimeReturnCode::TransferFailed); // Contract has enough balance but callee reverts because "1" is passed. - Balances::make_free_balance_be(&BOB, subsistence + 1000); + Balances::make_free_balance_be(&addr_bob, subsistence + 1000); let result = Contracts::bare_call( ALICE, - BOB, + addr_bob.clone(), 0, GAS_LIMIT, - vec![1], + AsRef::<[u8]>::as_ref(&addr_django).iter().chain(&1u32.to_le_bytes()).cloned().collect(), ).exec_result.unwrap(); assert_return_code!(result, RuntimeReturnCode::CalleeReverted); // Contract has enough balance but callee traps because "2" is passed. let result = Contracts::bare_call( ALICE, - BOB, + addr_bob, 0, GAS_LIMIT, - vec![2], + AsRef::<[u8]>::as_ref(&addr_django).iter().chain(&2u32.to_le_bytes()).cloned().collect(), ).exec_result.unwrap(); assert_return_code!(result, RuntimeReturnCode::CalleeTrapped); @@ -1815,13 +1863,15 @@ fn instantiate_return_code() { GAS_LIMIT, caller_hash.into(), vec![], + vec![], ), ); + let addr = Contracts::contract_address(&ALICE, &caller_hash, &[]); // Contract has only the minimal balance so any transfer will return BelowSubsistence. let result = Contracts::bare_call( ALICE, - BOB, + addr.clone(), 0, GAS_LIMIT, vec![0; 33], @@ -1831,11 +1881,11 @@ fn instantiate_return_code() { // Contract has enough total balance in order to not go below the subsistence // threshold when transfering 100 balance but this balance is reserved so // the transfer still fails but with another return code. - Balances::make_free_balance_be(&BOB, subsistence + 100); - Balances::reserve(&BOB, subsistence + 100).unwrap(); + Balances::make_free_balance_be(&addr, subsistence + 100); + Balances::reserve(&addr, subsistence + 100).unwrap(); let result = Contracts::bare_call( ALICE, - BOB, + addr.clone(), 0, GAS_LIMIT, vec![0; 33], @@ -1843,10 +1893,10 @@ fn instantiate_return_code() { assert_return_code!(result, RuntimeReturnCode::TransferFailed); // Contract has enough balance but the passed code hash is invalid - Balances::make_free_balance_be(&BOB, subsistence + 1000); + Balances::make_free_balance_be(&addr, subsistence + 1000); let result = Contracts::bare_call( ALICE, - BOB, + addr.clone(), 0, GAS_LIMIT, vec![0; 33], @@ -1856,20 +1906,20 @@ fn instantiate_return_code() { // Contract has enough balance but callee reverts because "1" is passed. let result = Contracts::bare_call( ALICE, - BOB, + addr.clone(), 0, GAS_LIMIT, - callee_hash.iter().cloned().chain(sp_std::iter::once(1)).collect(), + callee_hash.iter().chain(&1u32.to_le_bytes()).cloned().collect(), ).exec_result.unwrap(); assert_return_code!(result, RuntimeReturnCode::CalleeReverted); // Contract has enough balance but callee traps because "2" is passed. let result = Contracts::bare_call( ALICE, - BOB, + addr, 0, GAS_LIMIT, - callee_hash.iter().cloned().chain(sp_std::iter::once(2)).collect(), + callee_hash.iter().chain(&2u32.to_le_bytes()).cloned().collect(), ).exec_result.unwrap(); assert_return_code!(result, RuntimeReturnCode::CalleeTrapped); diff --git a/frame/contracts/src/wasm/code_cache.rs b/frame/contracts/src/wasm/code_cache.rs index 34b8ea7443538..a64f387097ed0 100644 --- a/frame/contracts/src/wasm/code_cache.rs +++ b/frame/contracts/src/wasm/code_cache.rs @@ -30,6 +30,7 @@ use crate::wasm::{prepare, runtime::Env, PrefabWasmModule}; use crate::{CodeHash, CodeStorage, PristineCode, Schedule, Trait}; use sp_std::prelude::*; use sp_runtime::traits::Hash; +use sp_core::crypto::UncheckedFrom; use frame_support::StorageMap; /// Put code in the storage. The hash of code is used as a key and is returned @@ -39,7 +40,7 @@ use frame_support::StorageMap; pub fn save( original_code: Vec, schedule: &Schedule, -) -> Result, &'static str> { +) -> Result, &'static str> where T::AccountId: UncheckedFrom + AsRef<[u8]> { let prefab_module = prepare::prepare_contract::(&original_code, schedule)?; let code_hash = T::Hashing::hash(&original_code); @@ -57,7 +58,7 @@ pub fn save( pub fn save_raw( original_code: Vec, schedule: &Schedule, -) -> Result, &'static str> { +) -> Result, &'static str> where T::AccountId: UncheckedFrom + AsRef<[u8]> { let prefab_module = prepare::benchmarking::prepare_contract::(&original_code, schedule)?; let code_hash = T::Hashing::hash(&original_code); @@ -75,7 +76,7 @@ pub fn save_raw( pub fn load( code_hash: &CodeHash, schedule: &Schedule, -) -> Result { +) -> Result where T::AccountId: UncheckedFrom + AsRef<[u8]> { let mut prefab_module = >::get(code_hash).ok_or_else(|| "code is not found")?; diff --git a/frame/contracts/src/wasm/env_def/macros.rs b/frame/contracts/src/wasm/env_def/macros.rs index 2538f85fb7385..6741896102d40 100644 --- a/frame/contracts/src/wasm/env_def/macros.rs +++ b/frame/contracts/src/wasm/env_def/macros.rs @@ -127,7 +127,12 @@ macro_rules! define_func { fn $name< E: $seal_ty >( $ctx: &mut $crate::wasm::Runtime, args: &[sp_sandbox::Value], - ) -> Result { + ) -> Result + where + ::AccountId: + sp_core::crypto::UncheckedFrom<::Hash> + + AsRef<[u8]> + { #[allow(unused)] let mut args = args.iter(); @@ -183,7 +188,12 @@ macro_rules! define_env { } } - impl $crate::wasm::env_def::FunctionImplProvider for $init_name { + impl $crate::wasm::env_def::FunctionImplProvider for $init_name + where + ::AccountId: + sp_core::crypto::UncheckedFrom<::Hash> + + AsRef<[u8]> + { fn impls)>(f: &mut F) { register_func!(f, < E: $seal_ty > ; $( $name ( $ctx $( , $names : $params )* ) $( -> $returns)* => $body )* ); } diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index f90f3af688d96..baa75ad49720c 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -23,6 +23,7 @@ use crate::exec::Ext; use crate::gas::GasMeter; use sp_std::prelude::*; +use sp_core::crypto::UncheckedFrom; use codec::{Encode, Decode}; use sp_sandbox; @@ -32,7 +33,7 @@ mod code_cache; mod prepare; mod runtime; -use self::runtime::{to_execution_result, Runtime}; +use self::runtime::Runtime; use self::code_cache::load as load_code; use pallet_contracts_primitives::ExecResult; @@ -71,13 +72,16 @@ pub struct WasmLoader<'a, T: Trait> { schedule: &'a Schedule, } -impl<'a, T: Trait> WasmLoader<'a, T> { +impl<'a, T: Trait> WasmLoader<'a, T> where T::AccountId: UncheckedFrom + AsRef<[u8]> { pub fn new(schedule: &'a Schedule) -> Self { WasmLoader { schedule } } } -impl<'a, T: Trait> crate::exec::Loader for WasmLoader<'a, T> { +impl<'a, T: Trait> crate::exec::Loader for WasmLoader<'a, T> +where + T::AccountId: UncheckedFrom + AsRef<[u8]> +{ type Executable = WasmExecutable; fn load_init(&self, code_hash: &CodeHash) -> Result { @@ -97,17 +101,20 @@ impl<'a, T: Trait> crate::exec::Loader for WasmLoader<'a, T> { } /// Implementation of `Vm` that takes `WasmExecutable` and executes it. -pub struct WasmVm<'a, T: Trait> { +pub struct WasmVm<'a, T: Trait> where T::AccountId: UncheckedFrom + AsRef<[u8]> { schedule: &'a Schedule, } -impl<'a, T: Trait> WasmVm<'a, T> { +impl<'a, T: Trait> WasmVm<'a, T> where T::AccountId: UncheckedFrom + AsRef<[u8]> { pub fn new(schedule: &'a Schedule) -> Self { WasmVm { schedule } } } -impl<'a, T: Trait> crate::exec::Vm for WasmVm<'a, T> { +impl<'a, T: Trait> crate::exec::Vm for WasmVm<'a, T> +where + T::AccountId: UncheckedFrom + AsRef<[u8]> +{ type Executable = WasmExecutable; fn execute>( @@ -147,20 +154,22 @@ impl<'a, T: Trait> crate::exec::Vm for WasmVm<'a, T> { // entrypoint. let result = sp_sandbox::Instance::new(&exec.prefab_module.code, &imports, &mut runtime) .and_then(|mut instance| instance.invoke(exec.entrypoint_name, &[], &mut runtime)); - to_execution_result(runtime, result) + runtime.to_execution_result(result) } } #[cfg(test)] mod tests { use super::*; + use crate::{ + CodeHash, BalanceOf, Error, Module as Contracts, + exec::{Ext, StorageKey, AccountIdOf}, + gas::{Gas, GasMeter}, + tests::{Test, Call, ALICE, BOB}, + wasm::prepare::prepare_contract, + }; use std::collections::HashMap; use sp_core::H256; - use crate::exec::{Ext, StorageKey}; - use crate::gas::{Gas, GasMeter}; - use crate::tests::{Test, Call}; - use crate::wasm::prepare::prepare_contract; - use crate::{CodeHash, BalanceOf, Error}; use hex_literal::hex; use sp_runtime::DispatchError; use frame_support::weights::Weight; @@ -174,7 +183,7 @@ mod tests { #[derive(Debug, PartialEq, Eq)] struct RestoreEntry { - dest: u64, + dest: AccountIdOf, code_hash: H256, rent_allowance: u64, delta: Vec, @@ -186,16 +195,17 @@ mod tests { endowment: u64, data: Vec, gas_left: u64, + salt: Vec, } #[derive(Debug, PartialEq, Eq)] struct TerminationEntry { - beneficiary: u64, + beneficiary: AccountIdOf, } #[derive(Debug, PartialEq, Eq)] struct TransferEntry { - to: u64, + to: AccountIdOf, value: u64, data: Vec, } @@ -210,7 +220,6 @@ mod tests { restores: Vec, // (topics, data) events: Vec<(Vec, Vec)>, - next_account_id: u64, } impl Ext for MockExt { @@ -228,18 +237,17 @@ mod tests { endowment: u64, gas_meter: &mut GasMeter, data: Vec, - ) -> Result<(u64, ExecReturnValue), ExecError> { + salt: &[u8], + ) -> Result<(AccountIdOf, ExecReturnValue), ExecError> { self.instantiates.push(InstantiateEntry { code_hash: code_hash.clone(), endowment, data: data.to_vec(), gas_left: gas_meter.gas_left(), + salt: salt.to_vec(), }); - let address = self.next_account_id; - self.next_account_id += 1; - Ok(( - address, + Contracts::::contract_address(&ALICE, code_hash, salt), ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new(), @@ -248,11 +256,11 @@ mod tests { } fn transfer( &mut self, - to: &u64, + to: &AccountIdOf, value: u64, ) -> Result<(), DispatchError> { self.transfers.push(TransferEntry { - to: *to, + to: to.clone(), value, data: Vec::new(), }); @@ -260,13 +268,13 @@ mod tests { } fn call( &mut self, - to: &u64, + to: &AccountIdOf, value: u64, _gas_meter: &mut GasMeter, data: Vec, ) -> ExecResult { self.transfers.push(TransferEntry { - to: *to, + to: to.clone(), value, data: data, }); @@ -276,20 +284,20 @@ mod tests { } fn terminate( &mut self, - beneficiary: &u64, + beneficiary: &AccountIdOf, ) -> Result<(), DispatchError> { self.terminations.push(TerminationEntry { - beneficiary: *beneficiary, + beneficiary: beneficiary.clone(), }); Ok(()) } fn restore_to( &mut self, - dest: u64, + dest: AccountIdOf, code_hash: H256, rent_allowance: u64, delta: Vec, - ) -> Result<(), &'static str> { + ) -> Result<(), DispatchError> { self.restores.push(RestoreEntry { dest, code_hash, @@ -298,11 +306,11 @@ mod tests { }); Ok(()) } - fn caller(&self) -> &u64 { - &42 + fn caller(&self) -> &AccountIdOf { + &ALICE } - fn address(&self) -> &u64 { - &69 + fn address(&self) -> &AccountIdOf { + &BOB } fn balance(&self) -> u64 { 228 @@ -363,25 +371,26 @@ mod tests { value: u64, gas_meter: &mut GasMeter, input_data: Vec, - ) -> Result<(u64, ExecReturnValue), ExecError> { - (**self).instantiate(code, value, gas_meter, input_data) + salt: &[u8], + ) -> Result<(AccountIdOf, ExecReturnValue), ExecError> { + (**self).instantiate(code, value, gas_meter, input_data, salt) } fn transfer( &mut self, - to: &u64, + to: &AccountIdOf, value: u64, ) -> Result<(), DispatchError> { (**self).transfer(to, value) } fn terminate( &mut self, - beneficiary: &u64, + beneficiary: &AccountIdOf, ) -> Result<(), DispatchError> { (**self).terminate(beneficiary) } fn call( &mut self, - to: &u64, + to: &AccountIdOf, value: u64, gas_meter: &mut GasMeter, input_data: Vec, @@ -390,11 +399,11 @@ mod tests { } fn restore_to( &mut self, - dest: u64, + dest: AccountIdOf, code_hash: H256, rent_allowance: u64, delta: Vec, - ) -> Result<(), &'static str> { + ) -> Result<(), DispatchError> { (**self).restore_to( dest, code_hash, @@ -402,10 +411,10 @@ mod tests { delta, ) } - fn caller(&self) -> &u64 { + fn caller(&self) -> &AccountIdOf { (**self).caller() } - fn address(&self) -> &u64 { + fn address(&self) -> &AccountIdOf { (**self).address() } fn balance(&self) -> u64 { @@ -451,7 +460,11 @@ mod tests { input_data: Vec, ext: E, gas_meter: &mut GasMeter, - ) -> ExecResult { + ) -> ExecResult + where + ::AccountId: + UncheckedFrom<::Hash> + AsRef<[u8]> + { use crate::exec::Vm; let wasm = wat::parse_str(wat).unwrap(); @@ -485,21 +498,23 @@ mod tests { (drop (call $seal_transfer (i32.const 4) ;; Pointer to "account" address. - (i32.const 8) ;; Length of "account" address. - (i32.const 12) ;; Pointer to the buffer with value to transfer + (i32.const 32) ;; Length of "account" address. + (i32.const 36) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer. ) ) ) (func (export "deploy")) - ;; Destination AccountId to transfer the funds. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 4) "\07\00\00\00\00\00\00\00") + ;; Destination AccountId (ALICE) + (data (i32.const 4) + "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" + "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" + ) ;; Amount of value to transfer. ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 12) "\99\00\00\00\00\00\00\00") + (data (i32.const 36) "\99\00\00\00\00\00\00\00") ) "#; @@ -516,7 +531,7 @@ mod tests { assert_eq!( &mock_ext.transfers, &[TransferEntry { - to: 7, + to: ALICE, value: 153, data: Vec::new(), }] @@ -542,11 +557,11 @@ mod tests { (drop (call $seal_call (i32.const 4) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. + (i32.const 32) ;; Length of "callee" address. (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 12) ;; Pointer to the buffer with value to transfer + (i32.const 36) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 20) ;; Pointer to input data buffer address + (i32.const 44) ;; Pointer to input data buffer address (i32.const 4) ;; Length of input data buffer (i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output (i32.const 0) ;; Length is ignored in this case @@ -555,14 +570,17 @@ mod tests { ) (func (export "deploy")) - ;; Destination AccountId to transfer the funds. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 4) "\09\00\00\00\00\00\00\00") + ;; Destination AccountId (ALICE) + (data (i32.const 4) + "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" + "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" + ) + ;; Amount of value to transfer. ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 12) "\06\00\00\00\00\00\00\00") + (data (i32.const 36) "\06\00\00\00\00\00\00\00") - (data (i32.const 20) "\01\02\03\04") + (data (i32.const 44) "\01\02\03\04") ) "#; @@ -579,7 +597,7 @@ mod tests { assert_eq!( &mock_ext.transfers, &[TransferEntry { - to: 9, + to: ALICE, value: 6, data: vec![1, 2, 3, 4], }] @@ -602,7 +620,9 @@ mod tests { ;; output_ptr: u32, ;; output_len_ptr: u32 ;; ) -> u32 - (import "seal0" "seal_instantiate" (func $seal_instantiate (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32) (result i32))) + (import "seal0" "seal_instantiate" (func $seal_instantiate + (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32) + )) (import "env" "memory" (memory 1 1)) (func (export "call") (drop @@ -618,11 +638,15 @@ mod tests { (i32.const 0) ;; Length is ignored in this case (i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output (i32.const 0) ;; Length is ignored in this case + (i32.const 0) ;; salt_ptr + (i32.const 4) ;; salt_len ) ) ) (func (export "deploy")) + ;; Salt + (data (i32.const 0) "\42\43\44\45") ;; Amount of value to transfer. ;; Represented by u64 (8 bytes long) in little endian. (data (i32.const 4) "\03\00\00\00\00\00\00\00") @@ -653,7 +677,11 @@ mod tests { endowment: 3, data, gas_left: _, - }] if code_hash == &[0x11; 32].into() && data == &vec![1, 2, 3, 4] + salt, + }] if + code_hash == &[0x11; 32].into() && + data == &vec![1, 2, 3, 4] && + salt == &vec![0x42, 0x43, 0x44, 0x45] ); } @@ -668,14 +696,16 @@ mod tests { (func (export "call") (call $seal_terminate (i32.const 4) ;; Pointer to "beneficiary" address. - (i32.const 8) ;; Length of "beneficiary" address. + (i32.const 32) ;; Length of "beneficiary" address. ) ) (func (export "deploy")) ;; Beneficiary AccountId to transfer the funds. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 4) "\09\00\00\00\00\00\00\00") + (data (i32.const 4) + "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" + "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" + ) ) "#; @@ -692,7 +722,7 @@ mod tests { assert_eq!( &mock_ext.terminations, &[TerminationEntry { - beneficiary: 0x09, + beneficiary: ALICE, }] ); } @@ -716,11 +746,11 @@ mod tests { (drop (call $seal_call (i32.const 4) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. + (i32.const 32) ;; Length of "callee" address. (i64.const 228) ;; How much gas to devote for the execution. - (i32.const 12) ;; Pointer to the buffer with value to transfer + (i32.const 36) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 20) ;; Pointer to input data buffer address + (i32.const 44) ;; Pointer to input data buffer address (i32.const 4) ;; Length of input data buffer (i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output (i32.const 0) ;; Length is ignored in this cas @@ -730,13 +760,15 @@ mod tests { (func (export "deploy")) ;; Destination AccountId to transfer the funds. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 4) "\09\00\00\00\00\00\00\00") + (data (i32.const 4) + "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" + "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" + ) ;; Amount of value to transfer. ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 12) "\06\00\00\00\00\00\00\00") + (data (i32.const 36) "\06\00\00\00\00\00\00\00") - (data (i32.const 20) "\01\02\03\04") + (data (i32.const 44) "\01\02\03\04") ) "#; @@ -753,7 +785,7 @@ mod tests { assert_eq!( &mock_ext.transfers, &[TransferEntry { - to: 9, + to: ALICE, value: 6, data: vec![1, 2, 3, 4], }] @@ -863,19 +895,19 @@ mod tests { ;; fill the buffer with the caller. (call $seal_caller (i32.const 0) (i32.const 32)) - ;; assert len == 8 + ;; assert len == 32 (call $assert (i32.eq (i32.load (i32.const 32)) - (i32.const 8) + (i32.const 32) ) ) - ;; assert that contents of the buffer is equal to the i64 value of 42. + ;; assert that the first 64 byte are the beginning of "ALICE" (call $assert (i64.eq (i64.load (i32.const 0)) - (i64.const 42) + (i64.const 0x0101010101010101) ) ) ) @@ -916,19 +948,19 @@ mod tests { ;; fill the buffer with the self address. (call $seal_address (i32.const 0) (i32.const 32)) - ;; assert size == 8 + ;; assert size == 32 (call $assert (i32.eq (i32.load (i32.const 32)) - (i32.const 8) + (i32.const 32) ) ) - ;; assert that contents of the buffer is equal to the i64 value of 69. + ;; assert that the first 64 byte are the beginning of "BOB" (call $assert (i64.eq (i64.load (i32.const 0)) - (i64.const 69) + (i64.const 0x0202020202020202) ) ) ) diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index ecb74fa42ac63..92d6c066c1570 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -29,6 +29,7 @@ use frame_support::dispatch::DispatchError; use sp_std::prelude::*; use codec::{Decode, Encode}; use sp_runtime::traits::SaturatedConversion; +use sp_core::crypto::UncheckedFrom; use sp_io::hashing::{ keccak_256, blake2_256, @@ -120,92 +121,6 @@ enum TrapReason { Restoration, } -/// Can only be used for one call. -pub(crate) struct Runtime<'a, E: Ext + 'a> { - ext: &'a mut E, - input_data: Option>, - schedule: &'a Schedule, - memory: sp_sandbox::Memory, - gas_meter: &'a mut GasMeter, - trap_reason: Option, -} -impl<'a, E: Ext + 'a> Runtime<'a, E> { - pub(crate) fn new( - ext: &'a mut E, - input_data: Vec, - schedule: &'a Schedule, - memory: sp_sandbox::Memory, - gas_meter: &'a mut GasMeter, - ) -> Self { - Runtime { - ext, - input_data: Some(input_data), - schedule, - memory, - gas_meter, - trap_reason: None, - } - } -} - -/// Converts the sandbox result and the runtime state into the execution outcome. -/// -/// It evaluates information stored in the `trap_reason` variable of the runtime and -/// bases the outcome on the value if this variable. Only if `trap_reason` is `None` -/// the result of the sandbox is evaluated. -pub(crate) fn to_execution_result( - runtime: Runtime, - sandbox_result: Result, -) -> ExecResult { - // If a trap reason is set we base our decision solely on that. - if let Some(trap_reason) = runtime.trap_reason { - return match trap_reason { - // The trap was the result of the execution `return` host function. - TrapReason::Return(ReturnData{ flags, data }) => { - let flags = ReturnFlags::from_bits(flags).ok_or_else(|| - "used reserved bit in return flags" - )?; - Ok(ExecReturnValue { - flags, - data, - }) - }, - TrapReason::Termination => { - Ok(ExecReturnValue { - flags: ReturnFlags::empty(), - data: Vec::new(), - }) - }, - TrapReason::Restoration => { - Ok(ExecReturnValue { - flags: ReturnFlags::empty(), - data: Vec::new(), - }) - }, - TrapReason::SupervisorError(error) => Err(error)?, - } - } - - // Check the exact type of the error. - match sandbox_result { - // No traps were generated. Proceed normally. - Ok(_) => { - Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() }) - } - // `Error::Module` is returned only if instantiation or linking failed (i.e. - // wasm binary tried to import a function that is not provided by the host). - // This shouldn't happen because validation process ought to reject such binaries. - // - // Because panics are really undesirable in the runtime code, we treat this as - // a trap for now. Eventually, we might want to revisit this. - Err(sp_sandbox::Error::Module) => - Err("validation error")?, - // Any other kind of a trap should result in a failure. - Err(sp_sandbox::Error::Execution) | Err(sp_sandbox::Error::OutOfBounds) => - Err(Error::::ContractTrapped)? - } -} - #[cfg_attr(test, derive(Debug, PartialEq, Eq))] #[derive(Copy, Clone)] pub enum RuntimeToken { @@ -266,10 +181,10 @@ pub enum RuntimeToken { CallSurchargeTransfer, /// Weight of output received through `seal_call` for the given size. CallCopyOut(u32), - /// Weight of calling `seal_instantiate` for the given input size without output weight. + /// Weight of calling `seal_instantiate` for the given input and salt without output weight. /// This includes the transfer as an instantiate without a value will always be below /// the existential deposit and is disregarded as corner case. - InstantiateBase(u32), + InstantiateBase{input_data_len: u32, salt_len: u32}, /// Weight of output received through `seal_instantiate` for the given size. InstantiateCopyOut(u32), /// Weight of calling `seal_hash_sha_256` for the given input size. @@ -294,7 +209,10 @@ pub enum RuntimeToken { CurveBls12381Pairing(u32), } -impl Token for RuntimeToken { +impl Token for RuntimeToken +where + T::AccountId: UncheckedFrom, T::AccountId: AsRef<[u8]> +{ type Metadata = HostFnWeights; fn calculate_amount(&self, s: &Self::Metadata) -> Gas { @@ -334,8 +252,9 @@ impl Token for RuntimeToken { .saturating_add(s.call_per_input_byte.saturating_mul(len.into())), CallSurchargeTransfer => s.call_transfer_surcharge, CallCopyOut(len) => s.call_per_output_byte.saturating_mul(len.into()), - InstantiateBase(len) => s.instantiate - .saturating_add(s.instantiate_per_input_byte.saturating_mul(len.into())), + InstantiateBase{input_data_len, salt_len} => s.instantiate + .saturating_add(s.instantiate_per_input_byte.saturating_mul(input_data_len.into())) + .saturating_add(s.instantiate_per_salt_byte.saturating_mul(salt_len.into())), InstantiateCopyOut(len) => s.instantiate_per_output_byte .saturating_mul(len.into()), HashSha256(len) => s.hash_sha2_256 @@ -362,215 +281,377 @@ impl Token for RuntimeToken { } } -/// Charge the gas meter with the specified token. -/// -/// Returns `Err(HostError)` if there is not enough gas. -fn charge_gas(ctx: &mut Runtime, token: Tok) -> Result<(), sp_sandbox::HostError> -where - E: Ext, - Tok: Token>, -{ - match ctx.gas_meter.charge(&ctx.schedule.host_fn_weights, token) { - GasMeterResult::Proceed => Ok(()), - GasMeterResult::OutOfGas => { - ctx.trap_reason = Some(TrapReason::SupervisorError(Error::::OutOfGas.into())); - Err(sp_sandbox::HostError) - }, - } +/// This is only appropriate when writing out data of constant size that does not depend on user +/// input. In this case the costs for this copy was already charged as part of the token at +/// the beginning of the API entry point. +fn already_charged(_: u32) -> Option { + None } -/// Read designated chunk from the sandbox memory. -/// -/// Returns `Err` if one of the following conditions occurs: +/// Finds duplicates in a given vector. /// -/// - requested buffer is not within the bounds of the sandbox memory. -fn read_sandbox_memory( - ctx: &mut Runtime, - ptr: u32, - len: u32, -) -> Result, sp_sandbox::HostError> { - let mut buf = vec![0u8; len as usize]; - ctx.memory.get(ptr, buf.as_mut_slice()) - .map_err(|_| store_err(ctx, Error::::OutOfBounds))?; - Ok(buf) +/// This function has complexity of O(n log n) and no additional memory is required, although +/// the order of items is not preserved. +fn has_duplicates>(items: &mut Vec) -> bool { + // Sort the vector + items.sort_by(|a, b| { + Ord::cmp(a.as_ref(), b.as_ref()) + }); + // And then find any two consecutive equal elements. + items.windows(2).any(|w| { + match w { + &[ref a, ref b] => a == b, + _ => false, + } + }) } -/// Read designated chunk from the sandbox memory into the supplied buffer. -/// -/// Returns `Err` if one of the following conditions occurs: -/// -/// - requested buffer is not within the bounds of the sandbox memory. -fn read_sandbox_memory_into_buf( - ctx: &mut Runtime, - ptr: u32, - buf: &mut [u8], -) -> Result<(), sp_sandbox::HostError> { - ctx.memory.get(ptr, buf).map_err(|_| store_err(ctx, Error::::OutOfBounds)) +/// Can only be used for one call. +pub struct Runtime<'a, E: Ext + 'a> { + ext: &'a mut E, + input_data: Option>, + schedule: &'a Schedule, + memory: sp_sandbox::Memory, + gas_meter: &'a mut GasMeter, + trap_reason: Option, } -/// Read designated chunk from the sandbox memory and attempt to decode into the specified type. -/// -/// Returns `Err` if one of the following conditions occurs: -/// -/// - requested buffer is not within the bounds of the sandbox memory. -/// - the buffer contents cannot be decoded as the required type. -fn read_sandbox_memory_as( - ctx: &mut Runtime, - ptr: u32, - len: u32, -) -> Result { - let buf = read_sandbox_memory(ctx, ptr, len)?; - D::decode(&mut &buf[..]).map_err(|_| store_err(ctx, Error::::DecodingFailed)) -} +impl<'a, E> Runtime<'a, E> +where + E: Ext + 'a, + ::AccountId: + UncheckedFrom<::Hash> + AsRef<[u8]> +{ + pub fn new( + ext: &'a mut E, + input_data: Vec, + schedule: &'a Schedule, + memory: sp_sandbox::Memory, + gas_meter: &'a mut GasMeter, + ) -> Self { + Runtime { + ext, + input_data: Some(input_data), + schedule, + memory, + gas_meter, + trap_reason: None, + } + } -/// Write the given buffer to the designated location in the sandbox memory. -/// -/// Returns `Err` if one of the following conditions occurs: -/// -/// - designated area is not within the bounds of the sandbox memory. -fn write_sandbox_memory( - ctx: &mut Runtime, - ptr: u32, - buf: &[u8], -) -> Result<(), sp_sandbox::HostError> { - ctx.memory.set(ptr, buf).map_err(|_| store_err(ctx, Error::::OutOfBounds)) -} + /// Converts the sandbox result and the runtime state into the execution outcome. + /// + /// It evaluates information stored in the `trap_reason` variable of the runtime and + /// bases the outcome on the value if this variable. Only if `trap_reason` is `None` + /// the result of the sandbox is evaluated. + pub fn to_execution_result( + self, + sandbox_result: Result, + ) -> ExecResult { + // If a trap reason is set we base our decision solely on that. + if let Some(trap_reason) = self.trap_reason { + return match trap_reason { + // The trap was the result of the execution `return` host function. + TrapReason::Return(ReturnData{ flags, data }) => { + let flags = ReturnFlags::from_bits(flags).ok_or_else(|| + "used reserved bit in return flags" + )?; + Ok(ExecReturnValue { + flags, + data, + }) + }, + TrapReason::Termination => { + Ok(ExecReturnValue { + flags: ReturnFlags::empty(), + data: Vec::new(), + }) + }, + TrapReason::Restoration => { + Ok(ExecReturnValue { + flags: ReturnFlags::empty(), + data: Vec::new(), + }) + }, + TrapReason::SupervisorError(error) => Err(error)?, + } + } -/// Write the given buffer and its length to the designated locations in sandbox memory and -/// charge gas according to the token returned by `create_token`. -// -/// `out_ptr` is the location in sandbox memory where `buf` should be written to. -/// `out_len_ptr` is an in-out location in sandbox memory. It is read to determine the -/// length of the buffer located at `out_ptr`. If that buffer is large enough the actual -/// `buf.len()` is written to this location. -/// -/// If `out_ptr` is set to the sentinel value of `u32::max_value()` and `allow_skip` is true the -/// operation is skipped and `Ok` is returned. This is supposed to help callers to make copying -/// output optional. For example to skip copying back the output buffer of an `seal_call` -/// when the caller is not interested in the result. -/// -/// `create_token` can optionally instruct this function to charge the gas meter with the token -/// it returns. `create_token` receives the variable amount of bytes that are about to be copied by -/// this function. -/// -/// In addition to the error conditions of `write_sandbox_memory` this functions returns -/// `Err` if the size of the buffer located at `out_ptr` is too small to fit `buf`. -fn write_sandbox_output( - ctx: &mut Runtime, - out_ptr: u32, - out_len_ptr: u32, - buf: &[u8], - allow_skip: bool, - create_token: impl FnOnce(u32) -> Option, -) -> Result<(), sp_sandbox::HostError> { - if allow_skip && out_ptr == u32::max_value() { - return Ok(()); + // Check the exact type of the error. + match sandbox_result { + // No traps were generated. Proceed normally. + Ok(_) => { + Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() }) + } + // `Error::Module` is returned only if instantiation or linking failed (i.e. + // wasm binary tried to import a function that is not provided by the host). + // This shouldn't happen because validation process ought to reject such binaries. + // + // Because panics are really undesirable in the runtime code, we treat this as + // a trap for now. Eventually, we might want to revisit this. + Err(sp_sandbox::Error::Module) => + Err("validation error")?, + // Any other kind of a trap should result in a failure. + Err(sp_sandbox::Error::Execution) | Err(sp_sandbox::Error::OutOfBounds) => + Err(Error::::ContractTrapped)? + } } - let buf_len = buf.len() as u32; - let len: u32 = read_sandbox_memory_as(ctx, out_len_ptr, 4)?; + /// Charge the gas meter with the specified token. + /// + /// Returns `Err(HostError)` if there is not enough gas. + fn charge_gas(&mut self, token: Tok) -> Result<(), sp_sandbox::HostError> + where + Tok: Token>, + { + match self.gas_meter.charge(&self.schedule.host_fn_weights, token) { + GasMeterResult::Proceed => Ok(()), + GasMeterResult::OutOfGas => { + self.trap_reason = Some( + TrapReason::SupervisorError(Error::::OutOfGas.into()) + ); + Err(sp_sandbox::HostError) + }, + } + } - if len < buf_len { - Err(store_err(ctx, Error::::OutputBufferTooSmall))? + /// Read designated chunk from the sandbox memory. + /// + /// Returns `Err` if one of the following conditions occurs: + /// + /// - requested buffer is not within the bounds of the sandbox memory. + fn read_sandbox_memory(&mut self, ptr: u32, len: u32) + -> Result, sp_sandbox::HostError> + { + let mut buf = vec![0u8; len as usize]; + self.memory.get(ptr, buf.as_mut_slice()) + .map_err(|_| self.store_err(Error::::OutOfBounds))?; + Ok(buf) } - if let Some(token) = create_token(buf_len) { - charge_gas(ctx, token)?; + /// Read designated chunk from the sandbox memory into the supplied buffer. + /// + /// Returns `Err` if one of the following conditions occurs: + /// + /// - requested buffer is not within the bounds of the sandbox memory. + fn read_sandbox_memory_into_buf(&mut self, ptr: u32, buf: &mut [u8]) + -> Result<(), sp_sandbox::HostError> + { + self.memory.get(ptr, buf).map_err(|_| self.store_err(Error::::OutOfBounds)) } - ctx.memory.set(out_ptr, buf).and_then(|_| { - ctx.memory.set(out_len_ptr, &buf_len.encode()) - }) - .map_err(|_| store_err(ctx, Error::::OutOfBounds))?; + /// Read designated chunk from the sandbox memory and attempt to decode into the specified type. + /// + /// Returns `Err` if one of the following conditions occurs: + /// + /// - requested buffer is not within the bounds of the sandbox memory. + /// - the buffer contents cannot be decoded as the required type. + fn read_sandbox_memory_as(&mut self, ptr: u32, len: u32) + -> Result + { + let buf = self.read_sandbox_memory(ptr, len)?; + D::decode(&mut &buf[..]).map_err(|_| self.store_err(Error::::DecodingFailed)) + } - Ok(()) -} + /// Write the given buffer to the designated location in the sandbox memory. + /// + /// Returns `Err` if one of the following conditions occurs: + /// + /// - designated area is not within the bounds of the sandbox memory. + fn write_sandbox_memory(&mut self, ptr: u32, buf: &[u8]) -> Result<(), sp_sandbox::HostError> { + self.memory.set(ptr, buf).map_err(|_| self.store_err(Error::::OutOfBounds)) + } -/// Supply to `write_sandbox_output` to indicate that the gas meter should not be charged. -/// -/// This is only appropriate when writing out data of constant size that does not depend on user -/// input. In this case the costs for this copy was already charged as part of the token at -/// the beginning of the API entry point. -fn already_charged(_: u32) -> Option { - None -} + /// Write the given buffer and its length to the designated locations in sandbox memory and + /// charge gas according to the token returned by `create_token`. + // + /// `out_ptr` is the location in sandbox memory where `buf` should be written to. + /// `out_len_ptr` is an in-out location in sandbox memory. It is read to determine the + /// length of the buffer located at `out_ptr`. If that buffer is large enough the actual + /// `buf.len()` is written to this location. + /// + /// If `out_ptr` is set to the sentinel value of `u32::max_value()` and `allow_skip` is true the + /// operation is skipped and `Ok` is returned. This is supposed to help callers to make copying + /// output optional. For example to skip copying back the output buffer of an `seal_call` + /// when the caller is not interested in the result. + /// + /// `create_token` can optionally instruct this function to charge the gas meter with the token + /// it returns. `create_token` receives the variable amount of bytes that are about to be copied by + /// this function. + /// + /// In addition to the error conditions of `write_sandbox_memory` this functions returns + /// `Err` if the size of the buffer located at `out_ptr` is too small to fit `buf`. + fn write_sandbox_output( + &mut self, + out_ptr: u32, + out_len_ptr: u32, + buf: &[u8], + allow_skip: bool, + create_token: impl FnOnce(u32) -> Option, + ) -> Result<(), sp_sandbox::HostError> + { + if allow_skip && out_ptr == u32::max_value() { + return Ok(()); + } -/// Stores a DispatchError returned from an Ext function into the trap_reason. -/// -/// This allows through supervisor generated errors to the caller. -fn store_err(ctx: &mut Runtime, err: Error) -> sp_sandbox::HostError where - E: Ext, - Error: Into, -{ - ctx.trap_reason = Some(TrapReason::SupervisorError(err.into())); - sp_sandbox::HostError -} + let buf_len = buf.len() as u32; + let len: u32 = self.read_sandbox_memory_as(out_len_ptr, 4)?; -/// Fallible conversion of `DispatchError` to `ReturnCode`. -fn err_into_return_code(from: DispatchError) -> Result { - use ReturnCode::*; - - let below_sub = Error::::BelowSubsistenceThreshold.into(); - let transfer_failed = Error::::TransferFailed.into(); - let not_funded = Error::::NewContractNotFunded.into(); - let no_code = Error::::CodeNotFound.into(); - let invalid_contract = Error::::NotCallable.into(); - - match from { - x if x == below_sub => Ok(BelowSubsistenceThreshold), - x if x == transfer_failed => Ok(TransferFailed), - x if x == not_funded => Ok(NewContractNotFunded), - x if x == no_code => Ok(CodeNotFound), - x if x == invalid_contract => Ok(NotCallable), - err => Err(err) + if len < buf_len { + Err(self.store_err(Error::::OutputBufferTooSmall))? + } + + if let Some(token) = create_token(buf_len) { + self.charge_gas(token)?; + } + + self.memory.set(out_ptr, buf).and_then(|_| { + self.memory.set(out_len_ptr, &buf_len.encode()) + }) + .map_err(|_| self.store_err(Error::::OutOfBounds))?; + + Ok(()) } -} -/// Fallible conversion of a `ExecResult` to `ReturnCode`. -fn exec_into_return_code(from: ExecResult) -> Result { - use pallet_contracts_primitives::ErrorOrigin::Callee; + /// Computes the given hash function on the supplied input. + /// + /// Reads from the sandboxed input buffer into an intermediate buffer. + /// Returns the result directly to the output buffer of the sandboxed memory. + /// + /// It is the callers responsibility to provide an output buffer that + /// is large enough to hold the expected amount of bytes returned by the + /// chosen hash function. + /// + /// # Note + /// + /// The `input` and `output` buffers may overlap. + fn compute_hash_on_intermediate_buffer( + &mut self, + hash_fn: F, + input_ptr: u32, + input_len: u32, + output_ptr: u32, + ) -> Result<(), sp_sandbox::HostError> + where + F: FnOnce(&[u8]) -> R, + R: AsRef<[u8]>, + { + // Copy input into supervisor memory. + let input = self.read_sandbox_memory(input_ptr, input_len)?; + // Compute the hash on the input buffer using the given hash function. + let hash = hash_fn(&input); + // Write the resulting hash back into the sandboxed output buffer. + self.write_sandbox_memory(output_ptr, hash.as_ref())?; + Ok(()) + } - let ExecError { error, origin } = match from { - Ok(retval) => return Ok(retval.into()), - Err(err) => err, - }; + /// Computes the given curve function on the supplied input. + /// + /// Reads from the sandboxed input buffer into an intermediate buffer. + /// Returns the result directly to the output buffer of the sandboxed memory. + /// + /// It is the callers responsibility to provide an output buffer that + /// is large enough to hold the expected amount of bytes returned by the + /// chosen hash function. + /// + /// # Note + /// + /// The `input` and `output` buffers may overlap. + fn compute_curve_on_intermediate_buffer( + ctx: &mut Runtime, + inflect_fn: F, + input_ptr: u32, + input_len: u32, + result_ptr: u32, + ) -> Result<(), sp_sandbox::HostError> + where + E: Ext, + F: FnOnce(&[u8]) -> R, + R: AsRef<[u8]>, + { + // Copy g1 and g2 into supervisor memory. + let input = read_sandbox_memory(ctx, input_ptr, input_len)?; + // Write the resulting hash back into the sandboxed output buffer. + let point = inflect_fn(&input); + write_sandbox_memory(ctx, result_ptr, &point.as_ref())?; + Ok(()) + } + + /// Stores a DispatchError returned from an Ext function into the trap_reason. + /// + /// This allows through supervisor generated errors to the caller. + fn store_err(&mut self, err: Error) -> sp_sandbox::HostError + where + Error: Into, + { + self.trap_reason = Some(TrapReason::SupervisorError(err.into())); + sp_sandbox::HostError + } - match (error, origin) { - (_, Callee) => Ok(ReturnCode::CalleeTrapped), - (err, _) => err_into_return_code::(err) + /// Used by Runtime API that calls into other contracts. + /// + /// Those need to transform the the `ExecResult` returned from the execution into + /// a `ReturnCode`. If this conversion fails because the `ExecResult` constitutes a + /// a fatal error then this error is stored in the `ExecutionContext` so it can be + /// extracted for display in the UI. + fn map_exec_result(&mut self, result: ExecResult) -> Result { + match Self::exec_into_return_code(result) { + Ok(code) => Ok(code), + Err(err) => Err(self.store_err(err)), + } } -} -/// Used by Runtime API that calls into other contracts. -/// -/// Those need to transform the the `ExecResult` returned from the execution into -/// a `ReturnCode`. If this conversion fails because the `ExecResult` constitutes a -/// a fatal error then this error is stored in the `ExecutionContext` so it can be -/// extracted for display in the UI. -fn map_exec_result(ctx: &mut Runtime, result: ExecResult) + /// Try to convert an error into a `ReturnCode`. + /// + /// Used to decide between fatal and non-fatal errors. + fn map_dispatch_result(&mut self, result: Result) -> Result -{ - match exec_into_return_code::(result) { - Ok(code) => Ok(code), - Err(err) => Err(store_err(ctx, err)), + { + let err = if let Err(err) = result { + err + } else { + return Ok(ReturnCode::Success) + }; + + match Self::err_into_return_code(err) { + Ok(code) => Ok(code), + Err(err) => Err(self.store_err(err)), + } } -} -/// Try to convert an error into a `ReturnCode`. -/// -/// Used to decide between fatal and non-fatal errors. -fn map_dispatch_result(ctx: &mut Runtime, result: Result) - -> Result -{ - let err = if let Err(err) = result { - err - } else { - return Ok(ReturnCode::Success) - }; - - match err_into_return_code::(err) { - Ok(code) => Ok(code), - Err(err) => Err(store_err(ctx, err)), + /// Fallible conversion of `DispatchError` to `ReturnCode`. + fn err_into_return_code(from: DispatchError) -> Result { + use ReturnCode::*; + + let below_sub = Error::::BelowSubsistenceThreshold.into(); + let transfer_failed = Error::::TransferFailed.into(); + let not_funded = Error::::NewContractNotFunded.into(); + let no_code = Error::::CodeNotFound.into(); + let invalid_contract = Error::::NotCallable.into(); + + match from { + x if x == below_sub => Ok(BelowSubsistenceThreshold), + x if x == transfer_failed => Ok(TransferFailed), + x if x == not_funded => Ok(NewContractNotFunded), + x if x == no_code => Ok(CodeNotFound), + x if x == invalid_contract => Ok(NotCallable), + err => Err(err) + } + } + + /// Fallible conversion of a `ExecResult` to `ReturnCode`. + fn exec_into_return_code(from: ExecResult) -> Result { + use pallet_contracts_primitives::ErrorOrigin::Callee; + + let ExecError { error, origin } = match from { + Ok(retval) => return Ok(retval.into()), + Err(err) => err, + }; + + match (error, origin) { + (_, Callee) => Ok(ReturnCode::CalleeTrapped), + (err, _) => Self::err_into_return_code(err) + } } } @@ -595,7 +676,7 @@ define_env!(Env, , // // - amount: How much gas is used. gas(ctx, amount: u32) => { - charge_gas(ctx, RuntimeToken::MeteringBlock(amount))?; + ctx.charge_gas(RuntimeToken::MeteringBlock(amount))?; Ok(()) }, @@ -615,13 +696,13 @@ define_env!(Env, , // - If value length exceeds the configured maximum value length of a storage entry. // - Upon trying to set an empty storage entry (value length is 0). seal_set_storage(ctx, key_ptr: u32, value_ptr: u32, value_len: u32) => { - charge_gas(ctx, RuntimeToken::SetStorage(value_len))?; + ctx.charge_gas(RuntimeToken::SetStorage(value_len))?; if value_len > ctx.ext.max_value_size() { - Err(store_err(ctx, Error::::ValueTooLarge))?; + Err(ctx.store_err(Error::::ValueTooLarge))?; } let mut key: StorageKey = [0; 32]; - read_sandbox_memory_into_buf(ctx, key_ptr, &mut key)?; - let value = Some(read_sandbox_memory(ctx, value_ptr, value_len)?); + ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?; + let value = Some(ctx.read_sandbox_memory(value_ptr, value_len)?); ctx.ext.set_storage(key, value); Ok(()) }, @@ -632,9 +713,9 @@ define_env!(Env, , // // - `key_ptr`: pointer into the linear memory where the location to clear the value is placed. seal_clear_storage(ctx, key_ptr: u32) => { - charge_gas(ctx, RuntimeToken::ClearStorage)?; + ctx.charge_gas(RuntimeToken::ClearStorage)?; let mut key: StorageKey = [0; 32]; - read_sandbox_memory_into_buf(ctx, key_ptr, &mut key)?; + ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?; ctx.ext.set_storage(key, None); Ok(()) }, @@ -652,11 +733,11 @@ define_env!(Env, , // // `ReturnCode::KeyNotFound` seal_get_storage(ctx, key_ptr: u32, out_ptr: u32, out_len_ptr: u32) -> ReturnCode => { - charge_gas(ctx, RuntimeToken::GetStorageBase)?; + ctx.charge_gas(RuntimeToken::GetStorageBase)?; let mut key: StorageKey = [0; 32]; - read_sandbox_memory_into_buf(ctx, key_ptr, &mut key)?; + ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?; if let Some(value) = ctx.ext.get_storage(&key) { - write_sandbox_output(ctx, out_ptr, out_len_ptr, &value, false, |len| { + ctx.write_sandbox_output(out_ptr, out_len_ptr, &value, false, |len| { Some(RuntimeToken::GetStorageCopyOut(len)) })?; Ok(ReturnCode::Success) @@ -687,14 +768,14 @@ define_env!(Env, , value_ptr: u32, value_len: u32 ) -> ReturnCode => { - charge_gas(ctx, RuntimeToken::Transfer)?; + ctx.charge_gas(RuntimeToken::Transfer)?; let callee: <::T as frame_system::Trait>::AccountId = - read_sandbox_memory_as(ctx, account_ptr, account_len)?; + ctx.read_sandbox_memory_as(account_ptr, account_len)?; let value: BalanceOf<::T> = - read_sandbox_memory_as(ctx, value_ptr, value_len)?; + ctx.read_sandbox_memory_as(value_ptr, value_len)?; let result = ctx.ext.transfer(&callee, value); - map_dispatch_result(ctx, result) + ctx.map_dispatch_result(result) }, // Make a call to another contract. @@ -740,14 +821,14 @@ define_env!(Env, , output_ptr: u32, output_len_ptr: u32 ) -> ReturnCode => { - charge_gas(ctx, RuntimeToken::CallBase(input_data_len))?; + ctx.charge_gas(RuntimeToken::CallBase(input_data_len))?; let callee: <::T as frame_system::Trait>::AccountId = - read_sandbox_memory_as(ctx, callee_ptr, callee_len)?; - let value: BalanceOf<::T> = read_sandbox_memory_as(ctx, value_ptr, value_len)?; - let input_data = read_sandbox_memory(ctx, input_data_ptr, input_data_len)?; + ctx.read_sandbox_memory_as(callee_ptr, callee_len)?; + let value: BalanceOf<::T> = ctx.read_sandbox_memory_as(value_ptr, value_len)?; + let input_data = ctx.read_sandbox_memory(input_data_ptr, input_data_len)?; if value > 0u32.into() { - charge_gas(ctx, RuntimeToken::CallSurchargeTransfer)?; + ctx.charge_gas(RuntimeToken::CallSurchargeTransfer)?; } let nested_gas_limit = if gas == 0 { @@ -772,11 +853,11 @@ define_env!(Env, , }); if let Ok(output) = &call_outcome { - write_sandbox_output(ctx, output_ptr, output_len_ptr, &output.data, true, |len| { + ctx.write_sandbox_output(output_ptr, output_len_ptr, &output.data, true, |len| { Some(RuntimeToken::CallCopyOut(len)) })?; } - map_exec_result(ctx, call_outcome) + ctx.map_exec_result(call_outcome) }, // Instantiate a contract with the specified code hash. @@ -807,6 +888,8 @@ define_env!(Env, , // - output_ptr: a pointer where the output buffer is copied to. // - output_len_ptr: in-out pointer to where the length of the buffer is read from // and the actual length is written to. + // - salt_ptr: Pointer to raw bytes used for address deriviation. See `fn contract_address`. + // - salt_len: length in bytes of the supplied salt. // // # Errors // @@ -834,13 +917,16 @@ define_env!(Env, , address_ptr: u32, address_len_ptr: u32, output_ptr: u32, - output_len_ptr: u32 + output_len_ptr: u32, + salt_ptr: u32, + salt_len: u32 ) -> ReturnCode => { - charge_gas(ctx, RuntimeToken::InstantiateBase(input_data_len))?; + ctx.charge_gas(RuntimeToken::InstantiateBase {input_data_len, salt_len})?; let code_hash: CodeHash<::T> = - read_sandbox_memory_as(ctx, code_hash_ptr, code_hash_len)?; - let value: BalanceOf<::T> = read_sandbox_memory_as(ctx, value_ptr, value_len)?; - let input_data = read_sandbox_memory(ctx, input_data_ptr, input_data_len)?; + ctx.read_sandbox_memory_as(code_hash_ptr, code_hash_len)?; + let value: BalanceOf<::T> = ctx.read_sandbox_memory_as(value_ptr, value_len)?; + let input_data = ctx.read_sandbox_memory(input_data_ptr, input_data_len)?; + let salt = ctx.read_sandbox_memory(salt_ptr, salt_len)?; let nested_gas_limit = if gas == 0 { ctx.gas_meter.gas_left() @@ -855,7 +941,8 @@ define_env!(Env, , &code_hash, value, nested_meter, - input_data + input_data, + &salt, ) } // there is not enough gas to allocate for the nested call. @@ -864,15 +951,15 @@ define_env!(Env, , }); if let Ok((address, output)) = &instantiate_outcome { if !output.flags.contains(ReturnFlags::REVERT) { - write_sandbox_output( - ctx, address_ptr, address_len_ptr, &address.encode(), true, already_charged, + ctx.write_sandbox_output( + address_ptr, address_len_ptr, &address.encode(), true, already_charged, )?; } - write_sandbox_output(ctx, output_ptr, output_len_ptr, &output.data, true, |len| { + ctx.write_sandbox_output(output_ptr, output_len_ptr, &output.data, true, |len| { Some(RuntimeToken::InstantiateCopyOut(len)) })?; } - map_exec_result(ctx, instantiate_outcome.map(|(_id, retval)| retval)) + ctx.map_exec_result(instantiate_outcome.map(|(_id, retval)| retval)) }, // Remove the calling account and transfer remaining balance. @@ -894,20 +981,20 @@ define_env!(Env, , beneficiary_ptr: u32, beneficiary_len: u32 ) => { - charge_gas(ctx, RuntimeToken::Terminate)?; + ctx.charge_gas(RuntimeToken::Terminate)?; let beneficiary: <::T as frame_system::Trait>::AccountId = - read_sandbox_memory_as(ctx, beneficiary_ptr, beneficiary_len)?; + ctx.read_sandbox_memory_as(beneficiary_ptr, beneficiary_len)?; - if let Ok(_) = ctx.ext.terminate(&beneficiary) { + if let Ok(_) = ctx.ext.terminate(&beneficiary).map_err(|e| ctx.store_err(e)) { ctx.trap_reason = Some(TrapReason::Termination); } Err(sp_sandbox::HostError) }, seal_input(ctx, buf_ptr: u32, buf_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::InputBase)?; + ctx.charge_gas(RuntimeToken::InputBase)?; if let Some(input) = ctx.input_data.take() { - write_sandbox_output(ctx, buf_ptr, buf_len_ptr, &input, false, |len| { + ctx.write_sandbox_output(buf_ptr, buf_len_ptr, &input, false, |len| { Some(RuntimeToken::InputCopyOut(len)) }) } else { @@ -933,10 +1020,10 @@ define_env!(Env, , // // Using a reserved bit triggers a trap. seal_return(ctx, flags: u32, data_ptr: u32, data_len: u32) => { - charge_gas(ctx, RuntimeToken::Return(data_len))?; + ctx.charge_gas(RuntimeToken::Return(data_len))?; ctx.trap_reason = Some(TrapReason::Return(ReturnData { flags, - data: read_sandbox_memory(ctx, data_ptr, data_len)?, + data: ctx.read_sandbox_memory(data_ptr, data_len)?, })); // The trap mechanism is used to immediately terminate the execution. @@ -956,9 +1043,9 @@ define_env!(Env, , // extrinsic will be returned. Otherwise, if this call is initiated by another contract then the // address of the contract will be returned. The value is encoded as T::AccountId. seal_caller(ctx, out_ptr: u32, out_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::Caller)?; - write_sandbox_output( - ctx, out_ptr, out_len_ptr, &ctx.ext.caller().encode(), false, already_charged + ctx.charge_gas(RuntimeToken::Caller)?; + ctx.write_sandbox_output( + out_ptr, out_len_ptr, &ctx.ext.caller().encode(), false, already_charged ) }, @@ -969,9 +1056,9 @@ define_env!(Env, , // `out_ptr`. This call overwrites it with the size of the value. If the available // space at `out_ptr` is less than the size of the value a trap is triggered. seal_address(ctx, out_ptr: u32, out_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::Address)?; - write_sandbox_output( - ctx, out_ptr, out_len_ptr, &ctx.ext.address().encode(), false, already_charged + ctx.charge_gas(RuntimeToken::Address)?; + ctx.write_sandbox_output( + out_ptr, out_len_ptr, &ctx.ext.address().encode(), false, already_charged ) }, @@ -989,10 +1076,9 @@ define_env!(Env, , // It is recommended to avoid specifying very small values for `gas` as the prices for a single // gas can be smaller than one. seal_weight_to_fee(ctx, gas: u64, out_ptr: u32, out_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::WeightToFee)?; - write_sandbox_output( - ctx, out_ptr, out_len_ptr, &ctx.ext.get_weight_price(gas).encode(), false, - already_charged + ctx.charge_gas(RuntimeToken::WeightToFee)?; + ctx.write_sandbox_output( + out_ptr, out_len_ptr, &ctx.ext.get_weight_price(gas).encode(), false, already_charged ) }, @@ -1005,9 +1091,9 @@ define_env!(Env, , // // The data is encoded as Gas. seal_gas_left(ctx, out_ptr: u32, out_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::GasLeft)?; - write_sandbox_output( - ctx, out_ptr, out_len_ptr, &ctx.gas_meter.gas_left().encode(), false, already_charged + ctx.charge_gas(RuntimeToken::GasLeft)?; + ctx.write_sandbox_output( + out_ptr, out_len_ptr, &ctx.gas_meter.gas_left().encode(), false, already_charged ) }, @@ -1020,9 +1106,9 @@ define_env!(Env, , // // The data is encoded as T::Balance. seal_balance(ctx, out_ptr: u32, out_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::Balance)?; - write_sandbox_output( - ctx, out_ptr, out_len_ptr, &ctx.ext.balance().encode(), false, already_charged + ctx.charge_gas(RuntimeToken::Balance)?; + ctx.write_sandbox_output( + out_ptr, out_len_ptr, &ctx.ext.balance().encode(), false, already_charged ) }, @@ -1035,10 +1121,9 @@ define_env!(Env, , // // The data is encoded as T::Balance. seal_value_transferred(ctx, out_ptr: u32, out_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::ValueTransferred)?; - write_sandbox_output( - ctx, out_ptr, out_len_ptr, &ctx.ext.value_transferred().encode(), false, - already_charged + ctx.charge_gas(RuntimeToken::ValueTransferred)?; + ctx.write_sandbox_output( + out_ptr, out_len_ptr, &ctx.ext.value_transferred().encode(), false, already_charged ) }, @@ -1051,14 +1136,13 @@ define_env!(Env, , // // The data is encoded as T::Hash. seal_random(ctx, subject_ptr: u32, subject_len: u32, out_ptr: u32, out_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::Random)?; + ctx.charge_gas(RuntimeToken::Random)?; if subject_len > ctx.schedule.limits.subject_len { return Err(sp_sandbox::HostError); } - let subject_buf = read_sandbox_memory(ctx, subject_ptr, subject_len)?; - write_sandbox_output( - ctx, out_ptr, out_len_ptr, &ctx.ext.random(&subject_buf).encode(), false, - already_charged + let subject_buf = ctx.read_sandbox_memory(subject_ptr, subject_len)?; + ctx.write_sandbox_output( + out_ptr, out_len_ptr, &ctx.ext.random(&subject_buf).encode(), false, already_charged ) }, @@ -1069,9 +1153,9 @@ define_env!(Env, , // `out_ptr`. This call overwrites it with the size of the value. If the available // space at `out_ptr` is less than the size of the value a trap is triggered. seal_now(ctx, out_ptr: u32, out_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::Now)?; - write_sandbox_output( - ctx, out_ptr, out_len_ptr, &ctx.ext.now().encode(), false, already_charged + ctx.charge_gas(RuntimeToken::Now)?; + ctx.write_sandbox_output( + out_ptr, out_len_ptr, &ctx.ext.now().encode(), false, already_charged ) }, @@ -1079,9 +1163,9 @@ define_env!(Env, , // // The data is encoded as T::Balance. seal_minimum_balance(ctx, out_ptr: u32, out_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::MinimumBalance)?; - write_sandbox_output( - ctx, out_ptr, out_len_ptr, &ctx.ext.minimum_balance().encode(), false, already_charged + ctx.charge_gas(RuntimeToken::MinimumBalance)?; + ctx.write_sandbox_output( + out_ptr, out_len_ptr, &ctx.ext.minimum_balance().encode(), false, already_charged ) }, @@ -1101,10 +1185,9 @@ define_env!(Env, , // below the sum of existential deposit and the tombstone deposit. The sum // is commonly referred as subsistence threshold in code. seal_tombstone_deposit(ctx, out_ptr: u32, out_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::TombstoneDeposit)?; - write_sandbox_output( - ctx, out_ptr, out_len_ptr, &ctx.ext.tombstone_deposit().encode(), false, - already_charged + ctx.charge_gas(RuntimeToken::TombstoneDeposit)?; + ctx.write_sandbox_output( + out_ptr, out_len_ptr, &ctx.ext.tombstone_deposit().encode(), false, already_charged ) }, @@ -1145,13 +1228,13 @@ define_env!(Env, , delta_ptr: u32, delta_count: u32 ) => { - charge_gas(ctx, RuntimeToken::RestoreTo(delta_count))?; + ctx.charge_gas(RuntimeToken::RestoreTo(delta_count))?; let dest: <::T as frame_system::Trait>::AccountId = - read_sandbox_memory_as(ctx, dest_ptr, dest_len)?; + ctx.read_sandbox_memory_as(dest_ptr, dest_len)?; let code_hash: CodeHash<::T> = - read_sandbox_memory_as(ctx, code_hash_ptr, code_hash_len)?; + ctx.read_sandbox_memory_as(code_hash_ptr, code_hash_len)?; let rent_allowance: BalanceOf<::T> = - read_sandbox_memory_as(ctx, rent_allowance_ptr, rent_allowance_len)?; + ctx.read_sandbox_memory_as(rent_allowance_ptr, rent_allowance_len)?; let delta = { // We can eagerly allocate because we charged for the complete delta count already let mut delta = Vec::with_capacity(delta_count as usize); @@ -1162,7 +1245,7 @@ define_env!(Env, , // Read the delta into the provided buffer and collect it into the buffer. let mut delta_key: StorageKey = [0; KEY_SIZE]; - read_sandbox_memory_into_buf(ctx, key_ptr, &mut delta_key)?; + ctx.read_sandbox_memory_into_buf(key_ptr, &mut delta_key)?; delta.push(delta_key); // Offset key_ptr to the next element. @@ -1177,7 +1260,7 @@ define_env!(Env, , code_hash, rent_allowance, delta, - ) { + ).map_err(|e| ctx.store_err(e)) { ctx.trap_reason = Some(TrapReason::Restoration); } Err(sp_sandbox::HostError) @@ -1194,18 +1277,18 @@ define_env!(Env, , seal_deposit_event(ctx, topics_ptr: u32, topics_len: u32, data_ptr: u32, data_len: u32) => { let num_topic = topics_len .checked_div(sp_std::mem::size_of::>() as u32) - .ok_or_else(|| store_err(ctx, "Zero sized topics are not allowed"))?; - charge_gas(ctx, RuntimeToken::DepositEvent { + .ok_or_else(|| ctx.store_err("Zero sized topics are not allowed"))?; + ctx.charge_gas(RuntimeToken::DepositEvent { num_topic, len: data_len, })?; if data_len > ctx.ext.max_value_size() { - Err(store_err(ctx, Error::::ValueTooLarge))?; + Err(ctx.store_err(Error::::ValueTooLarge))?; } let mut topics: Vec::::T>> = match topics_len { 0 => Vec::new(), - _ => read_sandbox_memory_as(ctx, topics_ptr, topics_len)?, + _ => ctx.read_sandbox_memory_as(topics_ptr, topics_len)?, }; // If there are more than `event_topics`, then trap. @@ -1218,7 +1301,7 @@ define_env!(Env, , return Err(sp_sandbox::HostError); } - let event_data = read_sandbox_memory(ctx, data_ptr, data_len)?; + let event_data = ctx.read_sandbox_memory(data_ptr, data_len)?; ctx.ext.deposit_event(topics, event_data); @@ -1231,9 +1314,9 @@ define_env!(Env, , // Should be decodable as a `T::Balance`. Traps otherwise. // - value_len: length of the value buffer. seal_set_rent_allowance(ctx, value_ptr: u32, value_len: u32) => { - charge_gas(ctx, RuntimeToken::SetRentAllowance)?; + ctx.charge_gas(RuntimeToken::SetRentAllowance)?; let value: BalanceOf<::T> = - read_sandbox_memory_as(ctx, value_ptr, value_len)?; + ctx.read_sandbox_memory_as(value_ptr, value_len)?; ctx.ext.set_rent_allowance(value); Ok(()) @@ -1248,9 +1331,9 @@ define_env!(Env, , // // The data is encoded as T::Balance. seal_rent_allowance(ctx, out_ptr: u32, out_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::RentAllowance)?; - write_sandbox_output( - ctx, out_ptr, out_len_ptr, &ctx.ext.rent_allowance().encode(), false, already_charged + ctx.charge_gas(RuntimeToken::RentAllowance)?; + ctx.write_sandbox_output( + out_ptr, out_len_ptr, &ctx.ext.rent_allowance().encode(), false, already_charged ) }, @@ -1258,7 +1341,7 @@ define_env!(Env, , // Only available on `--dev` chains. // This function may be removed at any time, superseded by a more general contract debugging feature. seal_println(ctx, str_ptr: u32, str_len: u32) => { - let data = read_sandbox_memory(ctx, str_ptr, str_len)?; + let data = ctx.read_sandbox_memory(str_ptr, str_len)?; if let Ok(utf8) = core::str::from_utf8(&data) { sp_runtime::print(utf8); } @@ -1272,9 +1355,9 @@ define_env!(Env, , // `out_ptr`. This call overwrites it with the size of the value. If the available // space at `out_ptr` is less than the size of the value a trap is triggered. seal_block_number(ctx, out_ptr: u32, out_len_ptr: u32) => { - charge_gas(ctx, RuntimeToken::BlockNumber)?; - write_sandbox_output( - ctx, out_ptr, out_len_ptr, &ctx.ext.block_number().encode(), false, already_charged + ctx.charge_gas(RuntimeToken::BlockNumber)?; + ctx.write_sandbox_output( + out_ptr, out_len_ptr, &ctx.ext.block_number().encode(), false, already_charged ) }, @@ -1299,8 +1382,8 @@ define_env!(Env, , // data is placed. The function will write the result // directly into this buffer. seal_hash_sha2_256(ctx, input_ptr: u32, input_len: u32, output_ptr: u32) => { - charge_gas(ctx, RuntimeToken::HashSha256(input_len))?; - compute_hash_on_intermediate_buffer(ctx, sha2_256, input_ptr, input_len, output_ptr) + ctx.charge_gas(RuntimeToken::HashSha256(input_len))?; + ctx.compute_hash_on_intermediate_buffer(sha2_256, input_ptr, input_len, output_ptr) }, // Computes the KECCAK 256-bit hash on the given input buffer. @@ -1324,8 +1407,8 @@ define_env!(Env, , // data is placed. The function will write the result // directly into this buffer. seal_hash_keccak_256(ctx, input_ptr: u32, input_len: u32, output_ptr: u32) => { - charge_gas(ctx, RuntimeToken::HashKeccak256(input_len))?; - compute_hash_on_intermediate_buffer(ctx, keccak_256, input_ptr, input_len, output_ptr) + ctx.charge_gas(RuntimeToken::HashKeccak256(input_len))?; + ctx.compute_hash_on_intermediate_buffer(keccak_256, input_ptr, input_len, output_ptr) }, // Computes the BLAKE2 256-bit hash on the given input buffer. @@ -1349,8 +1432,8 @@ define_env!(Env, , // data is placed. The function will write the result // directly into this buffer. seal_hash_blake2_256(ctx, input_ptr: u32, input_len: u32, output_ptr: u32) => { - charge_gas(ctx, RuntimeToken::HashBlake256(input_len))?; - compute_hash_on_intermediate_buffer(ctx, blake2_256, input_ptr, input_len, output_ptr) + ctx.charge_gas(RuntimeToken::HashBlake256(input_len))?; + ctx.compute_hash_on_intermediate_buffer(blake2_256, input_ptr, input_len, output_ptr) }, // Computes the BLAKE2 128-bit hash on the given input buffer. @@ -1374,8 +1457,8 @@ define_env!(Env, , // data is placed. The function will write the result // directly into this buffer. seal_hash_blake2_128(ctx, input_ptr: u32, input_len: u32, output_ptr: u32) => { - charge_gas(ctx, RuntimeToken::HashBlake128(input_len))?; - compute_hash_on_intermediate_buffer(ctx, blake2_128, input_ptr, input_len, output_ptr) + ctx.charge_gas(RuntimeToken::HashBlake128(input_len))?; + ctx.compute_hash_on_intermediate_buffer(blake2_128, input_ptr, input_len, output_ptr) }, // Computes the ALTBN128 add on the given input buffer. // @@ -1398,11 +1481,9 @@ define_env!(Env, , // - `result_ptr`: the pointer into the linear memory where the result // data is placed. The function will write the result // directly into this buffer. - seal_curve_altbn_128_add( - ctx, input_ptr: u32, input_len: u32, output_ptr: u32 - ) => { - charge_gas(ctx, RuntimeToken::CurveAltBn128Add(input_len))?; - compute_curve_on_intermediate_buffer( + seal_curve_altbn_128_add(ctx, input_ptr: u32, input_len: u32, output_ptr: u32) => { + ctx.charge_gas(RuntimeToken::CurveAltBn128Add(input_len))?; + ctx.compute_curve_on_intermediate_buffer( ctx, altbn_128_add, input_ptr, input_len, output_ptr, ) }, @@ -1427,11 +1508,9 @@ define_env!(Env, , // - `result_ptr`: the pointer into the linear memory where the result // data is placed. The function will write the result // directly into this buffer. - seal_curve_altbn_128_mul( - ctx, input_ptr: u32, input_len: u32, output_ptr: u32 - ) => { - charge_gas(ctx, RuntimeToken::CurveAltBn128Mul(input_len))?; - compute_curve_on_intermediate_buffer( + seal_curve_altbn_128_mul(ctx, input_ptr: u32, input_len: u32, output_ptr: u32) => { + ctx.charge_gas(ctx, RuntimeToken::CurveAltBn128Mul(input_len))?; + ctx.compute_curve_on_intermediate_buffer( ctx, altbn_128_mul, input_ptr, input_len, output_ptr, ) }, @@ -1454,10 +1533,8 @@ define_env!(Env, , // - `result_ptr`: the pointer into the linear memory where the output // data is placed. The function will write the result // directly into this buffer. - seal_curve_altbn_128_pairing( - ctx, input_ptr: u32, input_len: u32, result_ptr: u32 - ) => { - charge_gas(ctx, RuntimeToken::CurveAltBn128Pairing(input_len))?; + seal_curve_altbn_128_pairing(ctx, input_ptr: u32, input_len: u32, result_ptr: u32) => { + ctx.charge_gas(RuntimeToken::CurveAltBn128Pairing(input_len))?; let input = read_sandbox_memory(ctx, input_ptr, input_len)?; let result = if altbn_128_pairing(&input) { [0] @@ -1489,10 +1566,8 @@ define_env!(Env, , // - `result_ptr`: the pointer into the linear memory where the output // data is placed. The function will write the result // directly into this buffer. - seal_curve_bls12_381_add( - ctx, input_ptr: u32, input_len: u32, output_ptr: u32 - ) => { - charge_gas(ctx, RuntimeToken::CurveBls12381Add(input_len))?; + seal_curve_bls12_381_add(ctx, input_ptr: u32, input_len: u32, output_ptr: u32) => { + ctx.charge_gas(RuntimeToken::CurveBls12381Add(input_len))?; compute_curve_on_intermediate_buffer( ctx, bls12_381_add, input_ptr, input_len, output_ptr, ) @@ -1518,10 +1593,8 @@ define_env!(Env, , // - `result_ptr`: the pointer into the linear memory where the output // data is placed. The function will write the result // directly into this buffer. - seal_curve_bls12_381_mul( - ctx, input_ptr: u32, input_len: u32, output_ptr: u32 - ) => { - charge_gas(ctx, RuntimeToken::CurveBls12381Mul(input_len))?; + seal_curve_bls12_381_mul(ctx, input_ptr: u32, input_len: u32, output_ptr: u32) => { + ctx.charge_gas(RuntimeToken::CurveBls12381Mul(input_len))?; compute_curve_on_intermediate_buffer( ctx, bls12_381_mul, input_ptr, input_len, output_ptr, ) @@ -1547,10 +1620,8 @@ define_env!(Env, , // - `result_ptr`: the pointer into the linear memory where the output // data is placed. The function will write the result // directly into this buffer. - seal_curve_bls12_381_pairing( - ctx, input_ptr: u32, input_len: u32, result_ptr: u32 - ) => { - charge_gas(ctx, RuntimeToken::CurveBls12381Pairing(input_len))?; + seal_curve_bls12_381_pairing(ctx, input_ptr: u32, input_len: u32, result_ptr: u32) => { + ctx.charge_gas(RuntimeToken::CurveBls12381Pairing(input_len))?; let input = read_sandbox_memory(ctx, input_ptr, input_len)?; let result = if bls12_381_pairing(&input) { [0] @@ -1561,92 +1632,3 @@ define_env!(Env, , Ok(()) }, ); - -/// Computes the given hash function on the supplied input. -/// -/// Reads from the sandboxed input buffer into an intermediate buffer. -/// Returns the result directly to the output buffer of the sandboxed memory. -/// -/// It is the callers responsibility to provide an output buffer that -/// is large enough to hold the expected amount of bytes returned by the -/// chosen hash function. -/// -/// # Note -/// -/// The `input` and `output` buffers may overlap. -fn compute_hash_on_intermediate_buffer( - ctx: &mut Runtime, - hash_fn: F, - input_ptr: u32, - input_len: u32, - output_ptr: u32, -) -> Result<(), sp_sandbox::HostError> -where - E: Ext, - F: FnOnce(&[u8]) -> R, - R: AsRef<[u8]>, -{ - // Copy input into supervisor memory. - let input = read_sandbox_memory(ctx, input_ptr, input_len)?; - // Compute the hash on the input buffer using the given hash function. - let hash = hash_fn(&input); - // Write the resulting hash back into the sandboxed output buffer. - write_sandbox_memory( - ctx, - output_ptr, - hash.as_ref(), - )?; - Ok(()) -} - - -/// Computes the given curve function on the supplied input. -/// -/// Reads from the sandboxed input buffer into an intermediate buffer. -/// Returns the result directly to the output buffer of the sandboxed memory. -/// -/// It is the callers responsibility to provide an output buffer that -/// is large enough to hold the expected amount of bytes returned by the -/// chosen hash function. -/// -/// # Note -/// -/// The `input` and `output` buffers may overlap. -fn compute_curve_on_intermediate_buffer( - ctx: &mut Runtime, - inflect_fn: F, - input_ptr: u32, - input_len: u32, - result_ptr: u32, -) -> Result<(), sp_sandbox::HostError> -where - E: Ext, - F: FnOnce(&[u8]) -> R, - R: AsRef<[u8]>, -{ - // Copy g1 and g2 into supervisor memory. - let input = read_sandbox_memory(ctx, input_ptr, input_len)?; - // Write the resulting hash back into the sandboxed output buffer. - let point = inflect_fn(&input); - write_sandbox_memory(ctx, result_ptr, &point.as_ref())?; - Ok(()) -} - - -/// Finds duplicates in a given vector. -/// -/// This function has complexity of O(n log n) and no additional memory is required, although -/// the order of items is not preserved. -fn has_duplicates>(items: &mut Vec) -> bool { - // Sort the vector - items.sort_by(|a, b| { - Ord::cmp(a.as_ref(), b.as_ref()) - }); - // And then find any two consecutive equal elements. - items.windows(2).any(|w| { - match w { - &[ref a, ref b] => a == b, - _ => false, - } - }) -} diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index 2f354ae77c7b6..6a1f271e74084 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -17,7 +17,7 @@ //! Weights for pallet_contracts //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0 -//! DATE: 2020-10-27, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: [] +//! DATE: 2020-11-10, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -45,7 +45,7 @@ use sp_std::marker::PhantomData; pub trait WeightInfo { fn update_schedule() -> Weight; fn put_code(n: u32, ) -> Weight; - fn instantiate(n: u32, ) -> Weight; + fn instantiate(n: u32, s: u32, ) -> Weight; fn call() -> Weight; fn claim_surcharge() -> Weight; fn seal_caller(r: u32, ) -> Weight; @@ -80,7 +80,7 @@ pub trait WeightInfo { fn seal_call(r: u32, ) -> Weight; fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight; fn seal_instantiate(r: u32, ) -> Weight; - fn seal_instantiate_per_input_output_kb(i: u32, o: u32, ) -> Weight; + fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight; fn seal_hash_sha2_256(r: u32, ) -> Weight; fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight; fn seal_hash_keccak_256(r: u32, ) -> Weight; @@ -152,228 +152,201 @@ pub trait WeightInfo { fn instr_i64shru(r: u32, ) -> Weight; fn instr_i64rotl(r: u32, ) -> Weight; fn instr_i64rotr(r: u32, ) -> Weight; - } /// Weights for pallet_contracts using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn update_schedule() -> Weight { - (33_160_000 as Weight) + (35_214_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) - } fn put_code(n: u32, ) -> Weight { - (5_975_000 as Weight) - .saturating_add((108_953_000 as Weight).saturating_mul(n as Weight)) + (0 as Weight) + .saturating_add((109_242_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) - } - fn instantiate(n: u32, ) -> Weight { - (218_223_000 as Weight) - .saturating_add((1_007_000 as Weight).saturating_mul(n as Weight)) + fn instantiate(n: u32, s: u32, ) -> Weight { + (195_276_000 as Weight) + .saturating_add((35_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((2_244_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } fn call() -> Weight { - (201_492_000 as Weight) + (207_142_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) - } fn claim_surcharge() -> Weight { - (449_203_000 as Weight) + (489_633_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) - } fn seal_caller(r: u32, ) -> Weight { - (136_650_000 as Weight) - .saturating_add((364_640_000 as Weight).saturating_mul(r as Weight)) + (136_550_000 as Weight) + .saturating_add((373_182_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_address(r: u32, ) -> Weight { - (144_167_000 as Weight) - .saturating_add((365_328_000 as Weight).saturating_mul(r as Weight)) + (136_329_000 as Weight) + .saturating_add((373_392_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_gas_left(r: u32, ) -> Weight { - (138_458_000 as Weight) - .saturating_add((361_076_000 as Weight).saturating_mul(r as Weight)) + (111_577_000 as Weight) + .saturating_add((373_536_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_balance(r: u32, ) -> Weight { - (147_909_000 as Weight) - .saturating_add((792_169_000 as Weight).saturating_mul(r as Weight)) + (157_531_000 as Weight) + .saturating_add((810_382_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) - } fn seal_value_transferred(r: u32, ) -> Weight { - (148_524_000 as Weight) - .saturating_add((361_842_000 as Weight).saturating_mul(r as Weight)) + (143_801_000 as Weight) + .saturating_add((369_769_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_minimum_balance(r: u32, ) -> Weight { - (139_795_000 as Weight) - .saturating_add((366_013_000 as Weight).saturating_mul(r as Weight)) + (133_546_000 as Weight) + .saturating_add((370_036_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_tombstone_deposit(r: u32, ) -> Weight { - (140_557_000 as Weight) - .saturating_add((362_687_000 as Weight).saturating_mul(r as Weight)) + (138_568_000 as Weight) + .saturating_add((370_322_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_rent_allowance(r: u32, ) -> Weight { - (152_989_000 as Weight) - .saturating_add((836_876_000 as Weight).saturating_mul(r as Weight)) + (144_431_000 as Weight) + .saturating_add((851_810_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_block_number(r: u32, ) -> Weight { - (140_228_000 as Weight) - .saturating_add((360_561_000 as Weight).saturating_mul(r as Weight)) + (133_237_000 as Weight) + .saturating_add((369_156_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_now(r: u32, ) -> Weight { - (148_776_000 as Weight) - .saturating_add((361_712_000 as Weight).saturating_mul(r as Weight)) + (139_700_000 as Weight) + .saturating_add((368_961_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_weight_to_fee(r: u32, ) -> Weight { - (126_903_000 as Weight) - .saturating_add((603_100_000 as Weight).saturating_mul(r as Weight)) + (149_395_000 as Weight) + .saturating_add((625_812_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) - } fn seal_gas(r: u32, ) -> Weight { - (125_712_000 as Weight) - .saturating_add((184_450_000 as Weight).saturating_mul(r as Weight)) + (125_777_000 as Weight) + .saturating_add((187_585_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_input(r: u32, ) -> Weight { - (136_175_000 as Weight) - .saturating_add((7_489_000 as Weight).saturating_mul(r as Weight)) + (132_584_000 as Weight) + .saturating_add((7_661_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_input_per_kb(n: u32, ) -> Weight { - (145_434_000 as Weight) - .saturating_add((276_000 as Weight).saturating_mul(n as Weight)) + (143_408_000 as Weight) + .saturating_add((274_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_return(r: u32, ) -> Weight { - (124_788_000 as Weight) - .saturating_add((5_696_000 as Weight).saturating_mul(r as Weight)) + (126_257_000 as Weight) + .saturating_add((5_455_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_return_per_kb(n: u32, ) -> Weight { - (133_483_000 as Weight) - .saturating_add((675_000 as Weight).saturating_mul(n as Weight)) + (133_286_000 as Weight) + .saturating_add((698_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_terminate(r: u32, ) -> Weight { - (135_387_000 as Weight) - .saturating_add((338_395_000 as Weight).saturating_mul(r as Weight)) + (130_607_000 as Weight) + .saturating_add((358_370_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(r as Weight))) } fn seal_restore_to(r: u32, ) -> Weight { - (227_617_000 as Weight) - .saturating_add((132_493_000 as Weight).saturating_mul(r as Weight)) + (233_645_000 as Weight) + .saturating_add((135_355_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(r as Weight))) } fn seal_restore_to_per_delta(d: u32, ) -> Weight { - (15_263_000 as Weight) - .saturating_add((3_732_219_000 as Weight).saturating_mul(d as Weight)) + (74_573_000 as Weight) + .saturating_add((3_768_682_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(d as Weight))) .saturating_add(T::DbWeight::get().writes(5 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(d as Weight))) } fn seal_random(r: u32, ) -> Weight { - (236_391_000 as Weight) - .saturating_add((913_452_000 as Weight).saturating_mul(r as Weight)) + (140_286_000 as Weight) + .saturating_add((950_890_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) - } fn seal_deposit_event(r: u32, ) -> Weight { - (140_845_000 as Weight) - .saturating_add((1_322_796_000 as Weight).saturating_mul(r as Weight)) + (167_735_000 as Weight) + .saturating_add((1_375_429_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (1_651_556_000 as Weight) - .saturating_add((737_421_000 as Weight).saturating_mul(t as Weight)) - .saturating_add((244_183_000 as Weight).saturating_mul(n as Weight)) + (1_715_857_000 as Weight) + .saturating_add((760_777_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((241_853_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(t as Weight))) } fn seal_set_rent_allowance(r: u32, ) -> Weight { - (151_091_000 as Weight) - .saturating_add((983_375_000 as Weight).saturating_mul(r as Weight)) + (156_911_000 as Weight) + .saturating_add((1_006_139_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) - } fn seal_set_storage(r: u32, ) -> Weight { - (460_478_000 as Weight) - .saturating_add((14_824_033_000 as Weight).saturating_mul(r as Weight)) + (0 as Weight) + .saturating_add((14_938_793_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (2_255_458_000 as Weight) - .saturating_add((204_470_000 as Weight).saturating_mul(n as Weight)) + (2_300_169_000 as Weight) + .saturating_add((204_543_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) - } fn seal_clear_storage(r: u32, ) -> Weight { (0 as Weight) - .saturating_add((5_052_125_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((5_140_241_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } fn seal_get_storage(r: u32, ) -> Weight { - (95_473_000 as Weight) - .saturating_add((1_044_784_000 as Weight).saturating_mul(r as Weight)) + (45_212_000 as Weight) + .saturating_add((1_131_504_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - } fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (860_080_000 as Weight) - .saturating_add((146_913_000 as Weight).saturating_mul(n as Weight)) + (885_531_000 as Weight) + .saturating_add((148_986_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) - } fn seal_transfer(r: u32, ) -> Weight { - (107_119_000 as Weight) - .saturating_add((5_993_434_000 as Weight).saturating_mul(r as Weight)) + (92_276_000 as Weight) + .saturating_add((6_216_852_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -381,83 +354,74 @@ impl WeightInfo for SubstrateWeight { } fn seal_call(r: u32, ) -> Weight { (0 as Weight) - .saturating_add((10_533_320_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((10_734_719_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - } fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (9_839_633_000 as Weight) - .saturating_add((5_580_035_000 as Weight).saturating_mul(t as Weight)) - .saturating_add((53_716_000 as Weight).saturating_mul(i as Weight)) - .saturating_add((73_668_000 as Weight).saturating_mul(o as Weight)) + (12_735_614_000 as Weight) + .saturating_add((2_870_730_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((52_569_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((73_956_000 as Weight).saturating_mul(o as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes((101 as Weight).saturating_mul(t as Weight))) } fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - .saturating_add((21_856_497_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((22_365_908_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((300 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) .saturating_add(T::DbWeight::get().writes((200 as Weight).saturating_mul(r as Weight))) } - fn seal_instantiate_per_input_output_kb(i: u32, o: u32, ) -> Weight { - (18_796_671_000 as Weight) - .saturating_add((156_269_000 as Weight).saturating_mul(i as Weight)) - .saturating_add((74_645_000 as Weight).saturating_mul(o as Weight)) + fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { + (18_899_296_000 as Weight) + .saturating_add((53_289_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((76_026_000 as Weight).saturating_mul(o as Weight)) + .saturating_add((281_097_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(207 as Weight)) .saturating_add(T::DbWeight::get().writes(202 as Weight)) - } fn seal_hash_sha2_256(r: u32, ) -> Weight { - (132_190_000 as Weight) - .saturating_add((319_943_000 as Weight).saturating_mul(r as Weight)) + (136_601_000 as Weight) + .saturating_add((323_373_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (747_208_000 as Weight) - .saturating_add((421_808_000 as Weight).saturating_mul(n as Weight)) + (777_563_000 as Weight) + .saturating_add((423_353_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_hash_keccak_256(r: u32, ) -> Weight { - (139_235_000 as Weight) - .saturating_add((333_792_000 as Weight).saturating_mul(r as Weight)) + (136_771_000 as Weight) + .saturating_add((337_881_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (543_256_000 as Weight) - .saturating_add((334_383_000 as Weight).saturating_mul(n as Weight)) + (337_906_000 as Weight) + .saturating_add((336_778_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_hash_blake2_256(r: u32, ) -> Weight { - (142_704_000 as Weight) - .saturating_add((305_513_000 as Weight).saturating_mul(r as Weight)) + (131_040_000 as Weight) + .saturating_add((312_992_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (592_813_000 as Weight) - .saturating_add((151_270_000 as Weight).saturating_mul(n as Weight)) + (693_415_000 as Weight) + .saturating_add((152_745_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_hash_blake2_128(r: u32, ) -> Weight { - (139_921_000 as Weight) - .saturating_add((304_746_000 as Weight).saturating_mul(r as Weight)) + (135_654_000 as Weight) + .saturating_add((311_271_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (544_524_000 as Weight) - .saturating_add((151_549_000 as Weight).saturating_mul(n as Weight)) + (839_521_000 as Weight) + .saturating_add((153_146_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - } fn seal_curve_altbn_128_add(r: u32) -> Weight { (139_921_000 as Weight) @@ -520,481 +484,403 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(4 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (24_652_000 as Weight) - .saturating_add((3_306_000 as Weight).saturating_mul(r as Weight)) - + (26_679_000 as Weight) + .saturating_add((3_155_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (27_131_000 as Weight) - .saturating_add((162_220_000 as Weight).saturating_mul(r as Weight)) - + (28_920_000 as Weight) + .saturating_add((159_343_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (27_086_000 as Weight) - .saturating_add((230_977_000 as Weight).saturating_mul(r as Weight)) - + (28_928_000 as Weight) + .saturating_add((227_286_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (24_656_000 as Weight) - .saturating_add((12_570_000 as Weight).saturating_mul(r as Weight)) - + (26_591_000 as Weight) + .saturating_add((12_591_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (24_643_000 as Weight) - .saturating_add((12_442_000 as Weight).saturating_mul(r as Weight)) - + (26_597_000 as Weight) + .saturating_add((12_258_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (24_589_000 as Weight) - .saturating_add((6_237_000 as Weight).saturating_mul(r as Weight)) - + (26_586_000 as Weight) + .saturating_add((5_811_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (24_650_000 as Weight) - .saturating_add((14_393_000 as Weight).saturating_mul(r as Weight)) - + (26_581_000 as Weight) + .saturating_add((14_058_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (24_689_000 as Weight) - .saturating_add((15_706_000 as Weight).saturating_mul(r as Weight)) - + (26_615_000 as Weight) + .saturating_add((15_687_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (40_129_000 as Weight) - .saturating_add((83_000 as Weight).saturating_mul(e as Weight)) - + (40_963_000 as Weight) + .saturating_add((92_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (24_904_000 as Weight) - .saturating_add((96_429_000 as Weight).saturating_mul(r as Weight)) - + (26_880_000 as Weight) + .saturating_add((97_523_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (32_540_000 as Weight) - .saturating_add((201_773_000 as Weight).saturating_mul(r as Weight)) - + (34_628_000 as Weight) + .saturating_add((201_913_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (248_700_000 as Weight) - .saturating_add((3_705_000 as Weight).saturating_mul(p as Weight)) - + (255_763_000 as Weight) + .saturating_add((3_612_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (42_081_000 as Weight) - .saturating_add((3_548_000 as Weight).saturating_mul(r as Weight)) - + (45_954_000 as Weight) + .saturating_add((3_439_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (42_128_000 as Weight) - .saturating_add((3_678_000 as Weight).saturating_mul(r as Weight)) - + (45_952_000 as Weight) + .saturating_add((3_601_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (42_073_000 as Weight) - .saturating_add((5_212_000 as Weight).saturating_mul(r as Weight)) - + (45_883_000 as Weight) + .saturating_add((5_203_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (28_182_000 as Weight) - .saturating_add((8_180_000 as Weight).saturating_mul(r as Weight)) - + (29_895_000 as Weight) + .saturating_add((8_221_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (28_060_000 as Weight) - .saturating_add((12_081_000 as Weight).saturating_mul(r as Weight)) - + (29_916_000 as Weight) + .saturating_add((12_036_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (27_113_000 as Weight) - .saturating_add((3_802_000 as Weight).saturating_mul(r as Weight)) - + (28_878_000 as Weight) + .saturating_add((3_794_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (25_521_000 as Weight) - .saturating_add((2_288_295_000 as Weight).saturating_mul(r as Weight)) - + (27_351_000 as Weight) + .saturating_add((2_302_301_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (24_662_000 as Weight) - .saturating_add((5_497_000 as Weight).saturating_mul(r as Weight)) - + (26_535_000 as Weight) + .saturating_add((5_450_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (24_647_000 as Weight) - .saturating_add((5_556_000 as Weight).saturating_mul(r as Weight)) - + (26_489_000 as Weight) + .saturating_add((5_410_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (24_646_000 as Weight) - .saturating_add((6_138_000 as Weight).saturating_mul(r as Weight)) - + (26_576_000 as Weight) + .saturating_add((5_976_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (24_649_000 as Weight) - .saturating_add((5_477_000 as Weight).saturating_mul(r as Weight)) - + (26_521_000 as Weight) + .saturating_add((5_465_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (24_655_000 as Weight) - .saturating_add((5_414_000 as Weight).saturating_mul(r as Weight)) - + (26_534_000 as Weight) + .saturating_add((5_375_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (24_619_000 as Weight) - .saturating_add((5_434_000 as Weight).saturating_mul(r as Weight)) - + (26_560_000 as Weight) + .saturating_add((5_284_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (24_654_000 as Weight) - .saturating_add((5_483_000 as Weight).saturating_mul(r as Weight)) - + (26_554_000 as Weight) + .saturating_add((5_358_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (24_690_000 as Weight) - .saturating_add((7_485_000 as Weight).saturating_mul(r as Weight)) - + (26_549_000 as Weight) + .saturating_add((7_402_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (24_652_000 as Weight) - .saturating_add((7_468_000 as Weight).saturating_mul(r as Weight)) - + (26_582_000 as Weight) + .saturating_add((7_266_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (24_667_000 as Weight) - .saturating_add((7_426_000 as Weight).saturating_mul(r as Weight)) - + (26_558_000 as Weight) + .saturating_add((7_293_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (24_693_000 as Weight) - .saturating_add((7_393_000 as Weight).saturating_mul(r as Weight)) - + (26_569_000 as Weight) + .saturating_add((7_278_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (24_675_000 as Weight) - .saturating_add((7_407_000 as Weight).saturating_mul(r as Weight)) - + (26_516_000 as Weight) + .saturating_add((7_334_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (24_697_000 as Weight) - .saturating_add((7_392_000 as Weight).saturating_mul(r as Weight)) - + (26_561_000 as Weight) + .saturating_add((7_283_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (24_646_000 as Weight) - .saturating_add((7_420_000 as Weight).saturating_mul(r as Weight)) - + (26_589_000 as Weight) + .saturating_add((7_244_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (24_683_000 as Weight) - .saturating_add((7_404_000 as Weight).saturating_mul(r as Weight)) - + (26_593_000 as Weight) + .saturating_add((7_318_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (24_685_000 as Weight) - .saturating_add((7_461_000 as Weight).saturating_mul(r as Weight)) - + (26_626_000 as Weight) + .saturating_add((7_348_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (25_147_000 as Weight) - .saturating_add((7_003_000 as Weight).saturating_mul(r as Weight)) - + (26_595_000 as Weight) + .saturating_add((7_330_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (24_705_000 as Weight) - .saturating_add((7_483_000 as Weight).saturating_mul(r as Weight)) - + (26_568_000 as Weight) + .saturating_add((8_657_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (24_675_000 as Weight) - .saturating_add((7_377_000 as Weight).saturating_mul(r as Weight)) - + (27_393_000 as Weight) + .saturating_add((6_743_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (24_680_000 as Weight) - .saturating_add((7_376_000 as Weight).saturating_mul(r as Weight)) - + (26_571_000 as Weight) + .saturating_add((7_329_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (24_660_000 as Weight) - .saturating_add((13_091_000 as Weight).saturating_mul(r as Weight)) - + (26_585_000 as Weight) + .saturating_add((12_977_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (24_643_000 as Weight) - .saturating_add((12_109_000 as Weight).saturating_mul(r as Weight)) - + (26_554_000 as Weight) + .saturating_add((11_955_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (24_615_000 as Weight) - .saturating_add((13_049_000 as Weight).saturating_mul(r as Weight)) - + (26_570_000 as Weight) + .saturating_add((12_903_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (24_696_000 as Weight) - .saturating_add((12_039_000 as Weight).saturating_mul(r as Weight)) - + (26_561_000 as Weight) + .saturating_add((12_112_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (24_683_000 as Weight) - .saturating_add((7_314_000 as Weight).saturating_mul(r as Weight)) - + (26_587_000 as Weight) + .saturating_add((7_411_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (24_657_000 as Weight) - .saturating_add((7_401_000 as Weight).saturating_mul(r as Weight)) - + (26_588_000 as Weight) + .saturating_add((7_479_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (24_661_000 as Weight) - .saturating_add((7_347_000 as Weight).saturating_mul(r as Weight)) - + (26_541_000 as Weight) + .saturating_add((7_386_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (24_644_000 as Weight) - .saturating_add((7_389_000 as Weight).saturating_mul(r as Weight)) - + (26_562_000 as Weight) + .saturating_add((7_263_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (24_643_000 as Weight) - .saturating_add((7_416_000 as Weight).saturating_mul(r as Weight)) - + (26_569_000 as Weight) + .saturating_add((7_353_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (24_634_000 as Weight) - .saturating_add((7_392_000 as Weight).saturating_mul(r as Weight)) - + (26_533_000 as Weight) + .saturating_add((7_342_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (24_618_000 as Weight) - .saturating_add((7_452_000 as Weight).saturating_mul(r as Weight)) - + (26_545_000 as Weight) + .saturating_add((7_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (24_618_000 as Weight) - .saturating_add((7_447_000 as Weight).saturating_mul(r as Weight)) - + (26_535_000 as Weight) + .saturating_add((7_330_000 as Weight).saturating_mul(r as Weight)) } - } // For backwards compatibility and tests impl WeightInfo for () { fn update_schedule() -> Weight { - (33_160_000 as Weight) + (35_214_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) - } fn put_code(n: u32, ) -> Weight { - (5_975_000 as Weight) - .saturating_add((108_953_000 as Weight).saturating_mul(n as Weight)) + (0 as Weight) + .saturating_add((109_242_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) - } - fn instantiate(n: u32, ) -> Weight { - (218_223_000 as Weight) - .saturating_add((1_007_000 as Weight).saturating_mul(n as Weight)) + fn instantiate(n: u32, s: u32, ) -> Weight { + (195_276_000 as Weight) + .saturating_add((35_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((2_244_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } fn call() -> Weight { - (201_492_000 as Weight) + (207_142_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) - } fn claim_surcharge() -> Weight { - (449_203_000 as Weight) + (489_633_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) - } fn seal_caller(r: u32, ) -> Weight { - (136_650_000 as Weight) - .saturating_add((364_640_000 as Weight).saturating_mul(r as Weight)) + (136_550_000 as Weight) + .saturating_add((373_182_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_address(r: u32, ) -> Weight { - (144_167_000 as Weight) - .saturating_add((365_328_000 as Weight).saturating_mul(r as Weight)) + (136_329_000 as Weight) + .saturating_add((373_392_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_gas_left(r: u32, ) -> Weight { - (138_458_000 as Weight) - .saturating_add((361_076_000 as Weight).saturating_mul(r as Weight)) + (111_577_000 as Weight) + .saturating_add((373_536_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_balance(r: u32, ) -> Weight { - (147_909_000 as Weight) - .saturating_add((792_169_000 as Weight).saturating_mul(r as Weight)) + (157_531_000 as Weight) + .saturating_add((810_382_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - } fn seal_value_transferred(r: u32, ) -> Weight { - (148_524_000 as Weight) - .saturating_add((361_842_000 as Weight).saturating_mul(r as Weight)) + (143_801_000 as Weight) + .saturating_add((369_769_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_minimum_balance(r: u32, ) -> Weight { - (139_795_000 as Weight) - .saturating_add((366_013_000 as Weight).saturating_mul(r as Weight)) + (133_546_000 as Weight) + .saturating_add((370_036_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_tombstone_deposit(r: u32, ) -> Weight { - (140_557_000 as Weight) - .saturating_add((362_687_000 as Weight).saturating_mul(r as Weight)) + (138_568_000 as Weight) + .saturating_add((370_322_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_rent_allowance(r: u32, ) -> Weight { - (152_989_000 as Weight) - .saturating_add((836_876_000 as Weight).saturating_mul(r as Weight)) + (144_431_000 as Weight) + .saturating_add((851_810_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_block_number(r: u32, ) -> Weight { - (140_228_000 as Weight) - .saturating_add((360_561_000 as Weight).saturating_mul(r as Weight)) + (133_237_000 as Weight) + .saturating_add((369_156_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_now(r: u32, ) -> Weight { - (148_776_000 as Weight) - .saturating_add((361_712_000 as Weight).saturating_mul(r as Weight)) + (139_700_000 as Weight) + .saturating_add((368_961_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_weight_to_fee(r: u32, ) -> Weight { - (126_903_000 as Weight) - .saturating_add((603_100_000 as Weight).saturating_mul(r as Weight)) + (149_395_000 as Weight) + .saturating_add((625_812_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - } fn seal_gas(r: u32, ) -> Weight { - (125_712_000 as Weight) - .saturating_add((184_450_000 as Weight).saturating_mul(r as Weight)) + (125_777_000 as Weight) + .saturating_add((187_585_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_input(r: u32, ) -> Weight { - (136_175_000 as Weight) - .saturating_add((7_489_000 as Weight).saturating_mul(r as Weight)) + (132_584_000 as Weight) + .saturating_add((7_661_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_input_per_kb(n: u32, ) -> Weight { - (145_434_000 as Weight) - .saturating_add((276_000 as Weight).saturating_mul(n as Weight)) + (143_408_000 as Weight) + .saturating_add((274_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_return(r: u32, ) -> Weight { - (124_788_000 as Weight) - .saturating_add((5_696_000 as Weight).saturating_mul(r as Weight)) + (126_257_000 as Weight) + .saturating_add((5_455_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_return_per_kb(n: u32, ) -> Weight { - (133_483_000 as Weight) - .saturating_add((675_000 as Weight).saturating_mul(n as Weight)) + (133_286_000 as Weight) + .saturating_add((698_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_terminate(r: u32, ) -> Weight { - (135_387_000 as Weight) - .saturating_add((338_395_000 as Weight).saturating_mul(r as Weight)) + (130_607_000 as Weight) + .saturating_add((358_370_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(r as Weight))) } fn seal_restore_to(r: u32, ) -> Weight { - (227_617_000 as Weight) - .saturating_add((132_493_000 as Weight).saturating_mul(r as Weight)) + (233_645_000 as Weight) + .saturating_add((135_355_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(r as Weight))) } fn seal_restore_to_per_delta(d: u32, ) -> Weight { - (15_263_000 as Weight) - .saturating_add((3_732_219_000 as Weight).saturating_mul(d as Weight)) + (74_573_000 as Weight) + .saturating_add((3_768_682_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(d as Weight))) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(d as Weight))) } fn seal_random(r: u32, ) -> Weight { - (236_391_000 as Weight) - .saturating_add((913_452_000 as Weight).saturating_mul(r as Weight)) + (140_286_000 as Weight) + .saturating_add((950_890_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - } fn seal_deposit_event(r: u32, ) -> Weight { - (140_845_000 as Weight) - .saturating_add((1_322_796_000 as Weight).saturating_mul(r as Weight)) + (167_735_000 as Weight) + .saturating_add((1_375_429_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (1_651_556_000 as Weight) - .saturating_add((737_421_000 as Weight).saturating_mul(t as Weight)) - .saturating_add((244_183_000 as Weight).saturating_mul(n as Weight)) + (1_715_857_000 as Weight) + .saturating_add((760_777_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((241_853_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(t as Weight))) } fn seal_set_rent_allowance(r: u32, ) -> Weight { - (151_091_000 as Weight) - .saturating_add((983_375_000 as Weight).saturating_mul(r as Weight)) + (156_911_000 as Weight) + .saturating_add((1_006_139_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) - } fn seal_set_storage(r: u32, ) -> Weight { - (460_478_000 as Weight) - .saturating_add((14_824_033_000 as Weight).saturating_mul(r as Weight)) + (0 as Weight) + .saturating_add((14_938_793_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (2_255_458_000 as Weight) - .saturating_add((204_470_000 as Weight).saturating_mul(n as Weight)) + (2_300_169_000 as Weight) + .saturating_add((204_543_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) - } fn seal_clear_storage(r: u32, ) -> Weight { (0 as Weight) - .saturating_add((5_052_125_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((5_140_241_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } fn seal_get_storage(r: u32, ) -> Weight { - (95_473_000 as Weight) - .saturating_add((1_044_784_000 as Weight).saturating_mul(r as Weight)) + (45_212_000 as Weight) + .saturating_add((1_131_504_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - } fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (860_080_000 as Weight) - .saturating_add((146_913_000 as Weight).saturating_mul(n as Weight)) + (885_531_000 as Weight) + .saturating_add((148_986_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - } fn seal_transfer(r: u32, ) -> Weight { - (107_119_000 as Weight) - .saturating_add((5_993_434_000 as Weight).saturating_mul(r as Weight)) + (92_276_000 as Weight) + .saturating_add((6_216_852_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1002,83 +888,74 @@ impl WeightInfo for () { } fn seal_call(r: u32, ) -> Weight { (0 as Weight) - .saturating_add((10_533_320_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((10_734_719_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - } fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (9_839_633_000 as Weight) - .saturating_add((5_580_035_000 as Weight).saturating_mul(t as Weight)) - .saturating_add((53_716_000 as Weight).saturating_mul(i as Weight)) - .saturating_add((73_668_000 as Weight).saturating_mul(o as Weight)) + (12_735_614_000 as Weight) + .saturating_add((2_870_730_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((52_569_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((73_956_000 as Weight).saturating_mul(o as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes((101 as Weight).saturating_mul(t as Weight))) } fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - .saturating_add((21_856_497_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((22_365_908_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((300 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) .saturating_add(RocksDbWeight::get().writes((200 as Weight).saturating_mul(r as Weight))) } - fn seal_instantiate_per_input_output_kb(i: u32, o: u32, ) -> Weight { - (18_796_671_000 as Weight) - .saturating_add((156_269_000 as Weight).saturating_mul(i as Weight)) - .saturating_add((74_645_000 as Weight).saturating_mul(o as Weight)) + fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { + (18_899_296_000 as Weight) + .saturating_add((53_289_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((76_026_000 as Weight).saturating_mul(o as Weight)) + .saturating_add((281_097_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(207 as Weight)) .saturating_add(RocksDbWeight::get().writes(202 as Weight)) - } fn seal_hash_sha2_256(r: u32, ) -> Weight { - (132_190_000 as Weight) - .saturating_add((319_943_000 as Weight).saturating_mul(r as Weight)) + (136_601_000 as Weight) + .saturating_add((323_373_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (747_208_000 as Weight) - .saturating_add((421_808_000 as Weight).saturating_mul(n as Weight)) + (777_563_000 as Weight) + .saturating_add((423_353_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_hash_keccak_256(r: u32, ) -> Weight { - (139_235_000 as Weight) - .saturating_add((333_792_000 as Weight).saturating_mul(r as Weight)) + (136_771_000 as Weight) + .saturating_add((337_881_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (543_256_000 as Weight) - .saturating_add((334_383_000 as Weight).saturating_mul(n as Weight)) + (337_906_000 as Weight) + .saturating_add((336_778_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_hash_blake2_256(r: u32, ) -> Weight { - (142_704_000 as Weight) - .saturating_add((305_513_000 as Weight).saturating_mul(r as Weight)) + (131_040_000 as Weight) + .saturating_add((312_992_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (592_813_000 as Weight) - .saturating_add((151_270_000 as Weight).saturating_mul(n as Weight)) + (693_415_000 as Weight) + .saturating_add((152_745_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_hash_blake2_128(r: u32, ) -> Weight { - (139_921_000 as Weight) - .saturating_add((304_746_000 as Weight).saturating_mul(r as Weight)) + (135_654_000 as Weight) + .saturating_add((311_271_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (544_524_000 as Weight) - .saturating_add((151_549_000 as Weight).saturating_mul(n as Weight)) + (839_521_000 as Weight) + .saturating_add((153_146_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - } // TODO: Calculate the correct weight fn seal_curve_altbn_128_add(r: u32) -> Weight { @@ -1153,259 +1030,207 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(4 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (24_652_000 as Weight) - .saturating_add((3_306_000 as Weight).saturating_mul(r as Weight)) - + (26_679_000 as Weight) + .saturating_add((3_155_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (27_131_000 as Weight) - .saturating_add((162_220_000 as Weight).saturating_mul(r as Weight)) - + (28_920_000 as Weight) + .saturating_add((159_343_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (27_086_000 as Weight) - .saturating_add((230_977_000 as Weight).saturating_mul(r as Weight)) - + (28_928_000 as Weight) + .saturating_add((227_286_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (24_656_000 as Weight) - .saturating_add((12_570_000 as Weight).saturating_mul(r as Weight)) - + (26_591_000 as Weight) + .saturating_add((12_591_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (24_643_000 as Weight) - .saturating_add((12_442_000 as Weight).saturating_mul(r as Weight)) - + (26_597_000 as Weight) + .saturating_add((12_258_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (24_589_000 as Weight) - .saturating_add((6_237_000 as Weight).saturating_mul(r as Weight)) - + (26_586_000 as Weight) + .saturating_add((5_811_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (24_650_000 as Weight) - .saturating_add((14_393_000 as Weight).saturating_mul(r as Weight)) - + (26_581_000 as Weight) + .saturating_add((14_058_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (24_689_000 as Weight) - .saturating_add((15_706_000 as Weight).saturating_mul(r as Weight)) - + (26_615_000 as Weight) + .saturating_add((15_687_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (40_129_000 as Weight) - .saturating_add((83_000 as Weight).saturating_mul(e as Weight)) - + (40_963_000 as Weight) + .saturating_add((92_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (24_904_000 as Weight) - .saturating_add((96_429_000 as Weight).saturating_mul(r as Weight)) - + (26_880_000 as Weight) + .saturating_add((97_523_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (32_540_000 as Weight) - .saturating_add((201_773_000 as Weight).saturating_mul(r as Weight)) - + (34_628_000 as Weight) + .saturating_add((201_913_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (248_700_000 as Weight) - .saturating_add((3_705_000 as Weight).saturating_mul(p as Weight)) - + (255_763_000 as Weight) + .saturating_add((3_612_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (42_081_000 as Weight) - .saturating_add((3_548_000 as Weight).saturating_mul(r as Weight)) - + (45_954_000 as Weight) + .saturating_add((3_439_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (42_128_000 as Weight) - .saturating_add((3_678_000 as Weight).saturating_mul(r as Weight)) - + (45_952_000 as Weight) + .saturating_add((3_601_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (42_073_000 as Weight) - .saturating_add((5_212_000 as Weight).saturating_mul(r as Weight)) - + (45_883_000 as Weight) + .saturating_add((5_203_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (28_182_000 as Weight) - .saturating_add((8_180_000 as Weight).saturating_mul(r as Weight)) - + (29_895_000 as Weight) + .saturating_add((8_221_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (28_060_000 as Weight) - .saturating_add((12_081_000 as Weight).saturating_mul(r as Weight)) - + (29_916_000 as Weight) + .saturating_add((12_036_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (27_113_000 as Weight) - .saturating_add((3_802_000 as Weight).saturating_mul(r as Weight)) - + (28_878_000 as Weight) + .saturating_add((3_794_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (25_521_000 as Weight) - .saturating_add((2_288_295_000 as Weight).saturating_mul(r as Weight)) - + (27_351_000 as Weight) + .saturating_add((2_302_301_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (24_662_000 as Weight) - .saturating_add((5_497_000 as Weight).saturating_mul(r as Weight)) - + (26_535_000 as Weight) + .saturating_add((5_450_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (24_647_000 as Weight) - .saturating_add((5_556_000 as Weight).saturating_mul(r as Weight)) - + (26_489_000 as Weight) + .saturating_add((5_410_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (24_646_000 as Weight) - .saturating_add((6_138_000 as Weight).saturating_mul(r as Weight)) - + (26_576_000 as Weight) + .saturating_add((5_976_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (24_649_000 as Weight) - .saturating_add((5_477_000 as Weight).saturating_mul(r as Weight)) - + (26_521_000 as Weight) + .saturating_add((5_465_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (24_655_000 as Weight) - .saturating_add((5_414_000 as Weight).saturating_mul(r as Weight)) - + (26_534_000 as Weight) + .saturating_add((5_375_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (24_619_000 as Weight) - .saturating_add((5_434_000 as Weight).saturating_mul(r as Weight)) - + (26_560_000 as Weight) + .saturating_add((5_284_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (24_654_000 as Weight) - .saturating_add((5_483_000 as Weight).saturating_mul(r as Weight)) - + (26_554_000 as Weight) + .saturating_add((5_358_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (24_690_000 as Weight) - .saturating_add((7_485_000 as Weight).saturating_mul(r as Weight)) - + (26_549_000 as Weight) + .saturating_add((7_402_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (24_652_000 as Weight) - .saturating_add((7_468_000 as Weight).saturating_mul(r as Weight)) - + (26_582_000 as Weight) + .saturating_add((7_266_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (24_667_000 as Weight) - .saturating_add((7_426_000 as Weight).saturating_mul(r as Weight)) - + (26_558_000 as Weight) + .saturating_add((7_293_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (24_693_000 as Weight) - .saturating_add((7_393_000 as Weight).saturating_mul(r as Weight)) - + (26_569_000 as Weight) + .saturating_add((7_278_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (24_675_000 as Weight) - .saturating_add((7_407_000 as Weight).saturating_mul(r as Weight)) - + (26_516_000 as Weight) + .saturating_add((7_334_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (24_697_000 as Weight) - .saturating_add((7_392_000 as Weight).saturating_mul(r as Weight)) - + (26_561_000 as Weight) + .saturating_add((7_283_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (24_646_000 as Weight) - .saturating_add((7_420_000 as Weight).saturating_mul(r as Weight)) - + (26_589_000 as Weight) + .saturating_add((7_244_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (24_683_000 as Weight) - .saturating_add((7_404_000 as Weight).saturating_mul(r as Weight)) - + (26_593_000 as Weight) + .saturating_add((7_318_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (24_685_000 as Weight) - .saturating_add((7_461_000 as Weight).saturating_mul(r as Weight)) - + (26_626_000 as Weight) + .saturating_add((7_348_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (25_147_000 as Weight) - .saturating_add((7_003_000 as Weight).saturating_mul(r as Weight)) - + (26_595_000 as Weight) + .saturating_add((7_330_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (24_705_000 as Weight) - .saturating_add((7_483_000 as Weight).saturating_mul(r as Weight)) - + (26_568_000 as Weight) + .saturating_add((8_657_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (24_675_000 as Weight) - .saturating_add((7_377_000 as Weight).saturating_mul(r as Weight)) - + (27_393_000 as Weight) + .saturating_add((6_743_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (24_680_000 as Weight) - .saturating_add((7_376_000 as Weight).saturating_mul(r as Weight)) - + (26_571_000 as Weight) + .saturating_add((7_329_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (24_660_000 as Weight) - .saturating_add((13_091_000 as Weight).saturating_mul(r as Weight)) - + (26_585_000 as Weight) + .saturating_add((12_977_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (24_643_000 as Weight) - .saturating_add((12_109_000 as Weight).saturating_mul(r as Weight)) - + (26_554_000 as Weight) + .saturating_add((11_955_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (24_615_000 as Weight) - .saturating_add((13_049_000 as Weight).saturating_mul(r as Weight)) - + (26_570_000 as Weight) + .saturating_add((12_903_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (24_696_000 as Weight) - .saturating_add((12_039_000 as Weight).saturating_mul(r as Weight)) - + (26_561_000 as Weight) + .saturating_add((12_112_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (24_683_000 as Weight) - .saturating_add((7_314_000 as Weight).saturating_mul(r as Weight)) - + (26_587_000 as Weight) + .saturating_add((7_411_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (24_657_000 as Weight) - .saturating_add((7_401_000 as Weight).saturating_mul(r as Weight)) - + (26_588_000 as Weight) + .saturating_add((7_479_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (24_661_000 as Weight) - .saturating_add((7_347_000 as Weight).saturating_mul(r as Weight)) - + (26_541_000 as Weight) + .saturating_add((7_386_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (24_644_000 as Weight) - .saturating_add((7_389_000 as Weight).saturating_mul(r as Weight)) - + (26_562_000 as Weight) + .saturating_add((7_263_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (24_643_000 as Weight) - .saturating_add((7_416_000 as Weight).saturating_mul(r as Weight)) - + (26_569_000 as Weight) + .saturating_add((7_353_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (24_634_000 as Weight) - .saturating_add((7_392_000 as Weight).saturating_mul(r as Weight)) - + (26_533_000 as Weight) + .saturating_add((7_342_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (24_618_000 as Weight) - .saturating_add((7_452_000 as Weight).saturating_mul(r as Weight)) - + (26_545_000 as Weight) + .saturating_add((7_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (24_618_000 as Weight) - .saturating_add((7_447_000 as Weight).saturating_mul(r as Weight)) - + (26_535_000 as Weight) + .saturating_add((7_330_000 as Weight).saturating_mul(r as Weight)) } - } diff --git a/frame/democracy/src/tests.rs b/frame/democracy/src/tests.rs index bcc7099bb34a4..25209901109fa 100644 --- a/frame/democracy/src/tests.rs +++ b/frame/democracy/src/tests.rs @@ -18,7 +18,6 @@ //! The crate's tests. use super::*; -use std::cell::RefCell; use codec::Encode; use frame_support::{ impl_outer_origin, impl_outer_dispatch, assert_noop, assert_ok, parameter_types, @@ -154,6 +153,8 @@ parameter_types! { pub const CooloffPeriod: u64 = 2; pub const MaxVotes: u32 = 100; pub const MaxProposals: u32 = MAX_PROPOSALS; + pub static PreimageByteDeposit: u64 = 0; + pub static InstantAllowed: bool = false; } ord_parameter_types! { pub const One: u64 = 1; @@ -171,18 +172,7 @@ impl Contains for OneToFive { #[cfg(feature = "runtime-benchmarks")] fn add(_m: &u64) {} } -thread_local! { - static PREIMAGE_BYTE_DEPOSIT: RefCell = RefCell::new(0); - static INSTANT_ALLOWED: RefCell = RefCell::new(false); -} -pub struct PreimageByteDeposit; -impl Get for PreimageByteDeposit { - fn get() -> u64 { PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow()) } -} -pub struct InstantAllowed; -impl Get for InstantAllowed { - fn get() -> bool { INSTANT_ALLOWED.with(|v| *v.borrow()) } -} + impl super::Trait for Test { type Proposal = Call; type Event = Event; diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index cf3864f2e3f92..8279f9cf11f16 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -682,6 +682,10 @@ decl_event!( /// A \[member\] has been removed. This should always be followed by either `NewTerm` or /// `EmptyTerm`. MemberKicked(AccountId), + /// A candidate was slashed due to failing to obtain a seat as member or runner-up + CandidateSlashed(AccountId, Balance), + /// A seat holder (member or runner-up) was slashed due to failing to retaining their position. + SeatHolderSlashed(AccountId, Balance), /// A \[member\] has renounced their candidacy. MemberRenounced(AccountId), /// A voter was reported with the the report being successful or not. @@ -995,6 +999,7 @@ impl Module { new_runners_up_ids_sorted.binary_search(&c).is_err() { let (imbalance, _) = T::Currency::slash_reserved(&c, T::CandidacyBond::get()); + Self::deposit_event(RawEvent::CandidateSlashed(c, T::CandidacyBond::get())); T::LoserCandidate::on_unbalanced(imbalance); } }); @@ -1002,6 +1007,7 @@ impl Module { // Burn outgoing bonds to_burn_bond.into_iter().for_each(|x| { let (imbalance, _) = T::Currency::slash_reserved(&x, T::CandidacyBond::get()); + Self::deposit_event(RawEvent::SeatHolderSlashed(x, T::CandidacyBond::get())); T::LoserCandidate::on_unbalanced(imbalance); }); @@ -1052,7 +1058,6 @@ impl ContainsLengthBound for Module { #[cfg(test)] mod tests { use super::*; - use std::cell::RefCell; use frame_support::{assert_ok, assert_noop, assert_err_with_weight, parameter_types, weights::Weight, }; @@ -1117,36 +1122,13 @@ mod tests { pub const CandidacyBond: u64 = 3; } - thread_local! { - static VOTING_BOND: RefCell = RefCell::new(2); - static DESIRED_MEMBERS: RefCell = RefCell::new(2); - static DESIRED_RUNNERS_UP: RefCell = RefCell::new(2); - static TERM_DURATION: RefCell = RefCell::new(5); - } - - pub struct VotingBond; - impl Get for VotingBond { - fn get() -> u64 { VOTING_BOND.with(|v| *v.borrow()) } - } - - pub struct DesiredMembers; - impl Get for DesiredMembers { - fn get() -> u32 { DESIRED_MEMBERS.with(|v| *v.borrow()) } - } - - pub struct DesiredRunnersUp; - impl Get for DesiredRunnersUp { - fn get() -> u32 { DESIRED_RUNNERS_UP.with(|v| *v.borrow()) } - } - - pub struct TermDuration; - impl Get for TermDuration { - fn get() -> u64 { TERM_DURATION.with(|v| *v.borrow()) } - } - - thread_local! { - pub static MEMBERS: RefCell> = RefCell::new(vec![]); - pub static PRIME: RefCell> = RefCell::new(None); + frame_support::parameter_types! { + pub static VotingBond: u64 = 2; + pub static DesiredMembers: u32 = 2; + pub static DesiredRunnersUp: u32 = 2; + pub static TermDuration: u64 = 5; + pub static Members: Vec = vec![]; + pub static Prime: Option = None; } pub struct TestChangeMembers; diff --git a/frame/elections/src/mock.rs b/frame/elections/src/mock.rs index deec77da7b837..0d57089af5ef8 100644 --- a/frame/elections/src/mock.rs +++ b/frame/elections/src/mock.rs @@ -19,10 +19,9 @@ #![cfg(test)] -use std::cell::RefCell; use frame_support::{ StorageValue, StorageMap, parameter_types, assert_ok, - traits::{Get, ChangeMembers, Currency, LockIdentifier}, + traits::{ChangeMembers, Currency, LockIdentifier}, weights::Weight, }; use sp_core::H256; @@ -85,34 +84,11 @@ parameter_types! { pub const InactiveGracePeriod: u32 = 1; pub const VotingPeriod: u64 = 4; pub const MinimumVotingLock: u64 = 5; -} - -thread_local! { - static VOTER_BOND: RefCell = RefCell::new(0); - static VOTING_FEE: RefCell = RefCell::new(0); - static PRESENT_SLASH_PER_VOTER: RefCell = RefCell::new(0); - static DECAY_RATIO: RefCell = RefCell::new(0); - static MEMBERS: RefCell> = RefCell::new(vec![]); -} - -pub struct VotingBond; -impl Get for VotingBond { - fn get() -> u64 { VOTER_BOND.with(|v| *v.borrow()) } -} - -pub struct VotingFee; -impl Get for VotingFee { - fn get() -> u64 { VOTING_FEE.with(|v| *v.borrow()) } -} - -pub struct PresentSlashPerVoter; -impl Get for PresentSlashPerVoter { - fn get() -> u64 { PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow()) } -} - -pub struct DecayRatio; -impl Get for DecayRatio { - fn get() -> u32 { DECAY_RATIO.with(|v| *v.borrow()) } + pub static VotingBond: u64 = 0; + pub static VotingFee: u64 = 0; + pub static PresentSlashPerVoter: u64 = 0; + pub static DecayRatio: u32 = 0; + pub static Members: Vec = vec![]; } pub struct TestChangeMembers; @@ -175,7 +151,7 @@ pub struct ExtBuilder { decay_ratio: u32, desired_seats: u32, voting_fee: u64, - voter_bond: u64, + voting_bond: u64, bad_presentation_punishment: u64, } @@ -186,7 +162,7 @@ impl Default for ExtBuilder { decay_ratio: 24, desired_seats: 2, voting_fee: 0, - voter_bond: 0, + voting_bond: 0, bad_presentation_punishment: 1, } } @@ -209,8 +185,8 @@ impl ExtBuilder { self.bad_presentation_punishment = fee; self } - pub fn voter_bond(mut self, fee: u64) -> Self { - self.voter_bond = fee; + pub fn voting_bond(mut self, fee: u64) -> Self { + self.voting_bond = fee; self } pub fn desired_seats(mut self, seats: u32) -> Self { @@ -218,7 +194,7 @@ impl ExtBuilder { self } pub fn build(self) -> sp_io::TestExternalities { - VOTER_BOND.with(|v| *v.borrow_mut() = self.voter_bond); + VOTING_BOND.with(|v| *v.borrow_mut() = self.voting_bond); VOTING_FEE.with(|v| *v.borrow_mut() = self.voting_fee); PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow_mut() = self.bad_presentation_punishment); DECAY_RATIO.with(|v| *v.borrow_mut() = self.decay_ratio); diff --git a/frame/elections/src/tests.rs b/frame/elections/src/tests.rs index 92f6e11252b05..d3579ca337436 100644 --- a/frame/elections/src/tests.rs +++ b/frame/elections/src/tests.rs @@ -298,7 +298,7 @@ fn voting_initial_set_approvals_ignores_voter_index() { } #[test] fn voting_bad_approval_index_slashes_voters_and_bond_reduces_stake() { - ExtBuilder::default().voting_fee(5).voter_bond(2).build().execute_with(|| { + ExtBuilder::default().voting_fee(5).voting_bond(2).build().execute_with(|| { assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); (1..=63).for_each(|i| vote(i, 0)); @@ -365,7 +365,7 @@ fn voting_cannot_lock_less_than_limit() { #[test] fn voting_locking_more_than_total_balance_is_moot() { - ExtBuilder::default().voter_bond(2).build().execute_with(|| { + ExtBuilder::default().voting_bond(2).build().execute_with(|| { assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); assert_eq!(balances(&3), (30, 0)); @@ -381,7 +381,7 @@ fn voting_locking_more_than_total_balance_is_moot() { #[test] fn voting_locking_stake_and_reserving_bond_works() { - ExtBuilder::default().voter_bond(2).build().execute_with(|| { + ExtBuilder::default().voting_bond(2).build().execute_with(|| { assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); assert_eq!(balances(&2), (20, 0)); @@ -558,7 +558,7 @@ fn retracting_inactive_voter_should_work() { #[test] fn retracting_inactive_voter_with_other_candidates_in_slots_should_work() { - ExtBuilder::default().voter_bond(2).build().execute_with(|| { + ExtBuilder::default().voting_bond(2).build().execute_with(|| { System::set_block_number(4); assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); @@ -1107,7 +1107,7 @@ fn election_present_when_presenter_is_poor_should_not_work() { let test_present = |p| { ExtBuilder::default() .voting_fee(5) - .voter_bond(2) + .voting_bond(2) .bad_presentation_punishment(p) .build() .execute_with(|| { @@ -1507,7 +1507,7 @@ fn pot_winning_resets_accumulated_pot() { #[test] fn pot_resubmitting_approvals_stores_pot() { ExtBuilder::default() - .voter_bond(0) + .voting_bond(0) .voting_fee(0) .balance_factor(10) .build() diff --git a/frame/evm/Cargo.toml b/frame/evm/Cargo.toml deleted file mode 100644 index a228dfb566be2..0000000000000 --- a/frame/evm/Cargo.toml +++ /dev/null @@ -1,51 +0,0 @@ -[package] -name = "pallet-evm" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "Apache-2.0" -homepage = "https://substrate.dev" -repository = "https://github.com/paritytech/substrate/" -description = "FRAME EVM contracts pallet" -readme = "README.md" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } -frame-support = { version = "2.0.0", default-features = false, path = "../support" } -frame-system = { version = "2.0.0", default-features = false, path = "../system" } -pallet-timestamp = { version = "2.0.0", default-features = false, path = "../timestamp" } -pallet-balances = { version = "2.0.0", default-features = false, path = "../balances" } -sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } -primitive-types = { version = "0.7.0", default-features = false, features = ["rlp", "byteorder"] } -rlp = { version = "0.4", default-features = false } -evm = { version = "0.17", default-features = false } -sha3 = { version = "0.8", default-features = false } -impl-trait-for-tuples = "0.1" -ripemd160 = { version = "0.9", default-features = false } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "sp-core/std", - "sp-runtime/std", - "frame-support/std", - "frame-system/std", - "pallet-balances/std", - "sp-io/std", - "sp-std/std", - "sha3/std", - "rlp/std", - "primitive-types/std", - "evm/std", - "pallet-timestamp/std", - "ripemd160/std", -] diff --git a/frame/evm/README.md b/frame/evm/README.md deleted file mode 100644 index 499a0761cfa9d..0000000000000 --- a/frame/evm/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# EVM Module - -The EVM module allows unmodified EVM code to be executed in a Substrate-based blockchain. -- [`evm::Trait`](https://docs.rs/pallet-evm/2.0.0/pallet_evm/trait.Trait.html) - -## EVM Engine - -The EVM module uses [`SputnikVM`](https://github.com/rust-blockchain/evm) as the underlying EVM engine. The engine is overhauled so that it's [`modular`](https://github.com/corepaper/evm). - -## Execution Lifecycle - -There are a separate set of accounts managed by the EVM module. Substrate based accounts can call the EVM Module to deposit or withdraw balance from the Substrate base-currency into a different balance managed and used by the EVM module. Once a user has populated their balance, they can create and call smart contracts using this module. - -There's one-to-one mapping from Substrate accounts and EVM external accounts that is defined by a conversion function. - -## EVM Module vs Ethereum Network - -The EVM module should be able to produce nearly identical results compared to the Ethereum mainnet, including gas cost and balance changes. - -Observable differences include: - -- The available length of block hashes may not be 256 depending on the configuration of the System module in the Substrate runtime. -- Difficulty and coinbase, which do not make sense in this module and is currently hard coded to zero. - -We currently do not aim to make unobservable behaviors, such as state root, to be the same. We also don't aim to follow the exact same transaction / receipt format. However, given one Ethereum transaction and one Substrate account's private key, one should be able to convert any Ethereum transaction into a transaction compatible with this module. - -The gas configurations are configurable. Right now, a pre-defined Istanbul hard fork configuration option is provided. - -License: Apache-2.0 \ No newline at end of file diff --git a/frame/evm/src/backend.rs b/frame/evm/src/backend.rs deleted file mode 100644 index b625c0c548026..0000000000000 --- a/frame/evm/src/backend.rs +++ /dev/null @@ -1,216 +0,0 @@ -use sp_std::marker::PhantomData; -use sp_std::vec::Vec; -#[cfg(feature = "std")] -use serde::{Serialize, Deserialize}; -use codec::{Encode, Decode}; -use sp_core::{U256, H256, H160}; -use sp_runtime::traits::UniqueSaturatedInto; -use frame_support::traits::Get; -use frame_support::{debug, storage::{StorageMap, StorageDoubleMap}}; -use sha3::{Keccak256, Digest}; -use evm::backend::{Backend as BackendT, ApplyBackend, Apply}; -use crate::{Trait, AccountStorages, AccountCodes, Module, Event}; - -#[derive(Clone, Eq, PartialEq, Encode, Decode, Default)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -/// Ethereum account nonce, balance and code. Used by storage. -pub struct Account { - /// Account nonce. - pub nonce: U256, - /// Account balance. - pub balance: U256, -} - -#[derive(Clone, Eq, PartialEq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -/// Ethereum log. Used for `deposit_event`. -pub struct Log { - /// Source address of the log. - pub address: H160, - /// Topics of the log. - pub topics: Vec, - /// Byte array data of the log. - pub data: Vec, -} - -#[derive(Clone, Eq, PartialEq, Encode, Decode, Default)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -/// External input from the transaction. -pub struct Vicinity { - /// Current transaction gas price. - pub gas_price: U256, - /// Origin of the transaction. - pub origin: H160, -} - -/// Substrate backend for EVM. -pub struct Backend<'vicinity, T> { - vicinity: &'vicinity Vicinity, - _marker: PhantomData, -} - -impl<'vicinity, T> Backend<'vicinity, T> { - /// Create a new backend with given vicinity. - pub fn new(vicinity: &'vicinity Vicinity) -> Self { - Self { vicinity, _marker: PhantomData } - } -} - -impl<'vicinity, T: Trait> BackendT for Backend<'vicinity, T> { - fn gas_price(&self) -> U256 { self.vicinity.gas_price } - fn origin(&self) -> H160 { self.vicinity.origin } - - fn block_hash(&self, number: U256) -> H256 { - if number > U256::from(u32::max_value()) { - H256::default() - } else { - let number = T::BlockNumber::from(number.as_u32()); - H256::from_slice(frame_system::Module::::block_hash(number).as_ref()) - } - } - - fn block_number(&self) -> U256 { - let number: u128 = frame_system::Module::::block_number().unique_saturated_into(); - U256::from(number) - } - - fn block_coinbase(&self) -> H160 { - H160::default() - } - - fn block_timestamp(&self) -> U256 { - let now: u128 = pallet_timestamp::Module::::get().unique_saturated_into(); - U256::from(now / 1000) - } - - fn block_difficulty(&self) -> U256 { - U256::zero() - } - - fn block_gas_limit(&self) -> U256 { - U256::zero() - } - - fn chain_id(&self) -> U256 { - U256::from(T::ChainId::get()) - } - - fn exists(&self, _address: H160) -> bool { - true - } - - fn basic(&self, address: H160) -> evm::backend::Basic { - let account = Module::::account_basic(&address); - - evm::backend::Basic { - balance: account.balance, - nonce: account.nonce, - } - } - - fn code_size(&self, address: H160) -> usize { - AccountCodes::decode_len(&address).unwrap_or(0) - } - - fn code_hash(&self, address: H160) -> H256 { - H256::from_slice(Keccak256::digest(&AccountCodes::get(&address)).as_slice()) - } - - fn code(&self, address: H160) -> Vec { - AccountCodes::get(&address) - } - - fn storage(&self, address: H160, index: H256) -> H256 { - AccountStorages::get(address, index) - } -} - -impl<'vicinity, T: Trait> ApplyBackend for Backend<'vicinity, T> { - fn apply( - &mut self, - values: A, - logs: L, - delete_empty: bool, - ) where - A: IntoIterator>, - I: IntoIterator, - L: IntoIterator, - { - for apply in values { - match apply { - Apply::Modify { - address, basic, code, storage, reset_storage, - } => { - Module::::mutate_account_basic(&address, Account { - nonce: basic.nonce, - balance: basic.balance, - }); - - if let Some(code) = code { - debug::debug!( - target: "evm", - "Inserting code ({} bytes) at {:?}", - code.len(), - address - ); - AccountCodes::insert(address, code); - } - - if reset_storage { - AccountStorages::remove_prefix(address); - } - - for (index, value) in storage { - if value == H256::default() { - debug::debug!( - target: "evm", - "Removing storage for {:?} [index: {:?}]", - address, - index - ); - AccountStorages::remove(address, index); - } else { - debug::debug!( - target: "evm", - "Updating storage for {:?} [index: {:?}, value: {:?}]", - address, - index, - value - ); - AccountStorages::insert(address, index, value); - } - } - - if delete_empty { - Module::::remove_account_if_empty(&address); - } - }, - Apply::Delete { address } => { - debug::debug!( - target: "evm", - "Deleting account at {:?}", - address - ); - Module::::remove_account(&address) - }, - } - } - - for log in logs { - debug::trace!( - target: "evm", - "Inserting log for {:?}, topics ({}) {:?}, data ({}): {:?}]", - log.address, - log.topics.len(), - log.topics, - log.data.len(), - log.data - ); - Module::::deposit_event(Event::::Log(Log { - address: log.address, - topics: log.topics, - data: log.data, - })); - } - } -} diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs deleted file mode 100644 index e7812a55482fd..0000000000000 --- a/frame/evm/src/lib.rs +++ /dev/null @@ -1,678 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! # EVM Module -//! -//! The EVM module allows unmodified EVM code to be executed in a Substrate-based blockchain. -//! - [`evm::Trait`] -//! -//! ## EVM Engine -//! -//! The EVM module uses [`SputnikVM`](https://github.com/rust-blockchain/evm) as the underlying EVM engine. -//! The engine is overhauled so that it's [`modular`](https://github.com/corepaper/evm). -//! -//! ## Execution Lifecycle -//! -//! There are a separate set of accounts managed by the EVM module. Substrate based accounts can call the EVM Module -//! to deposit or withdraw balance from the Substrate base-currency into a different balance managed and used by -//! the EVM module. Once a user has populated their balance, they can create and call smart contracts using this module. -//! -//! There's one-to-one mapping from Substrate accounts and EVM external accounts that is defined by a conversion function. -//! -//! ## EVM Module vs Ethereum Network -//! -//! The EVM module should be able to produce nearly identical results compared to the Ethereum mainnet, -//! including gas cost and balance changes. -//! -//! Observable differences include: -//! -//! - The available length of block hashes may not be 256 depending on the configuration of the System module -//! in the Substrate runtime. -//! - Difficulty and coinbase, which do not make sense in this module and is currently hard coded to zero. -//! -//! We currently do not aim to make unobservable behaviors, such as state root, to be the same. We also don't aim to follow -//! the exact same transaction / receipt format. However, given one Ethereum transaction and one Substrate account's -//! private key, one should be able to convert any Ethereum transaction into a transaction compatible with this module. -//! -//! The gas configurations are configurable. Right now, a pre-defined Istanbul hard fork configuration option is provided. - -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] - -mod backend; -mod tests; -pub mod precompiles; - -pub use crate::precompiles::{Precompile, Precompiles}; -pub use crate::backend::{Account, Log, Vicinity, Backend}; - -use sp_std::vec::Vec; -#[cfg(feature = "std")] -use codec::{Encode, Decode}; -#[cfg(feature = "std")] -use serde::{Serialize, Deserialize}; -use frame_support::{debug, ensure, decl_module, decl_storage, decl_event, decl_error}; -use frame_support::weights::{Weight, Pays}; -use frame_support::traits::{Currency, ExistenceRequirement, Get}; -use frame_support::dispatch::DispatchResultWithPostInfo; -use frame_system::RawOrigin; -use sp_core::{U256, H256, H160, Hasher}; -use sp_runtime::{AccountId32, traits::{UniqueSaturatedInto, SaturatedConversion, BadOrigin}}; -use sha3::{Digest, Keccak256}; -pub use evm::{ExitReason, ExitSucceed, ExitError, ExitRevert, ExitFatal}; -use evm::Config; -use evm::executor::StackExecutor; -use evm::backend::ApplyBackend; - -/// Type alias for currency balance. -pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - -/// Trait that outputs the current transaction gas price. -pub trait FeeCalculator { - /// Return the minimal required gas price. - fn min_gas_price() -> U256; -} - -impl FeeCalculator for () { - fn min_gas_price() -> U256 { U256::zero() } -} - -pub trait EnsureAddressOrigin { - /// Success return type. - type Success; - - /// Perform the origin check. - fn ensure_address_origin( - address: &H160, - origin: OuterOrigin, - ) -> Result { - Self::try_address_origin(address, origin).map_err(|_| BadOrigin) - } - - /// Try with origin. - fn try_address_origin( - address: &H160, - origin: OuterOrigin, - ) -> Result; -} - -/// Ensure that the EVM address is the same as the Substrate address. This only works if the account -/// ID is `H160`. -pub struct EnsureAddressSame; - -impl EnsureAddressOrigin for EnsureAddressSame where - OuterOrigin: Into, OuterOrigin>> + From>, -{ - type Success = H160; - - fn try_address_origin( - address: &H160, - origin: OuterOrigin, - ) -> Result { - origin.into().and_then(|o| match o { - RawOrigin::Signed(who) if &who == address => Ok(who), - r => Err(OuterOrigin::from(r)) - }) - } -} - -/// Ensure that the origin is root. -pub struct EnsureAddressRoot(sp_std::marker::PhantomData); - -impl EnsureAddressOrigin for EnsureAddressRoot where - OuterOrigin: Into, OuterOrigin>> + From>, -{ - type Success = (); - - fn try_address_origin( - _address: &H160, - origin: OuterOrigin, - ) -> Result<(), OuterOrigin> { - origin.into().and_then(|o| match o { - RawOrigin::Root => Ok(()), - r => Err(OuterOrigin::from(r)), - }) - } -} - -/// Ensure that the origin never happens. -pub struct EnsureAddressNever(sp_std::marker::PhantomData); - -impl EnsureAddressOrigin for EnsureAddressNever { - type Success = AccountId; - - fn try_address_origin( - _address: &H160, - origin: OuterOrigin, - ) -> Result { - Err(origin) - } -} - -/// Ensure that the address is truncated hash of the origin. Only works if the account id is -/// `AccountId32`. -pub struct EnsureAddressTruncated; - -impl EnsureAddressOrigin for EnsureAddressTruncated where - OuterOrigin: Into, OuterOrigin>> + From>, -{ - type Success = AccountId32; - - fn try_address_origin( - address: &H160, - origin: OuterOrigin, - ) -> Result { - origin.into().and_then(|o| match o { - RawOrigin::Signed(who) - if AsRef::<[u8; 32]>::as_ref(&who)[0..20] == address[0..20] => Ok(who), - r => Err(OuterOrigin::from(r)) - }) - } -} - -pub trait AddressMapping { - fn into_account_id(address: H160) -> A; -} - -/// Identity address mapping. -pub struct IdentityAddressMapping; - -impl AddressMapping for IdentityAddressMapping { - fn into_account_id(address: H160) -> H160 { address } -} - -/// Hashed address mapping. -pub struct HashedAddressMapping(sp_std::marker::PhantomData); - -impl> AddressMapping for HashedAddressMapping { - fn into_account_id(address: H160) -> AccountId32 { - let mut data = [0u8; 24]; - data[0..4].copy_from_slice(b"evm:"); - data[4..24].copy_from_slice(&address[..]); - let hash = H::hash(&data); - - AccountId32::from(Into::<[u8; 32]>::into(hash)) - } -} - -/// Substrate system chain ID. -pub struct SystemChainId; - -impl Get for SystemChainId { - fn get() -> u64 { - sp_io::misc::chain_id() - } -} - -static ISTANBUL_CONFIG: Config = Config::istanbul(); - -/// EVM module trait -pub trait Trait: frame_system::Trait + pallet_timestamp::Trait { - /// Calculator for current gas price. - type FeeCalculator: FeeCalculator; - - /// Allow the origin to call on behalf of given address. - type CallOrigin: EnsureAddressOrigin; - /// Allow the origin to withdraw on behalf of given address. - type WithdrawOrigin: EnsureAddressOrigin; - - /// Mapping from address to account id. - type AddressMapping: AddressMapping; - /// Currency type for withdraw and balance storage. - type Currency: Currency; - - /// The overarching event type. - type Event: From> + Into<::Event>; - /// Precompiles associated with this EVM engine. - type Precompiles: Precompiles; - /// Chain ID of EVM. - type ChainId: Get; - - /// EVM config used in the module. - fn config() -> &'static Config { - &ISTANBUL_CONFIG - } -} - -#[cfg(feature = "std")] -#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, Serialize, Deserialize)] -/// Account definition used for genesis block construction. -pub struct GenesisAccount { - /// Account nonce. - pub nonce: U256, - /// Account balance. - pub balance: U256, - /// Full account storage. - pub storage: std::collections::BTreeMap, - /// Account code. - pub code: Vec, -} - -decl_storage! { - trait Store for Module as EVM { - AccountCodes get(fn account_codes): map hasher(blake2_128_concat) H160 => Vec; - AccountStorages get(fn account_storages): - double_map hasher(blake2_128_concat) H160, hasher(blake2_128_concat) H256 => H256; - } - - add_extra_genesis { - config(accounts): std::collections::BTreeMap; - build(|config: &GenesisConfig| { - for (address, account) in &config.accounts { - Module::::mutate_account_basic(&address, Account { - balance: account.balance, - nonce: account.nonce, - }); - AccountCodes::insert(address, &account.code); - - for (index, value) in &account.storage { - AccountStorages::insert(address, index, value); - } - } - }); - } -} - -decl_event! { - /// EVM events - pub enum Event where - ::AccountId, - { - /// Ethereum events from contracts. - Log(Log), - /// A contract has been created at given \[address\]. - Created(H160), - /// A \[contract\] was attempted to be created, but the execution failed. - CreatedFailed(H160), - /// A \[contract\] has been executed successfully with states applied. - Executed(H160), - /// A \[contract\] has been executed with errors. States are reverted with only gas fees applied. - ExecutedFailed(H160), - /// A deposit has been made at a given address. \[sender, address, value\] - BalanceDeposit(AccountId, H160, U256), - /// A withdrawal has been made from a given address. \[sender, address, value\] - BalanceWithdraw(AccountId, H160, U256), - } -} - -decl_error! { - pub enum Error for Module { - /// Not enough balance to perform action - BalanceLow, - /// Calculating total fee overflowed - FeeOverflow, - /// Calculating total payment overflowed - PaymentOverflow, - /// Withdraw fee failed - WithdrawFailed, - /// Gas price is too low. - GasPriceTooLow, - /// Nonce is invalid - InvalidNonce, - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - type Error = Error; - - fn deposit_event() = default; - - /// Withdraw balance from EVM into currency/balances module. - #[weight = 0] - fn withdraw(origin, address: H160, value: BalanceOf) { - let destination = T::WithdrawOrigin::ensure_address_origin(&address, origin)?; - let address_account_id = T::AddressMapping::into_account_id(address); - - T::Currency::transfer( - &address_account_id, - &destination, - value, - ExistenceRequirement::AllowDeath - )?; - } - - /// Issue an EVM call operation. This is similar to a message call transaction in Ethereum. - #[weight = (*gas_price).saturated_into::().saturating_mul(*gas_limit as Weight)] - fn call( - origin, - source: H160, - target: H160, - input: Vec, - value: U256, - gas_limit: u32, - gas_price: U256, - nonce: Option, - ) -> DispatchResultWithPostInfo { - T::CallOrigin::ensure_address_origin(&source, origin)?; - - match Self::execute_call( - source, - target, - input, - value, - gas_limit, - gas_price, - nonce, - true, - )? { - (ExitReason::Succeed(_), _, _, _) => { - Module::::deposit_event(Event::::Executed(target)); - }, - (_, _, _, _) => { - Module::::deposit_event(Event::::ExecutedFailed(target)); - }, - } - - Ok(Pays::No.into()) - } - - /// Issue an EVM create operation. This is similar to a contract creation transaction in - /// Ethereum. - #[weight = (*gas_price).saturated_into::().saturating_mul(*gas_limit as Weight)] - fn create( - origin, - source: H160, - init: Vec, - value: U256, - gas_limit: u32, - gas_price: U256, - nonce: Option, - ) -> DispatchResultWithPostInfo { - T::CallOrigin::ensure_address_origin(&source, origin)?; - - match Self::execute_create( - source, - init, - value, - gas_limit, - gas_price, - nonce, - true, - )? { - (ExitReason::Succeed(_), create_address, _, _) => { - Module::::deposit_event(Event::::Created(create_address)); - }, - (_, create_address, _, _) => { - Module::::deposit_event(Event::::CreatedFailed(create_address)); - }, - } - - Ok(Pays::No.into()) - } - - /// Issue an EVM create2 operation. - #[weight = (*gas_price).saturated_into::().saturating_mul(*gas_limit as Weight)] - fn create2( - origin, - source: H160, - init: Vec, - salt: H256, - value: U256, - gas_limit: u32, - gas_price: U256, - nonce: Option, - ) -> DispatchResultWithPostInfo { - T::CallOrigin::ensure_address_origin(&source, origin)?; - - match Self::execute_create2( - source, - init, - salt, - value, - gas_limit, - gas_price, - nonce, - true, - )? { - (ExitReason::Succeed(_), create_address, _, _) => { - Module::::deposit_event(Event::::Created(create_address)); - }, - (_, create_address, _, _) => { - Module::::deposit_event(Event::::CreatedFailed(create_address)); - }, - } - - Ok(Pays::No.into()) - } - } -} - -impl Module { - fn remove_account(address: &H160) { - AccountCodes::remove(address); - AccountStorages::remove_prefix(address); - } - - fn mutate_account_basic(address: &H160, new: Account) { - let account_id = T::AddressMapping::into_account_id(*address); - let current = Self::account_basic(address); - - if current.nonce < new.nonce { - // ASSUME: in one single EVM transaction, the nonce will not increase more than - // `u128::max_value()`. - for _ in 0..(new.nonce - current.nonce).low_u128() { - frame_system::Module::::inc_account_nonce(&account_id); - } - } - - if current.balance > new.balance { - let diff = current.balance - new.balance; - T::Currency::slash(&account_id, diff.low_u128().unique_saturated_into()); - } else if current.balance < new.balance { - let diff = new.balance - current.balance; - T::Currency::deposit_creating(&account_id, diff.low_u128().unique_saturated_into()); - } - } - - /// Check whether an account is empty. - pub fn is_account_empty(address: &H160) -> bool { - let account = Self::account_basic(address); - let code_len = AccountCodes::decode_len(address).unwrap_or(0); - - account.nonce == U256::zero() && - account.balance == U256::zero() && - code_len == 0 - } - - /// Remove an account if its empty. - pub fn remove_account_if_empty(address: &H160) { - if Self::is_account_empty(address) { - Self::remove_account(address); - } - } - - /// Get the account basic in EVM format. - pub fn account_basic(address: &H160) -> Account { - let account_id = T::AddressMapping::into_account_id(*address); - - let nonce = frame_system::Module::::account_nonce(&account_id); - let balance = T::Currency::free_balance(&account_id); - - Account { - nonce: U256::from(UniqueSaturatedInto::::unique_saturated_into(nonce)), - balance: U256::from(UniqueSaturatedInto::::unique_saturated_into(balance)), - } - } - - /// Execute a create transaction on behalf of given sender. - pub fn execute_create( - source: H160, - init: Vec, - value: U256, - gas_limit: u32, - gas_price: U256, - nonce: Option, - apply_state: bool, - ) -> Result<(ExitReason, H160, U256, Vec), Error> { - Self::execute_evm( - source, - value, - gas_limit, - gas_price, - nonce, - apply_state, - |executor| { - let address = executor.create_address( - evm::CreateScheme::Legacy { caller: source }, - ); - (executor.transact_create( - source, - value, - init, - gas_limit as usize, - ), address) - }, - ) - } - - /// Execute a create2 transaction on behalf of a given sender. - pub fn execute_create2( - source: H160, - init: Vec, - salt: H256, - value: U256, - gas_limit: u32, - gas_price: U256, - nonce: Option, - apply_state: bool, - ) -> Result<(ExitReason, H160, U256, Vec), Error> { - let code_hash = H256::from_slice(Keccak256::digest(&init).as_slice()); - Self::execute_evm( - source, - value, - gas_limit, - gas_price, - nonce, - apply_state, - |executor| { - let address = executor.create_address( - evm::CreateScheme::Create2 { caller: source, code_hash, salt }, - ); - (executor.transact_create2( - source, - value, - init, - salt, - gas_limit as usize, - ), address) - }, - ) - } - - /// Execute a call transaction on behalf of a given sender. - pub fn execute_call( - source: H160, - target: H160, - input: Vec, - value: U256, - gas_limit: u32, - gas_price: U256, - nonce: Option, - apply_state: bool, - ) -> Result<(ExitReason, Vec, U256, Vec), Error> { - Self::execute_evm( - source, - value, - gas_limit, - gas_price, - nonce, - apply_state, - |executor| executor.transact_call( - source, - target, - value, - input, - gas_limit as usize, - ), - ) - } - - /// Execute an EVM operation. - fn execute_evm( - source: H160, - value: U256, - gas_limit: u32, - gas_price: U256, - nonce: Option, - apply_state: bool, - f: F, - ) -> Result<(ExitReason, R, U256, Vec), Error> where - F: FnOnce(&mut StackExecutor>) -> (ExitReason, R), - { - - // Gas price check is skipped when performing a gas estimation. - if apply_state { - ensure!(gas_price >= T::FeeCalculator::min_gas_price(), Error::::GasPriceTooLow); - } - - let vicinity = Vicinity { - gas_price, - origin: source, - }; - - let mut backend = Backend::::new(&vicinity); - let mut executor = StackExecutor::new_with_precompile( - &backend, - gas_limit as usize, - T::config(), - T::Precompiles::execute, - ); - - let total_fee = gas_price.checked_mul(U256::from(gas_limit)) - .ok_or(Error::::FeeOverflow)?; - let total_payment = value.checked_add(total_fee).ok_or(Error::::PaymentOverflow)?; - let source_account = Self::account_basic(&source); - ensure!(source_account.balance >= total_payment, Error::::BalanceLow); - executor.withdraw(source, total_fee).map_err(|_| Error::::WithdrawFailed)?; - - if let Some(nonce) = nonce { - ensure!(source_account.nonce == nonce, Error::::InvalidNonce); - } - - let (retv, reason) = f(&mut executor); - - let used_gas = U256::from(executor.used_gas()); - let actual_fee = executor.fee(gas_price); - debug::debug!( - target: "evm", - "Execution {:?} [source: {:?}, value: {}, gas_limit: {}, used_gas: {}, actual_fee: {}]", - retv, - source, - value, - gas_limit, - used_gas, - actual_fee - ); - executor.deposit(source, total_fee.saturating_sub(actual_fee)); - - let (values, logs) = executor.deconstruct(); - let logs_data = logs.into_iter().map(|x| x ).collect::>(); - let logs_result = logs_data.clone().into_iter().map(|it| { - Log { - address: it.address, - topics: it.topics, - data: it.data - } - }).collect(); - if apply_state { - backend.apply(values, logs_data, true); - } - - Ok((retv, reason, used_gas, logs_result)) - } -} diff --git a/frame/evm/src/precompiles.rs b/frame/evm/src/precompiles.rs deleted file mode 100644 index 440d9bf1c68c2..0000000000000 --- a/frame/evm/src/precompiles.rs +++ /dev/null @@ -1,167 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Builtin precompiles. - -use sp_std::{cmp::min, vec::Vec}; -use sp_core::H160; -use evm::{ExitError, ExitSucceed}; -use ripemd160::Digest; -use impl_trait_for_tuples::impl_for_tuples; - -/// Custom precompiles to be used by EVM engine. -pub trait Precompiles { - /// Try to execute the code address as precompile. If the code address is not - /// a precompile or the precompile is not yet available, return `None`. - /// Otherwise, calculate the amount of gas needed with given `input` and - /// `target_gas`. Return `Some(Ok(status, output, gas_used))` if the execution - /// is successful. Otherwise return `Some(Err(_))`. - fn execute( - address: H160, - input: &[u8], - target_gas: Option, - ) -> Option, usize), ExitError>>; -} - -/// One single precompile used by EVM engine. -pub trait Precompile { - /// Try to execute the precompile. Calculate the amount of gas needed with given `input` and - /// `target_gas`. Return `Ok(status, output, gas_used)` if the execution is - /// successful. Otherwise return `Err(_)`. - fn execute( - input: &[u8], - target_gas: Option, - ) -> core::result::Result<(ExitSucceed, Vec, usize), ExitError>; -} - -#[impl_for_tuples(16)] -#[tuple_types_no_default_trait_bound] -impl Precompiles for Tuple { - for_tuples!( where #( Tuple: Precompile )* ); - - fn execute( - address: H160, - input: &[u8], - target_gas: Option, - ) -> Option, usize), ExitError>> { - let mut index = 0; - - for_tuples!( #( - index += 1; - if address == H160::from_low_u64_be(index) { - return Some(Tuple::execute(input, target_gas)) - } - )* ); - - None - } -} - -/// Linear gas cost -fn ensure_linear_cost( - target_gas: Option, - len: usize, - base: usize, - word: usize -) -> Result { - let cost = base.checked_add( - word.checked_mul(len.saturating_add(31) / 32).ok_or(ExitError::OutOfGas)? - ).ok_or(ExitError::OutOfGas)?; - - if let Some(target_gas) = target_gas { - if cost > target_gas { - return Err(ExitError::OutOfGas) - } - } - - Ok(cost) -} - -/// The identity precompile. -pub struct Identity; - -impl Precompile for Identity { - fn execute( - input: &[u8], - target_gas: Option, - ) -> core::result::Result<(ExitSucceed, Vec, usize), ExitError> { - let cost = ensure_linear_cost(target_gas, input.len(), 15, 3)?; - - Ok((ExitSucceed::Returned, input.to_vec(), cost)) - } -} - -/// The ecrecover precompile. -pub struct ECRecover; - -impl Precompile for ECRecover { - fn execute( - i: &[u8], - target_gas: Option, - ) -> core::result::Result<(ExitSucceed, Vec, usize), ExitError> { - let cost = ensure_linear_cost(target_gas, i.len(), 3000, 0)?; - - let mut input = [0u8; 128]; - input[..min(i.len(), 128)].copy_from_slice(&i[..min(i.len(), 128)]); - - let mut msg = [0u8; 32]; - let mut sig = [0u8; 65]; - - msg[0..32].copy_from_slice(&input[0..32]); - sig[0..32].copy_from_slice(&input[64..96]); - sig[32..64].copy_from_slice(&input[96..128]); - sig[64] = input[63]; - - let pubkey = sp_io::crypto::secp256k1_ecdsa_recover(&sig, &msg) - .map_err(|_| ExitError::Other("Public key recover failed"))?; - let mut address = sp_io::hashing::keccak_256(&pubkey); - address[0..12].copy_from_slice(&[0u8; 12]); - - Ok((ExitSucceed::Returned, address.to_vec(), cost)) - } -} - -/// The ripemd precompile. -pub struct Ripemd160; - -impl Precompile for Ripemd160 { - fn execute( - input: &[u8], - target_gas: Option, - ) -> core::result::Result<(ExitSucceed, Vec, usize), ExitError> { - let cost = ensure_linear_cost(target_gas, input.len(), 600, 120)?; - - let mut ret = [0u8; 32]; - ret[12..32].copy_from_slice(&ripemd160::Ripemd160::digest(input)); - Ok((ExitSucceed::Returned, ret.to_vec(), cost)) - } -} - -/// The sha256 precompile. -pub struct Sha256; - -impl Precompile for Sha256 { - fn execute( - input: &[u8], - target_gas: Option, - ) -> core::result::Result<(ExitSucceed, Vec, usize), ExitError> { - let cost = ensure_linear_cost(target_gas, input.len(), 60, 12)?; - - let ret = sp_io::hashing::sha2_256(input); - Ok((ExitSucceed::Returned, ret.to_vec(), cost)) - } -} diff --git a/frame/evm/src/tests.rs b/frame/evm/src/tests.rs deleted file mode 100644 index d05fdca1407e5..0000000000000 --- a/frame/evm/src/tests.rs +++ /dev/null @@ -1,189 +0,0 @@ -#![cfg(test)] - -use super::*; - -use std::{str::FromStr, collections::BTreeMap}; -use frame_support::{ - assert_ok, impl_outer_origin, parameter_types, impl_outer_dispatch, -}; -use sp_core::{Blake2Hasher, H256}; -use sp_runtime::{ - Perbill, - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, -}; - -impl_outer_origin! { - pub enum Origin for Test where system = frame_system {} -} - -impl_outer_dispatch! { - pub enum OuterCall for Test where origin: Origin { - self::EVM, - } -} - -#[derive(Clone, Eq, PartialEq)] -pub struct Test; -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} -impl frame_system::Trait for Test { - type BaseCallFilter = (); - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Call = OuterCall; - type Hashing = BlakeTwo256; - type AccountId = AccountId32; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type DbWeight = (); - type BlockExecutionWeight = (); - type ExtrinsicBaseWeight = (); - type MaximumExtrinsicWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - type PalletInfo = (); - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 1; -} -impl pallet_balances::Trait for Test { - type MaxLocks = (); - type Balance = u64; - type DustRemoval = (); - type Event = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); -} - -parameter_types! { - pub const MinimumPeriod: u64 = 1000; -} -impl pallet_timestamp::Trait for Test { - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; - type WeightInfo = (); -} - -/// Fixed gas price of `0`. -pub struct FixedGasPrice; -impl FeeCalculator for FixedGasPrice { - fn min_gas_price() -> U256 { - // Gas price is always one token per gas. - 0.into() - } -} - -impl Trait for Test { - type FeeCalculator = FixedGasPrice; - - type CallOrigin = EnsureAddressRoot; - type WithdrawOrigin = EnsureAddressNever; - - type AddressMapping = HashedAddressMapping; - type Currency = Balances; - - type Event = Event; - type Precompiles = (); - type ChainId = SystemChainId; -} - -type System = frame_system::Module; -type Balances = pallet_balances::Module; -type EVM = Module; - -pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - - let mut accounts = BTreeMap::new(); - accounts.insert( - H160::from_str("1000000000000000000000000000000000000001").unwrap(), - GenesisAccount { - nonce: U256::from(1), - balance: U256::from(1000000), - storage: Default::default(), - code: vec![ - 0x00, // STOP - ], - } - ); - accounts.insert( - H160::from_str("1000000000000000000000000000000000000002").unwrap(), - GenesisAccount { - nonce: U256::from(1), - balance: U256::from(1000000), - storage: Default::default(), - code: vec![ - 0xff, // INVALID - ], - } - ); - - pallet_balances::GenesisConfig::::default().assimilate_storage(&mut t).unwrap(); - GenesisConfig { accounts }.assimilate_storage::(&mut t).unwrap(); - t.into() -} - -#[test] -fn fail_call_return_ok() { - new_test_ext().execute_with(|| { - assert_ok!(EVM::call( - Origin::root(), - H160::default(), - H160::from_str("1000000000000000000000000000000000000001").unwrap(), - Vec::new(), - U256::default(), - 1000000, - U256::default(), - None, - )); - - assert_ok!(EVM::call( - Origin::root(), - H160::default(), - H160::from_str("1000000000000000000000000000000000000002").unwrap(), - Vec::new(), - U256::default(), - 1000000, - U256::default(), - None, - )); - }); -} - -#[test] -fn mutate_account_works() { - new_test_ext().execute_with(|| { - EVM::mutate_account_basic( - &H160::from_str("1000000000000000000000000000000000000001").unwrap(), - Account { - nonce: U256::from(10), - balance: U256::from(1000), - }, - ); - - assert_eq!(EVM::account_basic( - &H160::from_str("1000000000000000000000000000000000000001").unwrap() - ), Account { - nonce: U256::from(10), - balance: U256::from(1000), - }); - }); -} diff --git a/frame/indices/src/address.rs b/frame/indices/src/address.rs deleted file mode 100644 index 0fd8933381328..0000000000000 --- a/frame/indices/src/address.rs +++ /dev/null @@ -1,159 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Address type that is union of index and id for an account. - -#[cfg(feature = "std")] -use std::fmt; -use sp_std::convert::TryInto; -use crate::Member; -use codec::{Encode, Decode, Input, Output, Error}; - -/// An indices-aware address, which can be either a direct `AccountId` or -/// an index. -#[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Hash))] -pub enum Address where - AccountId: Member, - AccountIndex: Member, -{ - /// It's an account ID (pubkey). - Id(AccountId), - /// It's an account index. - Index(AccountIndex), -} - -#[cfg(feature = "std")] -impl fmt::Display for Address where - AccountId: Member, - AccountIndex: Member, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self) - } -} - -impl From for Address where - AccountId: Member, - AccountIndex: Member, -{ - fn from(a: AccountId) -> Self { - Address::Id(a) - } -} - -fn need_more_than(a: T, b: T) -> Result { - if a < b { Ok(b) } else { Err("Invalid range".into()) } -} - -impl Decode for Address where - AccountId: Member + Decode, - AccountIndex: Member + Decode + PartialOrd + Ord + From + Copy, -{ - fn decode(input: &mut I) -> Result { - Ok(match input.read_byte()? { - x @ 0x00..=0xef => Address::Index(AccountIndex::from(x as u32)), - 0xfc => Address::Index(AccountIndex::from( - need_more_than(0xef, u16::decode(input)?)? as u32 - )), - 0xfd => Address::Index(AccountIndex::from( - need_more_than(0xffff, u32::decode(input)?)? - )), - 0xfe => Address::Index( - need_more_than(0xffffffffu32.into(), Decode::decode(input)?)? - ), - 0xff => Address::Id(Decode::decode(input)?), - _ => return Err("Invalid address variant".into()), - }) - } -} - -impl Encode for Address where - AccountId: Member + Encode, - AccountIndex: Member + Encode + PartialOrd + Ord + Copy + From + TryInto, -{ - fn encode_to(&self, dest: &mut T) { - match *self { - Address::Id(ref i) => { - dest.push_byte(255); - dest.push(i); - } - Address::Index(i) => { - let maybe_u32: Result = i.try_into(); - if let Ok(x) = maybe_u32 { - if x > 0xffff { - dest.push_byte(253); - dest.push(&x); - } - else if x >= 0xf0 { - dest.push_byte(252); - dest.push(&(x as u16)); - } - else { - dest.push_byte(x as u8); - } - - } else { - dest.push_byte(254); - dest.push(&i); - } - }, - } - } -} - -impl codec::EncodeLike for Address where - AccountId: Member + Encode, - AccountIndex: Member + Encode + PartialOrd + Ord + Copy + From + TryInto, -{} - -impl Default for Address where - AccountId: Member + Default, - AccountIndex: Member, -{ - fn default() -> Self { - Address::Id(Default::default()) - } -} - -#[cfg(test)] -mod tests { - use codec::{Encode, Decode}; - - type Address = super::Address<[u8; 8], u32>; - fn index(i: u32) -> Address { super::Address::Index(i) } - fn id(i: [u8; 8]) -> Address { super::Address::Id(i) } - - fn compare(a: Option
, d: &[u8]) { - if let Some(ref a) = a { - assert_eq!(d, &a.encode()[..]); - } - assert_eq!(Address::decode(&mut &d[..]).ok(), a); - } - - #[test] - fn it_should_work() { - compare(Some(index(2)), &[2][..]); - compare(None, &[240][..]); - compare(None, &[252, 239, 0][..]); - compare(Some(index(240)), &[252, 240, 0][..]); - compare(Some(index(304)), &[252, 48, 1][..]); - compare(None, &[253, 255, 255, 0, 0][..]); - compare(Some(index(0x10000)), &[253, 0, 0, 1, 0][..]); - compare(Some(id([42, 69, 42, 69, 42, 69, 42, 69])), &[255, 42, 69, 42, 69, 42, 69, 42, 69][..]); - } -} diff --git a/frame/indices/src/lib.rs b/frame/indices/src/lib.rs index fd2eb956f9231..6d467aa673445 100644 --- a/frame/indices/src/lib.rs +++ b/frame/indices/src/lib.rs @@ -21,13 +21,13 @@ #![cfg_attr(not(feature = "std"), no_std)] mod mock; -pub mod address; mod tests; mod benchmarking; pub mod weights; use sp_std::prelude::*; use codec::Codec; +use sp_runtime::MultiAddress; use sp_runtime::traits::{ StaticLookup, Member, LookupError, Zero, Saturating, AtLeast32Bit }; @@ -35,10 +35,8 @@ use frame_support::{Parameter, decl_module, decl_error, decl_event, decl_storage use frame_support::dispatch::DispatchResult; use frame_support::traits::{Currency, ReservableCurrency, Get, BalanceStatus::Reserved}; use frame_system::{ensure_signed, ensure_root}; -use self::address::Address as RawAddress; pub use weights::WeightInfo; -pub type Address = RawAddress<::AccountId, ::AccountIndex>; type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; /// The module's config trait. @@ -287,17 +285,18 @@ impl Module { /// Lookup an address to get an Id, if there's one there. pub fn lookup_address( - a: address::Address + a: MultiAddress ) -> Option { match a { - address::Address::Id(i) => Some(i), - address::Address::Index(i) => Self::lookup_index(i), + MultiAddress::Id(i) => Some(i), + MultiAddress::Index(i) => Self::lookup_index(i), + _ => None, } } } impl StaticLookup for Module { - type Source = address::Address; + type Source = MultiAddress; type Target = T::AccountId; fn lookup(a: Self::Source) -> Result { @@ -305,6 +304,6 @@ impl StaticLookup for Module { } fn unlookup(a: Self::Target) -> Self::Source { - address::Address::Id(a) + MultiAddress::Id(a) } } diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs index 492fda88dd170..06188c42b21bd 100644 --- a/frame/membership/src/lib.rs +++ b/frame/membership/src/lib.rs @@ -278,7 +278,6 @@ impl, I: Instance> Contains for Module { mod tests { use super::*; - use std::cell::RefCell; use frame_support::{ assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight, ord_parameter_types @@ -298,6 +297,8 @@ mod tests { pub const MaximumBlockWeight: Weight = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub static Members: Vec = vec![]; + pub static Prime: Option = None; } impl frame_system::Trait for Test { type BaseCallFilter = (); @@ -334,11 +335,6 @@ mod tests { pub const Five: u64 = 5; } - thread_local! { - static MEMBERS: RefCell> = RefCell::new(vec![]); - static PRIME: RefCell> = RefCell::new(None); - } - pub struct TestChangeMembers; impl ChangeMembers for TestChangeMembers { fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) { diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 055ebb9730805..3aa3e9ae03d74 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -47,12 +47,6 @@ pub(crate) type Balance = u128; thread_local! { static SESSION: RefCell<(Vec, HashSet)> = RefCell::new(Default::default()); - static SESSION_PER_ERA: RefCell = RefCell::new(3); - static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); - static SLASH_DEFER_DURATION: RefCell = RefCell::new(0); - static ELECTION_LOOKAHEAD: RefCell = RefCell::new(0); - static PERIOD: RefCell = RefCell::new(1); - static MAX_ITERATIONS: RefCell = RefCell::new(0); } /// Another session handler struct to test on_disabled. @@ -92,53 +86,6 @@ pub fn is_disabled(controller: AccountId) -> bool { SESSION.with(|d| d.borrow().1.contains(&stash)) } -pub struct ExistentialDeposit; -impl Get for ExistentialDeposit { - fn get() -> Balance { - EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) - } -} - -pub struct SessionsPerEra; -impl Get for SessionsPerEra { - fn get() -> SessionIndex { - SESSION_PER_ERA.with(|v| *v.borrow()) - } -} -impl Get for SessionsPerEra { - fn get() -> BlockNumber { - SESSION_PER_ERA.with(|v| *v.borrow() as BlockNumber) - } -} - -pub struct ElectionLookahead; -impl Get for ElectionLookahead { - fn get() -> BlockNumber { - ELECTION_LOOKAHEAD.with(|v| *v.borrow()) - } -} - -pub struct Period; -impl Get for Period { - fn get() -> BlockNumber { - PERIOD.with(|v| *v.borrow()) - } -} - -pub struct SlashDeferDuration; -impl Get for SlashDeferDuration { - fn get() -> EraIndex { - SLASH_DEFER_DURATION.with(|v| *v.borrow()) - } -} - -pub struct MaxIterations; -impl Get for MaxIterations { - fn get() -> u32 { - MAX_ITERATIONS.with(|v| *v.borrow()) - } -} - impl_outer_origin! { pub enum Origin for Test where system = frame_system {} } @@ -186,7 +133,14 @@ parameter_types! { pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const MaxLocks: u32 = 1024; + pub static SessionsPerEra: SessionIndex = 3; + pub static ExistentialDeposit: Balance = 0; + pub static SlashDeferDuration: EraIndex = 0; + pub static ElectionLookahead: BlockNumber = 0; + pub static Period: BlockNumber = 1; + pub static MaxIterations: u32 = 0; } + impl frame_system::Trait for Test { type BaseCallFilter = (); type Origin = Origin; @@ -437,7 +391,7 @@ impl ExtBuilder { pub fn set_associated_constants(&self) { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); SLASH_DEFER_DURATION.with(|v| *v.borrow_mut() = self.slash_defer_duration); - SESSION_PER_ERA.with(|v| *v.borrow_mut() = self.session_per_era); + SESSIONS_PER_ERA.with(|v| *v.borrow_mut() = self.session_per_era); ELECTION_LOOKAHEAD.with(|v| *v.borrow_mut() = self.election_lookahead); PERIOD.with(|v| *v.borrow_mut() = self.session_length); MAX_ITERATIONS.with(|v| *v.borrow_mut() = self.max_offchain_iterations); diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index a132b787fd9bf..5dd452dbbe7b9 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -85,21 +85,27 @@ pub enum Never {} /// Create new implementations of the [`Get`](crate::traits::Get) trait. /// -/// The so-called parameter type can be created in three different ways: +/// The so-called parameter type can be created in four different ways: /// -/// - Using `const` to create a parameter type that provides a `const` getter. -/// It is required that the `value` is const. +/// - Using `const` to create a parameter type that provides a `const` getter. It is required that +/// the `value` is const. /// /// - Declare the parameter type without `const` to have more freedom when creating the value. /// -/// - Using `storage` to create a storage parameter type. This type is special as it tries to -/// load the value from the storage under a fixed key. If the value could not be found in the -/// storage, the given default value will be returned. It is required that the value implements -/// [`Encode`](codec::Encode) and [`Decode`](codec::Decode). The key for looking up the value -/// in the storage is built using the following formular: +/// - Using `storage` to create a storage parameter type. This type is special as it tries to load +/// the value from the storage under a fixed key. If the value could not be found in the storage, +/// the given default value will be returned. It is required that the value implements +/// [`Encode`](codec::Encode) and [`Decode`](codec::Decode). The key for looking up the value in +/// the storage is built using the following formula: /// /// `twox_128(":" ++ NAME ++ ":")` where `NAME` is the name that is passed as type name. /// +/// - Using `static` to create a static parameter type. Its value is +/// being provided by a static variable with the equivalent name in `UPPER_SNAKE_CASE`. An +/// additional `set` function is provided in this case to alter the static variable. +/// +/// **This is intended for testing ONLY and is ONLY available when `std` is enabled** +/// /// # Examples /// /// ``` @@ -114,12 +120,14 @@ pub enum Never {} /// /// Visibility of the type is optional /// OtherArgument: u64 = non_const_expression(); /// pub storage StorageArgument: u64 = 5; +/// pub static StaticArgument: u32 = 7; /// } /// /// trait Config { /// type Parameter: Get; /// type OtherParameter: Get; /// type StorageParameter: Get; +/// type StaticParameter: Get; /// } /// /// struct Runtime; @@ -127,7 +135,10 @@ pub enum Never {} /// type Parameter = Argument; /// type OtherParameter = OtherArgument; /// type StorageParameter = StorageArgument; +/// type StaticParameter = StaticArgument; /// } +/// +/// // In testing, `StaticArgument` can be altered later: `StaticArgument::set(8)`. /// ``` /// /// # Invalid example: @@ -142,7 +153,6 @@ pub enum Never {} /// pub const Argument: u64 = non_const_expression(); /// } /// ``` - #[macro_export] macro_rules! parameter_types { ( @@ -235,7 +245,69 @@ macro_rules! parameter_types { I::from(Self::get()) } } - } + }; + ( + $( + $( #[ $attr:meta ] )* + $vis:vis static $name:ident: $type:ty = $value:expr; + )* + ) => ( + $crate::parameter_types_impl_thread_local!( + $( + $( #[ $attr ] )* + $vis static $name: $type = $value; + )* + ); + ); +} + +#[cfg(not(feature = "std"))] +#[macro_export] +macro_rules! parameter_types_impl_thread_local { + ( $( $any:tt )* ) => { + compile_error!("static parameter types is only available in std and for testing."); + }; +} + +#[cfg(feature = "std")] +#[macro_export] +macro_rules! parameter_types_impl_thread_local { + ( + $( + $( #[ $attr:meta ] )* + $vis:vis static $name:ident: $type:ty = $value:expr; + )* + ) => { + $crate::parameter_types_impl_thread_local!( + IMPL_THREAD_LOCAL $( $vis, $name, $type, $value, )* + ); + $crate::paste::item! { + $crate::parameter_types!( + $( + $( #[ $attr ] )* + $vis $name: $type = [<$name:snake:upper>].with(|v| v.borrow().clone()); + )* + ); + $( + impl $name { + /// Set the internal value. + pub fn set(t: $type) { + [<$name:snake:upper>].with(|v| *v.borrow_mut() = t); + } + } + )* + } + }; + (IMPL_THREAD_LOCAL $( $vis:vis, $name:ident, $type:ty, $value:expr, )* ) => { + $crate::paste::item! { + thread_local! { + $( + pub static [<$name:snake:upper>]: std::cell::RefCell<$type> = + std::cell::RefCell::new($value); + )* + } + } + }; } /// Macro for easily creating a new implementation of both the `Get` and `Contains` traits. Use diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index bc1700a43c3ee..b40ebe3dba67c 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -1265,7 +1265,7 @@ pub trait ChangeMembers { Self::change_members_sorted(&incoming[..], &outgoing[..], &new_members); } - /// Compute diff between new and old members; they **must already be sorted**. + /// Compute diff between new and old members; they **must already be sorted**. /// /// Returns incoming and outgoing members. fn compute_members_diff( @@ -1427,6 +1427,9 @@ pub trait GetCallMetadata { #[impl_for_tuples(30)] pub trait OnFinalize { /// The block is being finalized. Implement to have something happen. + /// + /// NOTE: This function is called AFTER ALL extrinsics in a block are applied, + /// including inherent extrinsics. fn on_finalize(_n: BlockNumber) {} } @@ -1438,6 +1441,10 @@ pub trait OnInitialize { /// The block is being initialized. Implement to have something happen. /// /// Return the non-negotiable weight consumed in the block. + /// + /// NOTE: This function is called BEFORE ANY extrinsic in a block is applied, + /// including inherent extrinsics. Hence for instance, if you runtime includes + /// `pallet_timestamp`, the `timestamp` is not yet up to date at this point. fn on_initialize(_n: BlockNumber) -> crate::weights::Weight { 0 } } @@ -1569,7 +1576,7 @@ pub mod schedule { /// Reschedule a task. For one-off tasks, this dispatch is guaranteed to succeed /// only if it is executed *before* the currently scheduled block. For periodic tasks, /// this dispatch is guaranteed to succeed only before the *initial* execution; for - /// others, use `reschedule_named`. + /// others, use `reschedule_named`. /// /// Will return an error if the `address` is invalid. fn reschedule( diff --git a/frame/support/test/tests/construct_runtime_ui.rs b/frame/support/test/tests/construct_runtime_ui.rs index e1624c76830ae..83a90c96dd624 100644 --- a/frame/support/test/tests/construct_runtime_ui.rs +++ b/frame/support/test/tests/construct_runtime_ui.rs @@ -21,7 +21,7 @@ use std::env; #[test] fn ui() { // As trybuild is using `cargo check`, we don't need the real WASM binaries. - env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); + env::set_var("SKIP_WASM_BUILD", "1"); let t = trybuild::TestCases::new(); t.compile_fail("tests/construct_runtime_ui/*.rs"); diff --git a/frame/support/test/tests/decl_module_ui.rs b/frame/support/test/tests/decl_module_ui.rs index 7df64bc52f412..22237d904aeac 100644 --- a/frame/support/test/tests/decl_module_ui.rs +++ b/frame/support/test/tests/decl_module_ui.rs @@ -19,7 +19,7 @@ #[test] fn decl_module_ui() { // As trybuild is using `cargo check`, we don't need the real WASM binaries. - std::env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); + std::env::set_var("SKIP_WASM_BUILD", "1"); let t = trybuild::TestCases::new(); t.compile_fail("tests/decl_module_ui/*.rs"); diff --git a/frame/support/test/tests/decl_storage_ui.rs b/frame/support/test/tests/decl_storage_ui.rs index 56529d62c28ff..4b082cb8172a7 100644 --- a/frame/support/test/tests/decl_storage_ui.rs +++ b/frame/support/test/tests/decl_storage_ui.rs @@ -19,7 +19,7 @@ #[test] fn decl_storage_ui() { // As trybuild is using `cargo check`, we don't need the real WASM binaries. - std::env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); + std::env::set_var("SKIP_WASM_BUILD", "1"); let t = trybuild::TestCases::new(); t.compile_fail("tests/decl_storage_ui/*.rs"); diff --git a/frame/support/test/tests/derive_no_bound_ui.rs b/frame/support/test/tests/derive_no_bound_ui.rs index da276018f7f8e..ba8fff1f3a5c5 100644 --- a/frame/support/test/tests/derive_no_bound_ui.rs +++ b/frame/support/test/tests/derive_no_bound_ui.rs @@ -19,7 +19,7 @@ #[test] fn derive_no_bound_ui() { // As trybuild is using `cargo check`, we don't need the real WASM binaries. - std::env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); + std::env::set_var("SKIP_WASM_BUILD", "1"); let t = trybuild::TestCases::new(); t.compile_fail("tests/derive_no_bound_ui/*.rs"); diff --git a/frame/support/test/tests/reserved_keyword.rs b/frame/support/test/tests/reserved_keyword.rs index 382b2e498741f..8136d11824ace 100644 --- a/frame/support/test/tests/reserved_keyword.rs +++ b/frame/support/test/tests/reserved_keyword.rs @@ -19,7 +19,7 @@ #[test] fn reserved_keyword() { // As trybuild is using `cargo check`, we don't need the real WASM binaries. - std::env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); + std::env::set_var("SKIP_WASM_BUILD", "1"); let t = trybuild::TestCases::new(); t.compile_fail("tests/reserved_keyword/*.rs"); diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index dd310c2639842..751aa57da0f80 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -571,7 +571,6 @@ mod tests { traits::{BlakeTwo256, IdentityLookup}, Perbill, }; - use std::cell::RefCell; use smallvec::smallvec; const CALL: &::Call = @@ -599,20 +598,14 @@ mod tests { pub enum Origin for Runtime {} } - thread_local! { - static EXTRINSIC_BASE_WEIGHT: RefCell = RefCell::new(0); - } - - pub struct ExtrinsicBaseWeight; - impl Get for ExtrinsicBaseWeight { - fn get() -> u64 { EXTRINSIC_BASE_WEIGHT.with(|v| *v.borrow()) } - } - parameter_types! { pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: Weight = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub static ExtrinsicBaseWeight: u64 = 0; + pub static TransactionByteFee: u64 = 1; + pub static WeightToFee: u64 = 1; } impl frame_system::Trait for Runtime { @@ -656,17 +649,7 @@ mod tests { type MaxLocks = (); type WeightInfo = (); } - thread_local! { - static TRANSACTION_BYTE_FEE: RefCell = RefCell::new(1); - static WEIGHT_TO_FEE: RefCell = RefCell::new(1); - } - - pub struct TransactionByteFee; - impl Get for TransactionByteFee { - fn get() -> u64 { TRANSACTION_BYTE_FEE.with(|v| *v.borrow()) } - } - pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { type Balance = u64; diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index 8b78eac4fedf8..c09516c2cc27c 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -390,10 +390,8 @@ impl VestingSchedule for Module where mod tests { use super::*; - use std::cell::RefCell; use frame_support::{ assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight, - traits::Get }; use sp_core::H256; use sp_runtime::{ @@ -456,6 +454,7 @@ mod tests { } parameter_types! { pub const MinVestedTransfer: u64 = 256 * 2; + pub static ExistentialDeposit: u64 = 0; } impl Trait for Test { type Event = (); @@ -468,13 +467,6 @@ mod tests { type Balances = pallet_balances::Module; type Vesting = Module; - thread_local! { - static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); - } - pub struct ExistentialDeposit; - impl Get for ExistentialDeposit { - fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) } - } pub struct ExtBuilder { existential_deposit: u64, diff --git a/primitives/api/test/tests/trybuild.rs b/primitives/api/test/tests/trybuild.rs index 2f7fd6d06bcd3..f23c7291e8ef7 100644 --- a/primitives/api/test/tests/trybuild.rs +++ b/primitives/api/test/tests/trybuild.rs @@ -21,7 +21,7 @@ use std::env; #[test] fn ui() { // As trybuild is using `cargo check`, we don't need the real WASM binaries. - env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); + env::set_var("SKIP_WASM_BUILD", "1"); let t = trybuild::TestCases::new(); t.compile_fail("tests/ui/*.rs"); diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index f714aaaa1dae1..eac1e032e3e9a 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -15,12 +15,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.11" -lru = "0.4.0" +lru = "0.6.1" parking_lot = "0.10.0" thiserror = "1.0.21" codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } sp-consensus = { version = "0.8.0", path = "../consensus/common" } sp-runtime = { version = "2.0.0", path = "../runtime" } -sp-block-builder = { version = "2.0.0", path = "../block-builder" } sp-state-machine = { version = "0.8.0", path = "../state-machine" } sp-database = { version = "2.0.0", path = "../database" } diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index 001f0e3679458..938745048c1b0 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -33,7 +33,7 @@ codec = { package = "parity-scale-codec", version = "1.3.1", features = ["derive parking_lot = "0.10.0" serde = { version = "1.0", features = ["derive"] } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.8.0"} -wasm-timer = "0.2.4" +wasm-timer = "0.2.5" [dev-dependencies] futures = "0.3.4" diff --git a/primitives/consensus/common/src/block_import.rs b/primitives/consensus/common/src/block_import.rs index 5e593da1163d7..0100041fc0a0c 100644 --- a/primitives/consensus/common/src/block_import.rs +++ b/primitives/consensus/common/src/block_import.rs @@ -26,7 +26,7 @@ use std::sync::Arc; use std::any::Any; use crate::Error; -use crate::import_queue::{Verifier, CacheKeyId}; +use crate::import_queue::CacheKeyId; /// Block import result. #[derive(Debug, PartialEq, Eq)] @@ -54,8 +54,6 @@ pub struct ImportedAux { pub needs_justification: bool, /// Received a bad justification. pub bad_justification: bool, - /// Request a finality proof for the given block. - pub needs_finality_proof: bool, /// Whether the block that was imported is the new best block. pub is_new_best: bool, } @@ -63,7 +61,7 @@ pub struct ImportedAux { impl ImportResult { /// Returns default value for `ImportResult::Imported` with /// `clear_justification_requests`, `needs_justification`, - /// `bad_justification` and `needs_finality_proof` set to false. + /// `bad_justification` set to false. pub fn imported(is_new_best: bool) -> ImportResult { let mut aux = ImportedAux::default(); aux.is_new_best = is_new_best; @@ -345,21 +343,3 @@ pub trait JustificationImport { justification: Justification, ) -> Result<(), Self::Error>; } - -/// Finality proof import trait. -pub trait FinalityProofImport { - type Error: std::error::Error + Send + 'static; - - /// Called by the import queue when it is started. Returns a list of finality proofs to request - /// from the network. - fn on_start(&mut self) -> Vec<(B::Hash, NumberFor)> { Vec::new() } - - /// Import a Block justification and finalize the given block. Returns finalized block or error. - fn import_finality_proof( - &mut self, - hash: B::Hash, - number: NumberFor, - finality_proof: Vec, - verifier: &mut dyn Verifier, - ) -> Result<(B::Hash, NumberFor), Self::Error>; -} diff --git a/primitives/consensus/common/src/import_queue.rs b/primitives/consensus/common/src/import_queue.rs index 92bd9966d75ec..3ad8c7c92e07f 100644 --- a/primitives/consensus/common/src/import_queue.rs +++ b/primitives/consensus/common/src/import_queue.rs @@ -34,7 +34,7 @@ use crate::{ error::Error as ConsensusError, block_import::{ BlockImport, BlockOrigin, BlockImportParams, ImportedAux, JustificationImport, ImportResult, - BlockCheckParams, FinalityProofImport, + BlockCheckParams, }, metrics::Metrics, }; @@ -56,11 +56,6 @@ pub type BoxBlockImport = Box< /// Shared justification import struct used by the queue. pub type BoxJustificationImport = Box + Send + Sync>; -/// Shared finality proof import struct used by the queue. -pub type BoxFinalityProofImport = Box< - dyn FinalityProofImport + Send + Sync ->; - /// Maps to the Origin used by the network. pub type Origin = libp2p::PeerId; @@ -115,15 +110,6 @@ pub trait ImportQueue: Send { number: NumberFor, justification: Justification ); - /// Import block finality proof. - fn import_finality_proof( - &mut self, - who: Origin, - hash: B::Hash, - number: NumberFor, - finality_proof: Vec - ); - /// Polls for actions to perform on the network. /// /// This method should behave in a way similar to `Future::poll`. It can register the current @@ -146,19 +132,6 @@ pub trait Link: Send { fn justification_imported(&mut self, _who: Origin, _hash: &B::Hash, _number: NumberFor, _success: bool) {} /// Request a justification for the given block. fn request_justification(&mut self, _hash: &B::Hash, _number: NumberFor) {} - /// Finality proof import result. - /// - /// Even though we have asked for finality proof of block A, provider could return proof of - /// some earlier block B, if the proof for A was too large. The sync module should continue - /// asking for proof of A in this case. - fn finality_proof_imported( - &mut self, - _who: Origin, - _request_block: (B::Hash, NumberFor), - _finalization_result: Result<(B::Hash, NumberFor), ()>, - ) {} - /// Request a finality proof for the given block. - fn request_finality_proof(&mut self, _hash: &B::Hash, _number: NumberFor) {} } /// Block import successful result. diff --git a/primitives/consensus/common/src/import_queue/basic_queue.rs b/primitives/consensus/common/src/import_queue/basic_queue.rs index ea0ca2cf3ee88..b426c39100e69 100644 --- a/primitives/consensus/common/src/import_queue/basic_queue.rs +++ b/primitives/consensus/common/src/import_queue/basic_queue.rs @@ -25,7 +25,7 @@ use prometheus_endpoint::Registry; use crate::{ block_import::BlockOrigin, import_queue::{ - BlockImportResult, BlockImportError, Verifier, BoxBlockImport, BoxFinalityProofImport, + BlockImportResult, BlockImportError, Verifier, BoxBlockImport, BoxJustificationImport, ImportQueue, Link, Origin, IncomingBlock, import_single_block_metered, buffered_link::{self, BufferedLinkSender, BufferedLinkReceiver}, @@ -36,8 +36,8 @@ use crate::{ /// Interface to a basic block import queue that is importing blocks sequentially in a separate /// task, with plugable verification. pub struct BasicQueue { - /// Channel to send finality work messages to the background task. - finality_sender: TracingUnboundedSender>, + /// Channel to send justifcation import messages to the background task. + justification_sender: TracingUnboundedSender>, /// Channel to send block import messages to the background task. block_import_sender: TracingUnboundedSender>, /// Results coming from the worker task. @@ -48,7 +48,7 @@ pub struct BasicQueue { impl Drop for BasicQueue { fn drop(&mut self) { // Flush the queue and close the receiver to terminate the future. - self.finality_sender.close_channel(); + self.justification_sender.close_channel(); self.block_import_sender.close_channel(); self.result_port.close(); } @@ -57,13 +57,11 @@ impl Drop for BasicQueue { impl BasicQueue { /// Instantiate a new basic queue, with given verifier. /// - /// This creates a background task, and calls `on_start` on the justification importer and - /// finality proof importer. + /// This creates a background task, and calls `on_start` on the justification importer. pub fn new>( verifier: V, block_import: BoxBlockImport, justification_import: Option>, - finality_proof_import: Option>, spawner: &impl sp_core::traits::SpawnNamed, prometheus_registry: Option<&Registry>, ) -> Self { @@ -77,19 +75,18 @@ impl BasicQueue { .ok() }); - let (future, finality_sender, block_import_sender) = BlockImportWorker::new( + let (future, justification_sender, block_import_sender) = BlockImportWorker::new( result_sender, verifier, block_import, justification_import, - finality_proof_import, metrics, ); spawner.spawn_blocking("basic-block-import-worker", future.boxed()); Self { - finality_sender, + justification_sender, block_import_sender, result_port, _phantom: PhantomData, @@ -122,8 +119,8 @@ impl ImportQueue for BasicQueue number: NumberFor, justification: Justification, ) { - let res = self.finality_sender.unbounded_send( - worker_messages::Finality::ImportJustification(who, hash, number, justification), + let res = self.justification_sender.unbounded_send( + worker_messages::ImportJustification(who, hash, number, justification), ); if res.is_err() { @@ -134,26 +131,6 @@ impl ImportQueue for BasicQueue } } - fn import_finality_proof( - &mut self, - who: Origin, - hash: B::Hash, - number: NumberFor, - finality_proof: Vec, - ) { - trace!(target: "sync", "Scheduling finality proof of {}/{} for import", number, hash); - let res = self.finality_sender.unbounded_send( - worker_messages::Finality::ImportFinalityProof(who, hash, number, finality_proof), - ); - - if res.is_err() { - log::error!( - target: "sync", - "import_finality_proof: Background import task is no longer alive" - ); - } - } - fn poll_actions(&mut self, cx: &mut Context, link: &mut dyn Link) { if self.result_port.poll_actions(cx, link).is_err() { log::error!(target: "sync", "poll_actions: Background import task is no longer alive"); @@ -166,17 +143,12 @@ mod worker_messages { use super::*; pub struct ImportBlocks(pub BlockOrigin, pub Vec>); - - pub enum Finality { - ImportJustification(Origin, B::Hash, NumberFor, Justification), - ImportFinalityProof(Origin, B::Hash, NumberFor, Vec), - } + pub struct ImportJustification(pub Origin, pub B::Hash, pub NumberFor, pub Justification); } struct BlockImportWorker { result_sender: BufferedLinkSender, justification_import: Option>, - finality_proof_import: Option>, delay_between_blocks: Duration, metrics: Option, _phantom: PhantomData, @@ -188,17 +160,16 @@ impl BlockImportWorker { verifier: V, block_import: BoxBlockImport, justification_import: Option>, - finality_proof_import: Option>, metrics: Option, ) -> ( impl Future + Send, - TracingUnboundedSender>, + TracingUnboundedSender>, TracingUnboundedSender>, ) { use worker_messages::*; - let (finality_sender, mut finality_port) = - tracing_unbounded("mpsc_import_queue_worker_finality"); + let (justification_sender, mut justification_port) = + tracing_unbounded("mpsc_import_queue_worker_justification"); let (block_import_sender, mut block_import_port) = tracing_unbounded("mpsc_import_queue_worker_blocks"); @@ -206,23 +177,17 @@ impl BlockImportWorker { let mut worker = BlockImportWorker { result_sender, justification_import, - finality_proof_import, delay_between_blocks: Duration::new(0, 0), metrics, _phantom: PhantomData, }; - // Let's initialize `justification_import` and `finality_proof_import`. + // Let's initialize `justification_import` if let Some(justification_import) = worker.justification_import.as_mut() { for (hash, number) in justification_import.on_start() { worker.result_sender.request_justification(&hash, number); } } - if let Some(finality_proof_import) = worker.finality_proof_import.as_mut() { - for (hash, number) in finality_proof_import.on_start() { - worker.result_sender.request_finality_proof(&hash, number); - } - } // The future below has two possible states: // @@ -230,7 +195,7 @@ impl BlockImportWorker { // `Future`, and `block_import` is `None`. // - Something else, in which case `block_import` is `Some` and `importing` is None. // - // Additionally, the task will prioritize processing of finality work messages over + // Additionally, the task will prioritize processing of justification import messages over // block import messages, hence why two distinct channels are used. let mut block_import_verifier = Some((block_import, verifier)); let mut importing = None; @@ -243,28 +208,15 @@ impl BlockImportWorker { return Poll::Ready(()) } - // Grab the next finality action request sent to the import queue. - let finality_work = match Stream::poll_next(Pin::new(&mut finality_port), cx) { - Poll::Ready(Some(msg)) => Some(msg), - Poll::Ready(None) => return Poll::Ready(()), - Poll::Pending => None, - }; - - match finality_work { - Some(Finality::ImportFinalityProof(who, hash, number, proof)) => { - let (_, verif) = block_import_verifier - .as_mut() - .expect("block_import_verifier is always Some; qed"); - - worker.import_finality_proof(verif, who, hash, number, proof); - continue; - } - Some(Finality::ImportJustification(who, hash, number, justification)) => { + // Grab the next justification import request sent to the import queue. + match Stream::poll_next(Pin::new(&mut justification_port), cx) { + Poll::Ready(Some(ImportJustification(who, hash, number, justification))) => { worker.import_justification(who, hash, number, justification); continue; - } - None => {} - } + }, + Poll::Ready(None) => return Poll::Ready(()), + Poll::Pending => {}, + }; // If we are in the process of importing a bunch of blocks, let's resume this // process before doing anything more. @@ -299,7 +251,7 @@ impl BlockImportWorker { } }); - (future, finality_sender, block_import_sender) + (future, justification_sender, block_import_sender) } /// Returns a `Future` that imports the given blocks and sends the results on @@ -324,36 +276,6 @@ impl BlockImportWorker { }) } - fn import_finality_proof>( - &mut self, - verifier: &mut V, - who: Origin, - hash: B::Hash, - number: NumberFor, - finality_proof: Vec - ) { - let started = wasm_timer::Instant::now(); - let result = self.finality_proof_import.as_mut().map(|finality_proof_import| { - finality_proof_import.import_finality_proof(hash, number, finality_proof, verifier) - .map_err(|e| { - debug!( - "Finality proof import failed with {:?} for hash: {:?} number: {:?} coming from node: {:?}", - e, - hash, - number, - who, - ); - }) - }).unwrap_or(Err(())); - - if let Some(metrics) = self.metrics.as_ref() { - metrics.finality_proof_import_time.observe(started.elapsed().as_secs_f64()); - } - - trace!(target: "sync", "Imported finality proof for {}/{}", number, hash); - self.result_sender.finality_proof_imported(who, (hash, number), result); - } - fn import_justification( &mut self, who: Origin, @@ -596,7 +518,7 @@ mod tests { let (result_sender, mut result_port) = buffered_link::buffered_link(); let (mut worker, mut finality_sender, mut block_import_sender) = - BlockImportWorker::new(result_sender, (), Box::new(()), Some(Box::new(())), None, None); + BlockImportWorker::new(result_sender, (), Box::new(()), Some(Box::new(())), None); let mut import_block = |n| { let header = Header { @@ -629,7 +551,7 @@ mod tests { let mut import_justification = || { let hash = Hash::random(); - block_on(finality_sender.send(worker_messages::Finality::ImportJustification( + block_on(finality_sender.send(worker_messages::ImportJustification( libp2p::PeerId::random(), hash, 1, diff --git a/primitives/consensus/common/src/import_queue/buffered_link.rs b/primitives/consensus/common/src/import_queue/buffered_link.rs index a37d4c53c2603..db9bcc8f0ad63 100644 --- a/primitives/consensus/common/src/import_queue/buffered_link.rs +++ b/primitives/consensus/common/src/import_queue/buffered_link.rs @@ -81,8 +81,6 @@ enum BlockImportWorkerMsg { BlocksProcessed(usize, usize, Vec<(Result>, BlockImportError>, B::Hash)>), JustificationImported(Origin, B::Hash, NumberFor, bool), RequestJustification(B::Hash, NumberFor), - FinalityProofImported(Origin, (B::Hash, NumberFor), Result<(B::Hash, NumberFor), ()>), - RequestFinalityProof(B::Hash, NumberFor), } impl Link for BufferedLinkSender { @@ -109,20 +107,6 @@ impl Link for BufferedLinkSender { fn request_justification(&mut self, hash: &B::Hash, number: NumberFor) { let _ = self.tx.unbounded_send(BlockImportWorkerMsg::RequestJustification(hash.clone(), number)); } - - fn finality_proof_imported( - &mut self, - who: Origin, - request_block: (B::Hash, NumberFor), - finalization_result: Result<(B::Hash, NumberFor), ()>, - ) { - let msg = BlockImportWorkerMsg::FinalityProofImported(who, request_block, finalization_result); - let _ = self.tx.unbounded_send(msg); - } - - fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor) { - let _ = self.tx.unbounded_send(BlockImportWorkerMsg::RequestFinalityProof(hash.clone(), number)); - } } /// See [`buffered_link`]. @@ -154,10 +138,6 @@ impl BufferedLinkReceiver { link.justification_imported(who, &hash, number, success), BlockImportWorkerMsg::RequestJustification(hash, number) => link.request_justification(&hash, number), - BlockImportWorkerMsg::FinalityProofImported(who, block, result) => - link.finality_proof_imported(who, block, result), - BlockImportWorkerMsg::RequestFinalityProof(hash, number) => - link.request_finality_proof(&hash, number), } } } diff --git a/primitives/consensus/common/src/lib.rs b/primitives/consensus/common/src/lib.rs index 988aa7a816c42..10fe8a2b31580 100644 --- a/primitives/consensus/common/src/lib.rs +++ b/primitives/consensus/common/src/lib.rs @@ -49,7 +49,7 @@ mod metrics; pub use self::error::Error; pub use block_import::{ BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, BlockCheckParams, - ImportResult, JustificationImport, FinalityProofImport, + ImportResult, JustificationImport, }; pub use select_chain::SelectChain; pub use sp_state_machine::Backend as StateBackend; diff --git a/primitives/consensus/common/src/metrics.rs b/primitives/consensus/common/src/metrics.rs index a35b7c4968f7f..6e6b582e12594 100644 --- a/primitives/consensus/common/src/metrics.rs +++ b/primitives/consensus/common/src/metrics.rs @@ -30,7 +30,6 @@ pub(crate) struct Metrics { pub import_queue_processed: CounterVec, pub block_verification_time: HistogramVec, pub block_verification_and_import_time: Histogram, - pub finality_proof_import_time: Histogram, pub justification_import_time: Histogram, } @@ -63,15 +62,6 @@ impl Metrics { )?, registry, )?, - finality_proof_import_time: register( - Histogram::with_opts( - HistogramOpts::new( - "finality_proof_import_time", - "Time taken to import finality proofs", - ), - )?, - registry, - )?, justification_import_time: register( Histogram::with_opts( HistogramOpts::new( diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index f6989a0df4f0f..5044a1d669137 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -30,7 +30,7 @@ tiny-bip39 = { version = "0.8", optional = true } regex = { version = "1.3.1", optional = true } num-traits = { version = "0.2.8", default-features = false } zeroize = { version = "1.0.0", default-features = false } -secrecy = { version = "0.6.0", default-features = false } +secrecy = { version = "0.7.0", default-features = false } lazy_static = { version = "1.4.0", default-features = false, optional = true } parking_lot = { version = "0.10.0", optional = true } sp-debug-derive = { version = "2.0.0", path = "../debug-derive" } diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index e8483b2ef68c5..e470461d60b8c 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -30,7 +30,7 @@ sp-tracing = { version = "2.0.0", default-features = false, path = "../tracing" log = { version = "0.4.8", optional = true } futures = { version = "0.3.1", features = ["thread-pool"], optional = true } parking_lot = { version = "0.10.0", optional = true } -tracing = { version = "0.1.19", default-features = false } +tracing = { version = "0.1.22", default-features = false } tracing-core = { version = "0.1.17", default-features = false} [features] diff --git a/primitives/panic-handler/Cargo.toml b/primitives/panic-handler/Cargo.toml index acf454b960a7c..0baba8ee7abab 100644 --- a/primitives/panic-handler/Cargo.toml +++ b/primitives/panic-handler/Cargo.toml @@ -15,4 +15,3 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] backtrace = "0.3.38" -log = "0.4.8" diff --git a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml index 59790eb172eb3..eba557de5dbab 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml +++ b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml @@ -19,7 +19,7 @@ sp-io = { version = "2.0.0", default-features = false, path = "../../io" } sp-core = { version = "2.0.0", default-features = false, path = "../../core" } [build-dependencies] -wasm-builder-runner = { version = "2.0.0", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } +substrate-wasm-builder = { version = "3.0.0", path = "../../../utils/wasm-builder" } [features] default = [ "std" ] diff --git a/primitives/runtime-interface/test-wasm-deprecated/build.rs b/primitives/runtime-interface/test-wasm-deprecated/build.rs index 4f111bc993007..8a0b4d7a0c157 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/build.rs +++ b/primitives/runtime-interface/test-wasm-deprecated/build.rs @@ -15,12 +15,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use wasm_builder_runner::WasmBuilder; +use substrate_wasm_builder::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("2.0.1", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .build() diff --git a/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs b/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs index 174cdb8cdf85a..ae0697b2938f4 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs +++ b/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs @@ -26,8 +26,8 @@ use sp_runtime_interface::runtime_interface; #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +/// Wasm binary unwrapped. If built with `SKIP_WASM_BUILD`, the function panics. #[cfg(feature = "std")] -/// Wasm binary unwrapped. If built with `BUILD_DUMMY_WASM_BINARY`, the function panics. pub fn wasm_binary_unwrap() -> &'static [u8] { WASM_BINARY.expect("Development wasm binary is not available. Testing is only \ supported with the flag disabled.") diff --git a/primitives/runtime-interface/test-wasm/Cargo.toml b/primitives/runtime-interface/test-wasm/Cargo.toml index 39c8df976a5ba..3cf36f95145e6 100644 --- a/primitives/runtime-interface/test-wasm/Cargo.toml +++ b/primitives/runtime-interface/test-wasm/Cargo.toml @@ -19,7 +19,7 @@ sp-io = { version = "2.0.0", default-features = false, path = "../../io" } sp-core = { version = "2.0.0", default-features = false, path = "../../core" } [build-dependencies] -wasm-builder-runner = { version = "2.0.0", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } +substrate-wasm-builder = { version = "3.0.0", path = "../../../utils/wasm-builder" } [features] default = [ "std" ] diff --git a/primitives/runtime-interface/test-wasm/build.rs b/primitives/runtime-interface/test-wasm/build.rs index 4f111bc993007..8a0b4d7a0c157 100644 --- a/primitives/runtime-interface/test-wasm/build.rs +++ b/primitives/runtime-interface/test-wasm/build.rs @@ -15,12 +15,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use wasm_builder_runner::WasmBuilder; +use substrate_wasm_builder::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("2.0.1", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .build() diff --git a/primitives/runtime-interface/test-wasm/src/lib.rs b/primitives/runtime-interface/test-wasm/src/lib.rs index 28895df2214d1..6cd37a6c1d142 100644 --- a/primitives/runtime-interface/test-wasm/src/lib.rs +++ b/primitives/runtime-interface/test-wasm/src/lib.rs @@ -30,8 +30,8 @@ use sp_core::{sr25519::Public, wasm_export_functions}; #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +/// Wasm binary unwrapped. If built with `SKIP_WASM_BUILD`, the function panics. #[cfg(feature = "std")] -/// Wasm binary unwrapped. If built with `BUILD_DUMMY_WASM_BINARY`, the function panics. pub fn wasm_binary_unwrap() -> &'static [u8] { WASM_BINARY.expect("Development wasm binary is not available. Testing is only \ supported with the flag disabled.") diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml index d802f9cb6b39a..d6da3db4b69b1 100644 --- a/primitives/runtime-interface/test/Cargo.toml +++ b/primitives/runtime-interface/test/Cargo.toml @@ -20,5 +20,5 @@ sp-state-machine = { version = "0.8.0", path = "../../../primitives/state-machin sp-runtime = { version = "2.0.0", path = "../../runtime" } sp-core = { version = "2.0.0", path = "../../core" } sp-io = { version = "2.0.0", path = "../../io" } -tracing = "0.1.19" +tracing = "0.1.22" tracing-core = "0.1.17" diff --git a/primitives/runtime-interface/tests/ui.rs b/primitives/runtime-interface/tests/ui.rs index 2f7fd6d06bcd3..f23c7291e8ef7 100644 --- a/primitives/runtime-interface/tests/ui.rs +++ b/primitives/runtime-interface/tests/ui.rs @@ -21,7 +21,7 @@ use std::env; #[test] fn ui() { // As trybuild is using `cargo check`, we don't need the real WASM binaries. - env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); + env::set_var("SKIP_WASM_BUILD", "1"); let t = trybuild::TestCases::new(); t.compile_fail("tests/ui/*.rs"); diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 6579a17c77fec..9c3286cd4750d 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -26,7 +26,6 @@ log = { version = "0.4.8", optional = true } paste = "0.1.6" rand = { version = "0.7.2", optional = true } impl-trait-for-tuples = "0.1.3" -sp-inherents = { version = "2.0.0", default-features = false, path = "../inherents" } parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } hash256-std-hasher = { version = "0.15.2", default-features = false } either = { version = "1.5", default-features = false } @@ -50,7 +49,6 @@ std = [ "sp-std/std", "sp-io/std", "serde", - "sp-inherents/std", "parity-util-mem/std", "hash256-std-hasher/std", "either/use_std", diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index e6c707e906edc..ccd50334af660 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -56,9 +56,13 @@ pub mod traits; pub mod transaction_validity; pub mod random_number_generator; mod runtime_string; +mod multiaddress; pub use crate::runtime_string::*; +// Re-export Multiaddress +pub use multiaddress::MultiAddress; + /// Re-export these since they're only "kind of" generic. pub use generic::{DigestItem, Digest}; diff --git a/primitives/runtime/src/multiaddress.rs b/primitives/runtime/src/multiaddress.rs new file mode 100644 index 0000000000000..bb352f7eb5f8e --- /dev/null +++ b/primitives/runtime/src/multiaddress.rs @@ -0,0 +1,66 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! MultiAddress type is a wrapper for multiple downstream account formats. + +use codec::{Encode, Decode}; +use sp_std::vec::Vec; + +/// A multi-format address wrapper for on-chain accounts. +#[derive(Encode, Decode, PartialEq, Eq, Clone, crate::RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Hash))] +pub enum MultiAddress { + /// It's an account ID (pubkey). + Id(AccountId), + /// It's an account index. + Index(#[codec(compact)] AccountIndex), + /// It's some arbitrary raw bytes. + Raw(Vec), + /// It's a 32 byte representation. + Address32([u8; 32]), + /// Its a 20 byte representation. + Address20([u8; 20]), +} + +#[cfg(feature = "std")] +impl std::fmt::Display for MultiAddress +where + AccountId: std::fmt::Debug, + AccountIndex: std::fmt::Debug, +{ + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use sp_core::hexdisplay::HexDisplay; + match self { + MultiAddress::Raw(inner) => write!(f, "MultiAddress::Raw({})", HexDisplay::from(inner)), + MultiAddress::Address32(inner) => write!(f, "MultiAddress::Address32({})", HexDisplay::from(inner)), + MultiAddress::Address20(inner) => write!(f, "MultiAddress::Address20({})", HexDisplay::from(inner)), + _ => write!(f, "{:?}", self), + } + } +} + +impl From for MultiAddress { + fn from(a: AccountId) -> Self { + MultiAddress::Id(a) + } +} + +impl Default for MultiAddress { + fn default() -> Self { + MultiAddress::Id(Default::default()) + } +} diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 4d2b1f062f716..4ce9ac0afa9a3 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -209,6 +209,44 @@ impl Lookup for IdentityLookup { fn lookup(&self, x: T) -> Result { Ok(x) } } +/// A lookup implementation returning the `AccountId` from a `MultiAddress`. +pub struct AccountIdLookup(PhantomData<(AccountId, AccountIndex)>); +impl StaticLookup for AccountIdLookup +where + AccountId: Codec + Clone + PartialEq + Debug, + AccountIndex: Codec + Clone + PartialEq + Debug, + crate::MultiAddress: Codec, +{ + type Source = crate::MultiAddress; + type Target = AccountId; + fn lookup(x: Self::Source) -> Result { + match x { + crate::MultiAddress::Id(i) => Ok(i), + _ => Err(LookupError), + } + } + fn unlookup(x: Self::Target) -> Self::Source { + crate::MultiAddress::Id(x) + } +} + +/// Perform a StaticLookup where there are multiple lookup sources of the same type. +impl StaticLookup for (A, B) +where + A: StaticLookup, + B: StaticLookup, +{ + type Source = A::Source; + type Target = A::Target; + + fn lookup(x: Self::Source) -> Result { + A::lookup(x.clone()).or_else(|_| B::lookup(x)) + } + fn unlookup(x: Self::Target) -> Self::Source { + A::unlookup(x) + } +} + /// Extensible conversion trait. Generic over both source and destination types. pub trait Convert { /// Make conversion. diff --git a/primitives/tracing/Cargo.toml b/primitives/tracing/Cargo.toml index 1000952b39fd4..ba370f46b9b6a 100644 --- a/primitives/tracing/Cargo.toml +++ b/primitives/tracing/Cargo.toml @@ -20,7 +20,7 @@ targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] [dependencies] sp-std = { version = "2.0.0", path = "../std", default-features = false} codec = { version = "1.3.1", package = "parity-scale-codec", default-features = false, features = ["derive"]} -tracing = { version = "0.1.21", default-features = false } +tracing = { version = "0.1.22", default-features = false } tracing-core = { version = "0.1.17", default-features = false } log = { version = "0.4.8", optional = true } tracing-subscriber = { version = "0.2.10", optional = true, features = ["tracing-log"] } diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index cb6147adf25c6..cf1a4bcddd5b3 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -56,7 +56,7 @@ sc-executor = { version = "0.8.0", path = "../../client/executor" } substrate-test-runtime-client = { version = "2.0.0", path = "./client" } [build-dependencies] -wasm-builder-runner = { version = "2.0.0", package = "substrate-wasm-builder-runner", path = "../../utils/wasm-builder-runner" } +substrate-wasm-builder = { version = "3.0.0", path = "../../utils/wasm-builder" } [features] default = [ diff --git a/test-utils/runtime/build.rs b/test-utils/runtime/build.rs index 834551a7ba12d..5c9af20528a0b 100644 --- a/test-utils/runtime/build.rs +++ b/test-utils/runtime/build.rs @@ -15,12 +15,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use wasm_builder_runner::WasmBuilder; +use substrate_wasm_builder::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("2.0.1", "../../utils/wasm-builder") .export_heap_base() // Note that we set the stack-size to 1MB explicitly even though it is set // to this value by default. This is because some of our tests (`restoration_of_globals`) diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index e772a28ee33a2..2024467771057 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -66,8 +66,8 @@ pub type AuraId = sp_consensus_aura::sr25519::AuthorityId; #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +/// Wasm binary unwrapped. If built with `SKIP_WASM_BUILD`, the function panics. #[cfg(feature = "std")] -/// Wasm binary unwrapped. If built with `BUILD_DUMMY_WASM_BINARY`, the function panics. pub fn wasm_binary_unwrap() -> &'static [u8] { WASM_BINARY.expect("Development wasm binary is not available. Testing is only \ supported with the flag disabled.") diff --git a/utils/browser/Cargo.toml b/utils/browser/Cargo.toml index 9efc8c396680e..4f35cd9880393 100644 --- a/utils/browser/Cargo.toml +++ b/utils/browser/Cargo.toml @@ -21,7 +21,7 @@ console_error_panic_hook = "0.1.6" console_log = "0.1.2" js-sys = "0.3.34" wasm-bindgen = "0.2.57" -wasm-bindgen-futures = "0.4.7" +wasm-bindgen-futures = "0.4.18" kvdb-web = "0.7" sp-database = { version = "2.0.0", path = "../../primitives/database" } sc-informant = { version = "0.8.0", path = "../../client/informant" } diff --git a/utils/frame/benchmarking-cli/src/template.hbs b/utils/frame/benchmarking-cli/src/template.hbs index 7f7e2d6dcb995..fd066b1a3a8ae 100644 --- a/utils/frame/benchmarking-cli/src/template.hbs +++ b/utils/frame/benchmarking-cli/src/template.hbs @@ -1,5 +1,6 @@ {{header}} -//! Weights for {{pallet}} +//! Autogenerated weights for {{pallet}} +//! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}} //! DATE: {{date}}, STEPS: {{cmd.steps}}, REPEAT: {{cmd.repeat}}, LOW RANGE: {{cmd.lowest_range_values}}, HIGH RANGE: {{cmd.highest_range_values}} //! EXECUTION: {{cmd.execution}}, WASM-EXECUTION: {{cmd.wasm_execution}}, CHAIN: {{cmd.chain}}, DB CACHE: {{cmd.db_cache}} diff --git a/utils/wasm-builder-runner/Cargo.toml b/utils/wasm-builder-runner/Cargo.toml deleted file mode 100644 index 2c54a5ec3a4d6..0000000000000 --- a/utils/wasm-builder-runner/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "substrate-wasm-builder-runner" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Runner for substrate-wasm-builder" -edition = "2018" -readme = "README.md" -repository = "https://github.com/paritytech/substrate/" -license = "Apache-2.0" -homepage = "https://substrate.dev" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] diff --git a/utils/wasm-builder-runner/README.md b/utils/wasm-builder-runner/README.md deleted file mode 100644 index 1b9e2b08ca444..0000000000000 --- a/utils/wasm-builder-runner/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## WASM builder runner - -Since cargo contains many bugs when it comes to correct dependency and feature -resolution, we need this little tool. See for -more information. - -It will create a project that will call `substrate-wasm-builder` to prevent any dependencies -from `substrate-wasm-builder` influencing the main project's dependencies. - -For more information see - -License: GPL-3.0 diff --git a/utils/wasm-builder-runner/src/lib.rs b/utils/wasm-builder-runner/src/lib.rs deleted file mode 100644 index 04e06495c69b4..0000000000000 --- a/utils/wasm-builder-runner/src/lib.rs +++ /dev/null @@ -1,498 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! # WASM builder runner -//! -//! Since cargo contains many bugs when it comes to correct dependency and feature -//! resolution, we need this little tool. See for -//! more information. -//! -//! It will create a project that will call `substrate-wasm-builder` to prevent any dependencies -//! from `substrate-wasm-builder` influencing the main project's dependencies. -//! -//! For more information see - -use std::{ - env, process::{Command, self}, fs, path::{PathBuf, Path}, hash::{Hash, Hasher}, - collections::hash_map::DefaultHasher, -}; - -/// Environment variable that tells us to skip building the WASM binary. -const SKIP_BUILD_ENV: &str = "SKIP_WASM_BUILD"; - -/// Environment variable that tells us to create a dummy WASM binary. -/// -/// This is useful for `cargo check` to speed-up the compilation. -/// -/// # Caution -/// -/// Enabling this option will just provide `&[]` as WASM binary. -const DUMMY_WASM_BINARY_ENV: &str = "BUILD_DUMMY_WASM_BINARY"; - -/// Environment variable that makes sure the WASM build is triggered. -const FORCE_WASM_BUILD_ENV: &str = "FORCE_WASM_BUILD"; - -/// Replace all backslashes with slashes. -fn replace_back_slashes(path: T) -> String { - path.to_string().replace("\\", "/") -} - -/// Returns the manifest dir from the `CARGO_MANIFEST_DIR` env. -fn get_manifest_dir() -> PathBuf { - env::var("CARGO_MANIFEST_DIR") - .expect("`CARGO_MANIFEST_DIR` is always set for `build.rs` files; qed") - .into() -} - -/// First step of the [`WasmBuilder`] to select the project to build. -pub struct WasmBuilderSelectProject { - /// This parameter just exists to make it impossible to construct - /// this type outside of this crate. - _ignore: (), -} - -impl WasmBuilderSelectProject { - /// Use the current project as project for building the WASM binary. - /// - /// # Panics - /// - /// Panics if the `CARGO_MANIFEST_DIR` variable is not set. This variable - /// is always set by `Cargo` in `build.rs` files. - pub fn with_current_project(self) -> WasmBuilderSelectSource { - WasmBuilderSelectSource(get_manifest_dir().join("Cargo.toml")) - } - - /// Use the given `path` as project for building the WASM binary. - /// - /// Returns an error if the given `path` does not points to a `Cargo.toml`. - pub fn with_project( - self, - path: impl Into, - ) -> Result { - let path = path.into(); - - if path.ends_with("Cargo.toml") { - Ok(WasmBuilderSelectSource(path)) - } else { - Err("Project path must point to the `Cargo.toml` of the project") - } - } -} - -/// Second step of the [`WasmBuilder`] to set the source of the `wasm-builder`. -pub struct WasmBuilderSelectSource(PathBuf); - -impl WasmBuilderSelectSource { - /// Use the given `path` as source for `wasm-builder`. - /// - /// The `path` must be relative and point to the directory that contains the `Cargo.toml` for - /// `wasm-builder`. - pub fn with_wasm_builder_from_path(self, path: &'static str) -> WasmBuilder { - WasmBuilder { - source: WasmBuilderSource::Path(path), - rust_flags: Vec::new(), - file_name: None, - project_cargo_toml: self.0, - } - } - - /// Use the given `repo` and `rev` as source for `wasm-builder`. - pub fn with_wasm_builder_from_git(self, repo: &'static str, rev: &'static str) -> WasmBuilder { - WasmBuilder { - source: WasmBuilderSource::Git { repo, rev }, - rust_flags: Vec::new(), - file_name: None, - project_cargo_toml: self.0, - } - } - - /// Use the given `version` to fetch `wasm-builder` source from crates.io. - pub fn with_wasm_builder_from_crates(self, version: &'static str) -> WasmBuilder { - WasmBuilder { - source: WasmBuilderSource::Crates(version), - rust_flags: Vec::new(), - file_name: None, - project_cargo_toml: self.0, - } - } - - /// Use the given `version` to fetch `wasm-builder` source from crates.io or use - /// the given `path` as source. - /// - /// The `path` must be relative and point to the directory that contains the `Cargo.toml` for - /// `wasm-builder`. - pub fn with_wasm_builder_from_crates_or_path( - self, - version: &'static str, - path: &'static str, - ) -> WasmBuilder { - WasmBuilder { - source: WasmBuilderSource::CratesOrPath { version, path }, - rust_flags: Vec::new(), - file_name: None, - project_cargo_toml: self.0, - } - } - - /// Use the given `source` as source for `wasm-builder`. - pub fn with_wasm_builder_source(self, source: WasmBuilderSource) -> WasmBuilder { - WasmBuilder { - source, - rust_flags: Vec::new(), - file_name: None, - project_cargo_toml: self.0, - } - } -} - -/// The builder for building a wasm binary. -/// -/// The builder itself is seperated into multiple structs to make the setup type safe. -/// -/// Building a wasm binary: -/// -/// 1. Call [`WasmBuilder::new`] to create a new builder. -/// 2. Select the project to build using the methods of [`WasmBuilderSelectProject`]. -/// 3. Select the source of the `wasm-builder` crate using the methods of -/// [`WasmBuilderSelectSource`]. -/// 4. Set additional `RUST_FLAGS` or a different name for the file containing the WASM code -/// using methods of [`WasmBuilder`]. -/// 5. Build the WASM binary using [`Self::build`]. -pub struct WasmBuilder { - /// Where should we pull the `wasm-builder` crate from. - source: WasmBuilderSource, - /// Flags that should be appended to `RUST_FLAGS` env variable. - rust_flags: Vec, - /// The name of the file that is being generated in `OUT_DIR`. - /// - /// Defaults to `wasm_binary.rs`. - file_name: Option, - /// The path to the `Cargo.toml` of the project that should be build - /// for wasm. - project_cargo_toml: PathBuf, -} - -impl WasmBuilder { - /// Create a new instance of the builder. - pub fn new() -> WasmBuilderSelectProject { - WasmBuilderSelectProject { - _ignore: (), - } - } - - /// Enable exporting `__heap_base` as global variable in the WASM binary. - /// - /// This adds `-Clink-arg=--export=__heap_base` to `RUST_FLAGS`. - pub fn export_heap_base(mut self) -> Self { - self.rust_flags.push("-Clink-arg=--export=__heap_base".into()); - self - } - - /// Set the name of the file that will be generated in `OUT_DIR`. - /// - /// This file needs to be included to get access to the build WASM binary. - /// - /// If this function is not called, `file_name` defaults to `wasm_binary.rs` - pub fn set_file_name(mut self, file_name: impl Into) -> Self { - self.file_name = Some(file_name.into()); - self - } - - /// Instruct the linker to import the memory into the WASM binary. - /// - /// This adds `-C link-arg=--import-memory` to `RUST_FLAGS`. - pub fn import_memory(mut self) -> Self { - self.rust_flags.push("-C link-arg=--import-memory".into()); - self - } - - /// Append the given `flag` to `RUST_FLAGS`. - /// - /// `flag` is appended as is, so it needs to be a valid flag. - pub fn append_to_rust_flags(mut self, flag: impl Into) -> Self { - self.rust_flags.push(flag.into()); - self - } - - /// Build the WASM binary. - pub fn build(self) { - let out_dir = PathBuf::from(env::var("OUT_DIR").expect("`OUT_DIR` is set by cargo!")); - let file_path = out_dir.join(self.file_name.unwrap_or_else(|| "wasm_binary.rs".into())); - - if check_skip_build() { - // If we skip the build, we still want to make sure to be called when an env variable - // changes - generate_rerun_if_changed_instructions(); - - provide_dummy_wasm_binary(&file_path, true); - - return; - } - - // Hash the path to the project cargo toml. - let mut hasher = DefaultHasher::new(); - self.project_cargo_toml.hash(&mut hasher); - - let project_name = env::var("CARGO_PKG_NAME").expect("`CARGO_PKG_NAME` is set by cargo!"); - // Make sure the `wasm-builder-runner` path is unique by concatenating the name of the - // project that is compiling the WASM binary with the hash of the path to the project that - // should be compiled as WASM binary. - let project_folder = get_workspace_root() - .join(format!("{}{}", project_name, hasher.finish())); - - if check_provide_dummy_wasm_binary() { - provide_dummy_wasm_binary(&file_path, false); - } else { - create_project( - &project_folder, - &file_path, - self.source, - &self.project_cargo_toml, - &self.rust_flags.into_iter().map(|f| format!("{} ", f)).collect::(), - ); - run_project(&project_folder); - } - - // As last step we need to generate our `rerun-if-changed` stuff. If a build fails, we don't - // want to spam the output! - generate_rerun_if_changed_instructions(); - } -} - -/// The `wasm-builder` dependency source. -pub enum WasmBuilderSource { - /// The relative path to the source code from the current manifest dir. - Path(&'static str), - /// The git repository that contains the source code. - Git { - repo: &'static str, - rev: &'static str, - }, - /// Use the given version released on crates.io. - Crates(&'static str), - /// Use the given version released on crates.io or from the given path. - CratesOrPath { - version: &'static str, - path: &'static str, - } -} - -impl WasmBuilderSource { - /// Convert to a valid cargo source declaration. - /// - /// `absolute_path` - The manifest dir. - fn to_cargo_source(&self, manifest_dir: &Path) -> String { - match self { - WasmBuilderSource::Path(path) => { - replace_back_slashes(format!("path = \"{}\"", manifest_dir.join(path).display())) - } - WasmBuilderSource::Git { repo, rev } => { - format!("git = \"{}\", rev=\"{}\"", repo, rev) - } - WasmBuilderSource::Crates(version) => { - format!("version = \"{}\"", version) - } - WasmBuilderSource::CratesOrPath { version, path } => { - replace_back_slashes( - format!( - "path = \"{}\", version = \"{}\"", - manifest_dir.join(path).display(), - version - ) - ) - } - } - } -} - -/// Build the currently built project as WASM binary and extend `RUSTFLAGS` with the given rustflags. -/// -/// For more information, see [`build_current_project`]. -#[deprecated( - since = "1.0.5", - note = "Please switch to [`WasmBuilder`]", -)] -pub fn build_current_project_with_rustflags( - file_name: &str, - wasm_builder_source: WasmBuilderSource, - default_rust_flags: &str, -) { - WasmBuilder::new() - .with_current_project() - .with_wasm_builder_source(wasm_builder_source) - .append_to_rust_flags(default_rust_flags) - .set_file_name(file_name) - .build() -} - -/// Build the currently built project as WASM binary. -/// -/// The current project is determined using the `CARGO_MANIFEST_DIR` environment variable. -/// -/// `file_name` - The name of the file being generated in the `OUT_DIR`. The file contains the -/// constant `WASM_BINARY` which contains the build wasm binary. -/// `wasm_builder_path` - Path to the wasm-builder project, relative to `CARGO_MANIFEST_DIR`. -#[deprecated( - since = "1.0.5", - note = "Please switch to [`WasmBuilder`]", -)] -pub fn build_current_project(file_name: &str, wasm_builder_source: WasmBuilderSource) { - #[allow(deprecated)] - build_current_project_with_rustflags(file_name, wasm_builder_source, ""); -} - -/// Returns the root path of the wasm-builder workspace. -/// -/// The wasm-builder workspace contains all wasm-builder's projects. -fn get_workspace_root() -> PathBuf { - let out_dir_env = env::var("OUT_DIR").expect("`OUT_DIR` is set by cargo!"); - let mut out_dir = PathBuf::from(&out_dir_env); - - loop { - match out_dir.parent() { - Some(parent) if out_dir.ends_with("build") => return parent.join("wbuild-runner"), - _ => if !out_dir.pop() { - break; - } - } - } - - panic!("Could not find target dir in: {}", out_dir_env) -} - -fn create_project( - project_folder: &Path, - file_path: &Path, - wasm_builder_source: WasmBuilderSource, - cargo_toml_path: &Path, - default_rustflags: &str, -) { - fs::create_dir_all(project_folder.join("src")) - .expect("WASM build runner dir create can not fail; qed"); - - write_file_if_changed( - project_folder.join("Cargo.toml"), - format!( - r#" - [package] - name = "wasm-build-runner-impl" - version = "1.0.0" - edition = "2018" - - [dependencies] - substrate-wasm-builder = {{ {wasm_builder_source} }} - - [workspace] - "#, - wasm_builder_source = wasm_builder_source.to_cargo_source(&get_manifest_dir()), - ), - ); - - write_file_if_changed( - project_folder.join("src/main.rs"), - format!( - r#" - //! This is automatically generated code by `substrate-wasm-builder`. - - use substrate_wasm_builder::build_project_with_default_rustflags; - - fn main() {{ - build_project_with_default_rustflags( - "{file_path}", - "{cargo_toml_path}", - "{default_rustflags}", - ) - }} - "#, - file_path = replace_back_slashes(file_path.display()), - cargo_toml_path = replace_back_slashes(cargo_toml_path.display()), - default_rustflags = default_rustflags, - ), - ); -} - -fn run_project(project_folder: &Path) { - let cargo = env::var("CARGO").expect("`CARGO` env variable is always set when executing `build.rs`."); - let mut cmd = Command::new(cargo); - cmd.arg("run").arg(format!("--manifest-path={}", project_folder.join("Cargo.toml").display())); - - if env::var("DEBUG") != Ok(String::from("true")) { - cmd.arg("--release"); - } - - // Make sure we always run the `wasm-builder` project for the `HOST` architecture. - let host_triple = env::var("HOST").expect("`HOST` is always set when executing `build.rs`."); - cmd.arg(&format!("--target={}", host_triple)); - - // Unset the `CARGO_TARGET_DIR` to prevent a cargo deadlock (cargo locks a target dir exclusive). - // The runner project is created in `CARGO_TARGET_DIR` and executing it will create a sub target - // directory inside of `CARGO_TARGET_DIR`. - cmd.env_remove("CARGO_TARGET_DIR"); - - if !cmd.status().map(|s| s.success()).unwrap_or(false) { - // Don't spam the output with backtraces when a build failed! - process::exit(1); - } -} - -/// Generate the name of the skip build environment variable for the current crate. -fn generate_crate_skip_build_env_name() -> String { - format!( - "SKIP_{}_WASM_BUILD", - env::var("CARGO_PKG_NAME").expect("Package name is set").to_uppercase().replace('-', "_"), - ) -} - -/// Checks if the build of the WASM binary should be skipped. -fn check_skip_build() -> bool { - env::var(SKIP_BUILD_ENV).is_ok() || env::var(generate_crate_skip_build_env_name()).is_ok() -} - -/// Check if we should provide a dummy WASM binary. -fn check_provide_dummy_wasm_binary() -> bool { - env::var(DUMMY_WASM_BINARY_ENV).is_ok() -} - -/// Provide the dummy WASM binary -/// -/// If `skip_build` is `true`, it will only generate the wasm binary if it doesn't exist. -fn provide_dummy_wasm_binary(file_path: &Path, skip_build: bool) { - if !skip_build || !file_path.exists() { - write_file_if_changed( - file_path.into(), - "pub const WASM_BINARY: Option<&[u8]> = None;\ - pub const WASM_BINARY_BLOATY: Option<&[u8]> = None;".into(), - ); - } -} - -/// Generate the `rerun-if-changed` instructions for cargo to make sure that the WASM binary is -/// rebuilt when needed. -fn generate_rerun_if_changed_instructions() { - // Make sure that the `build.rs` is called again if one of the following env variables changes. - println!("cargo:rerun-if-env-changed={}", SKIP_BUILD_ENV); - println!("cargo:rerun-if-env-changed={}", DUMMY_WASM_BINARY_ENV); - println!("cargo:rerun-if-env-changed={}", FORCE_WASM_BUILD_ENV); - println!("cargo:rerun-if-env-changed={}", generate_crate_skip_build_env_name()); -} - -/// Write to the given `file` if the `content` is different. -fn write_file_if_changed(file: PathBuf, content: String) { - if fs::read_to_string(&file).ok().as_ref() != Some(&content) { - fs::write(&file, content).unwrap_or_else(|_| panic!("Writing `{}` can not fail!", file.display())); - } -} diff --git a/utils/wasm-builder/Cargo.toml b/utils/wasm-builder/Cargo.toml index e9dd1a97b89e4..199e26b509e2e 100644 --- a/utils/wasm-builder/Cargo.toml +++ b/utils/wasm-builder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "substrate-wasm-builder" -version = "2.0.1" +version = "3.0.0" authors = ["Parity Technologies "] description = "Utility for building WASM binaries" edition = "2018" @@ -14,12 +14,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] build-helper = "0.1.1" -cargo_metadata = "0.10.0" +cargo_metadata = "0.12.0" tempfile = "3.1.0" toml = "0.5.4" walkdir = "2.3.1" -fs2 = "0.4.3" wasm-gc-api = "0.1.11" atty = "0.2.13" -itertools = "0.8.2" ansi_term = "0.12.1" diff --git a/utils/wasm-builder/README.md b/utils/wasm-builder/README.md index 1e24d2cebab32..3868faf1acab5 100644 --- a/utils/wasm-builder/README.md +++ b/utils/wasm-builder/README.md @@ -8,20 +8,23 @@ The Wasm builder is a tool that integrates the process of building the WASM bina A project that should be compiled as a Wasm binary needs to: 1. Add a `build.rs` file. -2. Add `substrate-wasm-builder` as dependency into `build-dependencies`. +2. Add `wasm-builder` as dependency into `build-dependencies`. The `build.rs` file needs to contain the following code: ```rust -use wasm_builder_runner::{build_current_project, WasmBuilderSource}; +use substrate_wasm_builder::WasmBuilder; fn main() { - build_current_project( - // The name of the file being generated in out-dir. - "wasm_binary.rs", - // How to include wasm-builder, in this case from crates.io. - WasmBuilderSource::Crates("1.0.0"), - ); + WasmBuilder::new() + // Tell the builder to build the project (crate) this `build.rs` is part of. + .with_current_project() + // Make sure to export the `heap_base` global, this is required by Substrate + .export_heap_base() + // Build the Wasm file so that it imports the memory (need to be provided by at instantiation) + .import_memory() + // Build it. + .build() } ``` @@ -32,9 +35,10 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); ``` This will include the generated Wasm binary as two constants `WASM_BINARY` and `WASM_BINARY_BLOATY`. -The former is a compact Wasm binary and the latter is not compacted. +The former is a compact Wasm binary and the latter is the Wasm binary as being generated by the compiler. +Both variables have `Option<&'static [u8]>` as type. -### Feature +### Features Wasm builder supports to enable cargo features while building the Wasm binary. By default it will enable all features in the wasm build that are enabled for the native build except the @@ -46,19 +50,19 @@ Wasm binary. If this feature is not present, it will not be enabled. By using environment variables, you can configure which Wasm binaries are built and how: -- `SKIP_WASM_BUILD` - Skips building any wasm binary. This is useful when only native should be recompiled. -- `BUILD_DUMMY_WASM_BINARY` - Builds dummy wasm binaries. These dummy binaries are empty and useful - for `cargo check` runs. -- `WASM_BUILD_TYPE` - Sets the build type for building wasm binaries. Supported values are `release` or `debug`. +- `SKIP_WASM_BUILD` - Skips building any Wasm binary. This is useful when only native should be recompiled. + If this is the first run and there doesn't exist a Wasm binary, this will set both + variables to `None`. +- `WASM_BUILD_TYPE` - Sets the build type for building Wasm binaries. Supported values are `release` or `debug`. By default the build type is equal to the build type used by the main build. -- `FORCE_WASM_BUILD` - Can be set to force a wasm build. On subsequent calls the value of the variable - needs to change. As wasm builder instructs `cargo` to watch for file changes +- `FORCE_WASM_BUILD` - Can be set to force a Wasm build. On subsequent calls the value of the variable + needs to change. As wasm-builder instructs `cargo` to watch for file changes this environment variable should only be required in certain circumstances. - `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the wasm binary. - `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build. -- `WASM_TARGET_DIRECTORY` - Will copy any build wasm binary to the given directory. The path needs +- `WASM_TARGET_DIRECTORY` - Will copy any build Wasm binary to the given directory. The path needs to be absolute. -- `WASM_BUILD_TOOLCHAIN` - The toolchain that should be used to build the wasm binaries. The +- `WASM_BUILD_TOOLCHAIN` - The toolchain that should be used to build the Wasm binaries. The format needs to be the same as used by cargo, e.g. `nightly-2020-02-20`. Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. diff --git a/utils/wasm-builder/src/builder.rs b/utils/wasm-builder/src/builder.rs new file mode 100644 index 0000000000000..75e1d80572012 --- /dev/null +++ b/utils/wasm-builder/src/builder.rs @@ -0,0 +1,245 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::{env, path::{PathBuf, Path}, process}; + +/// Returns the manifest dir from the `CARGO_MANIFEST_DIR` env. +fn get_manifest_dir() -> PathBuf { + env::var("CARGO_MANIFEST_DIR") + .expect("`CARGO_MANIFEST_DIR` is always set for `build.rs` files; qed") + .into() +} + +/// First step of the [`WasmBuilder`] to select the project to build. +pub struct WasmBuilderSelectProject { + /// This parameter just exists to make it impossible to construct + /// this type outside of this crate. + _ignore: (), +} + +impl WasmBuilderSelectProject { + /// Use the current project as project for building the WASM binary. + /// + /// # Panics + /// + /// Panics if the `CARGO_MANIFEST_DIR` variable is not set. This variable + /// is always set by `Cargo` in `build.rs` files. + pub fn with_current_project(self) -> WasmBuilder { + WasmBuilder { + rust_flags: Vec::new(), + file_name: None, + project_cargo_toml: get_manifest_dir().join("Cargo.toml"), + } + } + + /// Use the given `path` as project for building the WASM binary. + /// + /// Returns an error if the given `path` does not points to a `Cargo.toml`. + pub fn with_project( + self, + path: impl Into, + ) -> Result { + let path = path.into(); + + if path.ends_with("Cargo.toml") && path.exists() { + Ok(WasmBuilder { + rust_flags: Vec::new(), + file_name: None, + project_cargo_toml: path, + }) + } else { + Err("Project path must point to the `Cargo.toml` of the project") + } + } +} + +/// The builder for building a wasm binary. +/// +/// The builder itself is separated into multiple structs to make the setup type safe. +/// +/// Building a wasm binary: +/// +/// 1. Call [`WasmBuilder::new`] to create a new builder. +/// 2. Select the project to build using the methods of [`WasmBuilderSelectProject`]. +/// 3. Set additional `RUST_FLAGS` or a different name for the file containing the WASM code +/// using methods of [`WasmBuilder`]. +/// 4. Build the WASM binary using [`Self::build`]. +pub struct WasmBuilder { + /// Flags that should be appended to `RUST_FLAGS` env variable. + rust_flags: Vec, + /// The name of the file that is being generated in `OUT_DIR`. + /// + /// Defaults to `wasm_binary.rs`. + file_name: Option, + /// The path to the `Cargo.toml` of the project that should be built + /// for wasm. + project_cargo_toml: PathBuf, +} + +impl WasmBuilder { + /// Create a new instance of the builder. + pub fn new() -> WasmBuilderSelectProject { + WasmBuilderSelectProject { + _ignore: (), + } + } + + /// Enable exporting `__heap_base` as global variable in the WASM binary. + /// + /// This adds `-Clink-arg=--export=__heap_base` to `RUST_FLAGS`. + pub fn export_heap_base(mut self) -> Self { + self.rust_flags.push("-Clink-arg=--export=__heap_base".into()); + self + } + + /// Set the name of the file that will be generated in `OUT_DIR`. + /// + /// This file needs to be included to get access to the build WASM binary. + /// + /// If this function is not called, `file_name` defaults to `wasm_binary.rs` + pub fn set_file_name(mut self, file_name: impl Into) -> Self { + self.file_name = Some(file_name.into()); + self + } + + /// Instruct the linker to import the memory into the WASM binary. + /// + /// This adds `-C link-arg=--import-memory` to `RUST_FLAGS`. + pub fn import_memory(mut self) -> Self { + self.rust_flags.push("-C link-arg=--import-memory".into()); + self + } + + /// Append the given `flag` to `RUST_FLAGS`. + /// + /// `flag` is appended as is, so it needs to be a valid flag. + pub fn append_to_rust_flags(mut self, flag: impl Into) -> Self { + self.rust_flags.push(flag.into()); + self + } + + /// Build the WASM binary. + pub fn build(self) { + let out_dir = PathBuf::from(env::var("OUT_DIR").expect("`OUT_DIR` is set by cargo!")); + let file_path = out_dir.join(self.file_name.unwrap_or_else(|| "wasm_binary.rs".into())); + + if check_skip_build() { + // If we skip the build, we still want to make sure to be called when an env variable + // changes + generate_rerun_if_changed_instructions(); + + provide_dummy_wasm_binary_if_not_exist(&file_path); + + return; + } + + build_project( + file_path, + self.project_cargo_toml, + self.rust_flags.into_iter().map(|f| format!("{} ", f)).collect(), + ); + + // As last step we need to generate our `rerun-if-changed` stuff. If a build fails, we don't + // want to spam the output! + generate_rerun_if_changed_instructions(); + } +} + +/// Generate the name of the skip build environment variable for the current crate. +fn generate_crate_skip_build_env_name() -> String { + format!( + "SKIP_{}_WASM_BUILD", + env::var("CARGO_PKG_NAME").expect("Package name is set").to_uppercase().replace('-', "_"), + ) +} + +/// Checks if the build of the WASM binary should be skipped. +fn check_skip_build() -> bool { + env::var(crate::SKIP_BUILD_ENV).is_ok() || env::var(generate_crate_skip_build_env_name()).is_ok() +} + +/// Provide a dummy WASM binary if there doesn't exist one. +fn provide_dummy_wasm_binary_if_not_exist(file_path: &Path) { + if !file_path.exists() { + crate::write_file_if_changed( + file_path, + "pub const WASM_BINARY: Option<&[u8]> = None;\ + pub const WASM_BINARY_BLOATY: Option<&[u8]> = None;", + ); + } +} + +/// Generate the `rerun-if-changed` instructions for cargo to make sure that the WASM binary is +/// rebuilt when needed. +fn generate_rerun_if_changed_instructions() { + // Make sure that the `build.rs` is called again if one of the following env variables changes. + println!("cargo:rerun-if-env-changed={}", crate::SKIP_BUILD_ENV); + println!("cargo:rerun-if-env-changed={}", crate::FORCE_WASM_BUILD_ENV); + println!("cargo:rerun-if-env-changed={}", generate_crate_skip_build_env_name()); +} + +/// Build the currently built project as wasm binary. +/// +/// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable. +/// +/// `file_name` - The name + path of the file being generated. The file contains the +/// constant `WASM_BINARY`, which contains the built WASM binary. +/// `project_cargo_toml` - The path to the `Cargo.toml` of the project that should be built. +/// `default_rustflags` - Default `RUSTFLAGS` that will always be set for the build. +fn build_project( + file_name: PathBuf, + project_cargo_toml: PathBuf, + default_rustflags: String, +) { + let cargo_cmd = match crate::prerequisites::check() { + Ok(cmd) => cmd, + Err(err_msg) => { + eprintln!("{}", err_msg); + process::exit(1); + }, + }; + + let (wasm_binary, bloaty) = crate::wasm_project::create_and_compile( + &project_cargo_toml, + &default_rustflags, + cargo_cmd, + ); + + let (wasm_binary, wasm_binary_bloaty) = if let Some(wasm_binary) = wasm_binary { + ( + wasm_binary.wasm_binary_path_escaped(), + bloaty.wasm_binary_bloaty_path_escaped(), + ) + } else { + ( + bloaty.wasm_binary_bloaty_path_escaped(), + bloaty.wasm_binary_bloaty_path_escaped(), + ) + }; + + crate::write_file_if_changed( + file_name, + format!( + r#" + pub const WASM_BINARY: Option<&[u8]> = Some(include_bytes!("{wasm_binary}")); + pub const WASM_BINARY_BLOATY: Option<&[u8]> = Some(include_bytes!("{wasm_binary_bloaty}")); + "#, + wasm_binary = wasm_binary, + wasm_binary_bloaty = wasm_binary_bloaty, + ), + ); +} diff --git a/utils/wasm-builder/src/lib.rs b/utils/wasm-builder/src/lib.rs index aa63e9596e190..573afbfcb6dc5 100644 --- a/utils/wasm-builder/src/lib.rs +++ b/utils/wasm-builder/src/lib.rs @@ -25,20 +25,23 @@ //! A project that should be compiled as a Wasm binary needs to: //! //! 1. Add a `build.rs` file. -//! 2. Add `substrate-wasm-builder` as dependency into `build-dependencies`. +//! 2. Add `wasm-builder` as dependency into `build-dependencies`. //! //! The `build.rs` file needs to contain the following code: //! -//! ```ignore -//! use wasm_builder_runner::{build_current_project, WasmBuilderSource}; +//! ```no_run +//! use substrate_wasm_builder::WasmBuilder; //! //! fn main() { -//! build_current_project( -//! // The name of the file being generated in out-dir. -//! "wasm_binary.rs", -//! // How to include wasm-builder, in this case from crates.io. -//! WasmBuilderSource::Crates("1.0.0"), -//! ); +//! WasmBuilder::new() +//! // Tell the builder to build the project (crate) this `build.rs` is part of. +//! .with_current_project() +//! // Make sure to export the `heap_base` global, this is required by Substrate +//! .export_heap_base() +//! // Build the Wasm file so that it imports the memory (need to be provided by at instantiation) +//! .import_memory() +//! // Build it. +//! .build() //! } //! ``` //! @@ -49,7 +52,8 @@ //! ``` //! //! This will include the generated Wasm binary as two constants `WASM_BINARY` and `WASM_BINARY_BLOATY`. -//! The former is a compact Wasm binary and the latter is not compacted. +//! The former is a compact Wasm binary and the latter is the Wasm binary as being generated by the compiler. +//! Both variables have `Option<&'static [u8]>` as type. //! //! ### Feature //! @@ -63,19 +67,19 @@ //! //! By using environment variables, you can configure which Wasm binaries are built and how: //! -//! - `SKIP_WASM_BUILD` - Skips building any wasm binary. This is useful when only native should be recompiled. -//! - `BUILD_DUMMY_WASM_BINARY` - Builds dummy wasm binaries. These dummy binaries are empty and useful -//! for `cargo check` runs. -//! - `WASM_BUILD_TYPE` - Sets the build type for building wasm binaries. Supported values are `release` or `debug`. +//! - `SKIP_WASM_BUILD` - Skips building any Wasm binary. This is useful when only native should be recompiled. +//! If this is the first run and there doesn't exist a Wasm binary, this will set both +//! variables to `None`. +//! - `WASM_BUILD_TYPE` - Sets the build type for building Wasm binaries. Supported values are `release` or `debug`. //! By default the build type is equal to the build type used by the main build. -//! - `FORCE_WASM_BUILD` - Can be set to force a wasm build. On subsequent calls the value of the variable -//! needs to change. As wasm builder instructs `cargo` to watch for file changes +//! - `FORCE_WASM_BUILD` - Can be set to force a Wasm build. On subsequent calls the value of the variable +//! needs to change. As wasm-builder instructs `cargo` to watch for file changes //! this environment variable should only be required in certain circumstances. //! - `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the wasm binary. //! - `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build. -//! - `WASM_TARGET_DIRECTORY` - Will copy any build wasm binary to the given directory. The path needs +//! - `WASM_TARGET_DIRECTORY` - Will copy any build Wasm binary to the given directory. The path needs //! to be absolute. -//! - `WASM_BUILD_TOOLCHAIN` - The toolchain that should be used to build the wasm binaries. The +//! - `WASM_BUILD_TOOLCHAIN` - The toolchain that should be used to build the Wasm binaries. The //! format needs to be the same as used by cargo, e.g. `nightly-2020-02-20`. //! //! Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. @@ -92,11 +96,14 @@ //! as well. For example if installing the rust nightly from 20.02.2020 using `rustup install nightly-2020-02-20`, //! the wasm target needs to be installed as well `rustup target add wasm32-unknown-unknown --toolchain nightly-2020-02-20`. -use std::{env, fs, path::{PathBuf, Path}, process::{Command, self}, io::BufRead}; +use std::{env, fs, path::{PathBuf, Path}, process::Command, io::BufRead}; +mod builder; mod prerequisites; mod wasm_project; +pub use builder::{WasmBuilder, WasmBuilderSelectProject}; + /// Environment variable that tells us to skip building the wasm binary. const SKIP_BUILD_ENV: &str = "SKIP_WASM_BUILD"; @@ -120,87 +127,8 @@ const WASM_BUILD_NO_COLOR: &str = "WASM_BUILD_NO_COLOR"; /// Environment variable to set the toolchain used to compile the wasm binary. const WASM_BUILD_TOOLCHAIN: &str = "WASM_BUILD_TOOLCHAIN"; -/// Build the currently built project as wasm binary. -/// -/// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable. -/// -/// `file_name` - The name + path of the file being generated. The file contains the -/// constant `WASM_BINARY`, which contains the built WASM binary. -/// `cargo_manifest` - The path to the `Cargo.toml` of the project that should be built. -pub fn build_project(file_name: &str, cargo_manifest: &str) { - build_project_with_default_rustflags(file_name, cargo_manifest, ""); -} - -/// Build the currently built project as wasm binary. -/// -/// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable. -/// -/// `file_name` - The name + path of the file being generated. The file contains the -/// constant `WASM_BINARY`, which contains the built WASM binary. -/// `cargo_manifest` - The path to the `Cargo.toml` of the project that should be built. -/// `default_rustflags` - Default `RUSTFLAGS` that will always be set for the build. -pub fn build_project_with_default_rustflags( - file_name: &str, - cargo_manifest: &str, - default_rustflags: &str, -) { - if check_skip_build() { - return; - } - - let cargo_manifest = PathBuf::from(cargo_manifest); - - if !cargo_manifest.exists() { - panic!("'{}' does not exist!", cargo_manifest.display()); - } - - if !cargo_manifest.ends_with("Cargo.toml") { - panic!("'{}' no valid path to a `Cargo.toml`!", cargo_manifest.display()); - } - - let cargo_cmd = match prerequisites::check() { - Ok(cmd) => cmd, - Err(err_msg) => { - eprintln!("{}", err_msg); - process::exit(1); - }, - }; - - let (wasm_binary, bloaty) = wasm_project::create_and_compile( - &cargo_manifest, - default_rustflags, - cargo_cmd, - ); - - let (wasm_binary, wasm_binary_bloaty) = if let Some(wasm_binary) = wasm_binary { - ( - wasm_binary.wasm_binary_path_escaped(), - bloaty.wasm_binary_bloaty_path_escaped(), - ) - } else { - ( - bloaty.wasm_binary_bloaty_path_escaped(), - bloaty.wasm_binary_bloaty_path_escaped(), - ) - }; - - write_file_if_changed( - file_name, - format!( - r#" - pub const WASM_BINARY: Option<&[u8]> = Some(include_bytes!("{wasm_binary}")); - pub const WASM_BINARY_BLOATY: Option<&[u8]> = Some(include_bytes!("{wasm_binary_bloaty}")); - "#, - wasm_binary = wasm_binary, - wasm_binary_bloaty = wasm_binary_bloaty, - ), - ); -} - -/// Checks if the build of the WASM binary should be skipped. -fn check_skip_build() -> bool { - env::var(SKIP_BUILD_ENV).is_ok() -} +/// Environment variable that makes sure the WASM build is triggered. +const FORCE_WASM_BUILD_ENV: &str = "FORCE_WASM_BUILD"; /// Write to the given `file` if the `content` is different. fn write_file_if_changed(file: impl AsRef, content: impl AsRef) { @@ -217,7 +145,9 @@ fn copy_file_if_changed(src: PathBuf, dst: PathBuf) { if src_file != dst_file { fs::copy(&src, &dst) - .unwrap_or_else(|_| panic!("Copying `{}` to `{}` can not fail; qed", src.display(), dst.display())); + .unwrap_or_else( + |_| panic!("Copying `{}` to `{}` can not fail; qed", src.display(), dst.display()) + ); } } diff --git a/utils/wasm-builder/src/wasm_project.rs b/utils/wasm-builder/src/wasm_project.rs index c27af71988b07..4c4c80e5a8664 100644 --- a/utils/wasm-builder/src/wasm_project.rs +++ b/utils/wasm-builder/src/wasm_project.rs @@ -30,10 +30,6 @@ use cargo_metadata::{MetadataCommand, Metadata}; use walkdir::WalkDir; -use fs2::FileExt; - -use itertools::Itertools; - /// Colorize an info message. /// /// Returns the colorized message. @@ -70,31 +66,6 @@ impl WasmBinary { } } -/// A lock for the WASM workspace. -struct WorkspaceLock(fs::File); - -impl WorkspaceLock { - /// Create a new lock - fn new(wasm_workspace_root: &Path) -> Self { - let lock = fs::OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(wasm_workspace_root.join("wasm_workspace.lock")) - .expect("Opening the lock file does not fail"); - - lock.lock_exclusive().expect("Locking `wasm_workspace.lock` failed"); - - WorkspaceLock(lock) - } -} - -impl Drop for WorkspaceLock { - fn drop(&mut self) { - let _ = self.0.unlock(); - } -} - fn crate_metadata(cargo_manifest: &Path) -> Metadata { let mut cargo_lock = cargo_manifest.to_path_buf(); cargo_lock.set_file_name("Cargo.lock"); @@ -120,35 +91,36 @@ fn crate_metadata(cargo_manifest: &Path) -> Metadata { /// Creates the WASM project, compiles the WASM binary and compacts the WASM binary. /// /// # Returns +/// /// The path to the compact WASM binary and the bloaty WASM binary. pub(crate) fn create_and_compile( - cargo_manifest: &Path, + project_cargo_toml: &Path, default_rustflags: &str, cargo_cmd: CargoCommandVersioned, ) -> (Option, WasmBinaryBloaty) { let wasm_workspace_root = get_wasm_workspace_root(); let wasm_workspace = wasm_workspace_root.join("wbuild"); - // Lock the workspace exclusively for us - let _lock = WorkspaceLock::new(&wasm_workspace_root); + let crate_metadata = crate_metadata(project_cargo_toml); - let crate_metadata = crate_metadata(cargo_manifest); - - let project = create_project(cargo_manifest, &wasm_workspace, &crate_metadata); - create_wasm_workspace_project(&wasm_workspace, &crate_metadata.workspace_root); + let project = create_project( + project_cargo_toml, + &wasm_workspace, + &crate_metadata, + &crate_metadata.workspace_root, + ); build_project(&project, default_rustflags, cargo_cmd); let (wasm_binary, bloaty) = compact_wasm_file( &project, - cargo_manifest, - &wasm_workspace, + project_cargo_toml, ); wasm_binary.as_ref().map(|wasm_binary| - copy_wasm_to_target_directory(cargo_manifest, wasm_binary) + copy_wasm_to_target_directory(project_cargo_toml, wasm_binary) ); - generate_rerun_if_changed_instructions(cargo_manifest, &project, &wasm_workspace); + generate_rerun_if_changed_instructions(project_cargo_toml, &project, &wasm_workspace); (wasm_binary, bloaty) } @@ -221,69 +193,14 @@ fn get_wasm_workspace_root() -> PathBuf { panic!("Could not find target dir in: {}", build_helper::out_dir().display()) } -/// Find all workspace members. -/// -/// Each folder in `wasm_workspace` is seen as a member of the workspace. Exceptions are -/// folders starting with "." and the "target" folder. -/// -/// Every workspace member that is not valid anymore is deleted (the folder of it). A -/// member is not valid anymore when the `wasm-project` dependency points to an non-existing -/// folder or the package name is not valid. -fn find_and_clear_workspace_members(wasm_workspace: &Path) -> Vec { - let mut members = WalkDir::new(wasm_workspace) - .min_depth(1) - .max_depth(1) - .into_iter() - .filter_map(|p| p.ok()) - .map(|d| d.into_path()) - .filter(|p| p.is_dir()) - .filter_map(|p| p.file_name().map(|f| f.to_owned()).and_then(|s| s.into_string().ok())) - .filter(|f| !f.starts_with('.') && f != "target") - .collect::>(); - - let mut i = 0; - while i != members.len() { - let path = wasm_workspace.join(&members[i]).join("Cargo.toml"); - - // Extract the `wasm-project` dependency. - // If the path can be extracted and is valid and the package name matches, - // the member is valid. - if let Some(mut wasm_project) = fs::read_to_string(path) - .ok() - .and_then(|s| toml::from_str::(&s).ok()) - .and_then(|mut t| t.remove("dependencies")) - .and_then(|p| p.try_into::
().ok()) - .and_then(|mut t| t.remove("wasm_project")) - .and_then(|p| p.try_into::
().ok()) - { - if let Some(path) = wasm_project.remove("path") - .and_then(|p| p.try_into::().ok()) - { - if let Some(name) = wasm_project.remove("package") - .and_then(|p| p.try_into::().ok()) - { - let path = PathBuf::from(path); - if path.exists() { - if name == get_crate_name(&path.join("Cargo.toml")) { - i += 1; - continue - } - } - } - } - } - - fs::remove_dir_all(wasm_workspace.join(&members[i])) - .expect("Removing invalid workspace member can not fail; qed"); - members.remove(i); - } - - members -} - -fn create_wasm_workspace_project(wasm_workspace: &Path, workspace_root_path: &Path) { - let members = find_and_clear_workspace_members(wasm_workspace); - +fn create_project_cargo_toml( + wasm_workspace: &Path, + workspace_root_path: &Path, + crate_name: &str, + crate_path: &Path, + wasm_binary: &str, + enabled_features: &[String], +) { let mut workspace_toml: Table = toml::from_str( &fs::read_to_string( workspace_root_path.join("Cargo.toml"), @@ -306,12 +223,6 @@ fn create_wasm_workspace_project(wasm_workspace: &Path, workspace_root_path: &Pa wasm_workspace_toml.insert("profile".into(), profile.into()); - // Add `workspace` with members - let mut workspace = Table::new(); - workspace.insert("members".into(), members.into()); - - wasm_workspace_toml.insert("workspace".into(), workspace.into()); - // Add patch section from the project root `Cargo.toml` if let Some(mut patch) = workspace_toml.remove("patch").and_then(|p| p.try_into::
().ok()) { // Iterate over all patches and make the patch path absolute from the workspace root path. @@ -335,6 +246,33 @@ fn create_wasm_workspace_project(wasm_workspace: &Path, workspace_root_path: &Pa wasm_workspace_toml.insert("patch".into(), patch.into()); } + let mut package = Table::new(); + package.insert("name".into(), format!("{}-wasm", crate_name).into()); + package.insert("version".into(), "1.0.0".into()); + package.insert("edition".into(), "2018".into()); + + wasm_workspace_toml.insert("package".into(), package.into()); + + let mut lib = Table::new(); + lib.insert("name".into(), wasm_binary.into()); + lib.insert("crate-type".into(), vec!["cdylib".to_string()].into()); + + wasm_workspace_toml.insert("lib".into(), lib.into()); + + let mut dependencies = Table::new(); + + let mut wasm_project = Table::new(); + wasm_project.insert("package".into(), crate_name.into()); + wasm_project.insert("path".into(), crate_path.display().to_string().into()); + wasm_project.insert("default-features".into(), false.into()); + wasm_project.insert("features".into(), enabled_features.to_vec().into()); + + dependencies.insert("wasm-project".into(), wasm_project.into()); + + wasm_workspace_toml.insert("dependencies".into(), dependencies.into()); + + wasm_workspace_toml.insert("workspace".into(), Table::new().into()); + write_file_if_changed( wasm_workspace.join("Cargo.toml"), toml::to_string_pretty(&wasm_workspace_toml).expect("Wasm workspace toml is valid; qed"), @@ -394,56 +332,48 @@ fn has_runtime_wasm_feature_declared( /// Create the project used to build the wasm binary. /// /// # Returns -/// The path to the created project. -fn create_project(cargo_manifest: &Path, wasm_workspace: &Path, crate_metadata: &Metadata) -> PathBuf { - let crate_name = get_crate_name(cargo_manifest); - let crate_path = cargo_manifest.parent().expect("Parent path exists; qed"); - let wasm_binary = get_wasm_binary_name(cargo_manifest); - let project_folder = wasm_workspace.join(&crate_name); - - fs::create_dir_all(project_folder.join("src")) +/// +/// The path to the created wasm project. +fn create_project( + project_cargo_toml: &Path, + wasm_workspace: &Path, + crate_metadata: &Metadata, + workspace_root_path: &Path, +) -> PathBuf { + let crate_name = get_crate_name(project_cargo_toml); + let crate_path = project_cargo_toml.parent().expect("Parent path exists; qed"); + let wasm_binary = get_wasm_binary_name(project_cargo_toml); + let wasm_project_folder = wasm_workspace.join(&crate_name); + + fs::create_dir_all(wasm_project_folder.join("src")) .expect("Wasm project dir create can not fail; qed"); - let mut enabled_features = project_enabled_features(&cargo_manifest, &crate_metadata); + let mut enabled_features = project_enabled_features(&project_cargo_toml, &crate_metadata); - if has_runtime_wasm_feature_declared(cargo_manifest, crate_metadata) { + if has_runtime_wasm_feature_declared(project_cargo_toml, crate_metadata) { enabled_features.push("runtime-wasm".into()); } - write_file_if_changed( - project_folder.join("Cargo.toml"), - format!( - r#" - [package] - name = "{crate_name}-wasm" - version = "1.0.0" - edition = "2018" - - [lib] - name = "{wasm_binary}" - crate-type = ["cdylib"] - - [dependencies] - wasm_project = {{ package = "{crate_name}", path = "{crate_path}", default-features = false, features = [ {features} ] }} - "#, - crate_name = crate_name, - crate_path = crate_path.display(), - wasm_binary = wasm_binary, - features = enabled_features.into_iter().map(|f| format!("\"{}\"", f)).join(","), - ) + create_project_cargo_toml( + &wasm_project_folder, + workspace_root_path, + &crate_name, + &crate_path, + &wasm_binary, + &enabled_features, ); write_file_if_changed( - project_folder.join("src/lib.rs"), + wasm_project_folder.join("src/lib.rs"), "#![no_std] pub use wasm_project::*;", ); - if let Some(crate_lock_file) = find_cargo_lock(cargo_manifest) { + if let Some(crate_lock_file) = find_cargo_lock(project_cargo_toml) { // Use the `Cargo.lock` of the main project. - crate::copy_file_if_changed(crate_lock_file, wasm_workspace.join("Cargo.lock")); + crate::copy_file_if_changed(crate_lock_file, wasm_project_folder.join("Cargo.lock")); } - project_folder + wasm_project_folder } /// Returns if the project should be built as a release. @@ -474,9 +404,13 @@ fn build_project(project: &Path, default_rustflags: &str, cargo_cmd: CargoComman env::var(crate::WASM_BUILD_RUSTFLAGS_ENV).unwrap_or_default(), ); - build_cmd.args(&["rustc", "--target=wasm32-unknown-unknown"]) + build_cmd.args(&["-Zfeatures=build_dep", "rustc", "--target=wasm32-unknown-unknown"]) .arg(format!("--manifest-path={}", manifest_path.display())) .env("RUSTFLAGS", rustflags) + // Unset the `CARGO_TARGET_DIR` to prevent a cargo deadlock (cargo locks a target dir exclusive). + // The runner project is created in `CARGO_TARGET_DIR` and executing it will create a sub target + // directory inside of `CARGO_TARGET_DIR`. + .env_remove("CARGO_TARGET_DIR") // We don't want to call ourselves recursively .env(crate::SKIP_BUILD_ENV, ""); @@ -503,14 +437,14 @@ fn build_project(project: &Path, default_rustflags: &str, cargo_cmd: CargoComman fn compact_wasm_file( project: &Path, cargo_manifest: &Path, - wasm_workspace: &Path, ) -> (Option, WasmBinaryBloaty) { let is_release_build = is_release_build(); let target = if is_release_build { "release" } else { "debug" }; let wasm_binary = get_wasm_binary_name(cargo_manifest); - let wasm_file = wasm_workspace.join("target/wasm32-unknown-unknown") + let wasm_file = project.join("target/wasm32-unknown-unknown") .join(target) .join(format!("{}.wasm", wasm_binary)); + let wasm_compact_file = if is_release_build { let wasm_compact_file = project.join(format!("{}.compact.wasm", wasm_binary)); wasm_gc::garbage_collect_file(&wasm_file, &wasm_compact_file)