diff --git a/.circleci/config.yml b/.circleci/config.yml
index 74dd8a631b..de970a552b 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -13,8 +13,8 @@ commands:
             source ~/.cargo/env
             rustup install $RUST_VERSION
             rustup default $RUST_VERSION
-            rustup install nightly-2020-11-16
-            rustup target add wasm32-unknown-unknown --toolchain=nightly-2020-11-16
+            rustup install nightly-2021-02-28
+            rustup target add wasm32-unknown-unknown --toolchain=nightly-2021-02-28
             rustup target add x86_64-unknown-linux-musl --toolchain=$RUST_VERSION
             export RUSTC_WRAPPER="" # sccache is uninstalled at this point so it must be unset here for `wasm-gc` install
             command -v wasm-gc || cargo install --git https://github.com/alexcrichton/wasm-gc --force
@@ -76,7 +76,7 @@ jobs:
     resource_class: large
     environment:
       BASH_ENV: ~/.cargo/env
-      RUST_VERSION: 1.49.0
+      RUST_VERSION: 1.50.0
       RUSTC_WRAPPER: sccache
       SCCACHE_CACHE_SIZE: 10G
     steps:
@@ -92,7 +92,7 @@ jobs:
     resource_class: large
     environment:
       BASH_ENV: ~/.cargo/env
-      RUST_VERSION: 1.49.0
+      RUST_VERSION: 1.50.0
       RUSTC_WRAPPER: sccache
       SCCACHE_CACHE_SIZE: 10G
     steps:
diff --git a/.github/allowed-actions.js b/.github/allowed-actions.js
deleted file mode 100644
index 4fb8947580..0000000000
--- a/.github/allowed-actions.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// This is a whitelist of GitHub Actions that are approved for use in this project.
-// If a new or existing workflow file is updated to use an action or action version
-// not listed here, CI will fail.
-
-module.exports = [
-    'gaurav-nelson/github-action-markdown-link-check@7481451f70251762f149d69596e3e276ebf2b236', // gaurav-nelson/github-action-markdown-link-check@v1.0.8
-]
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index d782bb80f7..0000000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-version: 2
-updates:
-  - package-ecosystem: "cargo"
-    directory: "/"
-    labels: ["A2-insubstantial", "B0-silent", "C1-low"]
-    schedule:
-      interval: "daily"
diff --git a/.github/workflows/burnin-label-notification.yml b/.github/workflows/burnin-label-notification.yml
deleted file mode 100644
index 22f15c0ec3..0000000000
--- a/.github/workflows/burnin-label-notification.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: Notify devops when burn-in label applied
-on:
-  pull_request:
-    types: [labeled]
-
-jobs:
-  notify-devops:
-    runs-on: ubuntu-latest
-    steps:
-      - name: Notify devops
-        if: github.event.label.name == 'A1-needsburnin'
-        uses: s3krit/matrix-message-action@v0.0.3
-        with:
-          room_id: ${{ secrets.POLKADOT_DEVOPS_MATRIX_ROOM_ID }}
-          access_token: ${{ secrets.POLKADOT_DEVOPS_MATRIX_ACCESS_TOKEN }}
-          message: "@room Burn-in request received for [${{ github.event.pull_request.title }}](${{ github.event.pull_request.html_url }})"
-          server: "matrix.parity.io"
diff --git a/.github/workflows/md-link-check.yml b/.github/workflows/md-link-check.yml
deleted file mode 100644
index 868569911d..0000000000
--- a/.github/workflows/md-link-check.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-name: Check Links
-
-on:
-  pull_request:
-    branches:
-    - master
-  push:
-    branches:
-    - master
-
-jobs:
-  markdown-link-check:
-    runs-on: ubuntu-latest
-    steps:
-    - uses: actions/checkout@v2
-    - uses: gaurav-nelson/github-action-markdown-link-check@7481451f70251762f149d69596e3e276ebf2b236
-      with:
-        use-quiet-mode: 'yes'
-        config-file: '.github/workflows/mlc_config.json'
diff --git a/.github/workflows/mlc_config.json b/.github/workflows/mlc_config.json
deleted file mode 100644
index e7e620b39e..0000000000
--- a/.github/workflows/mlc_config.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-    "ignorePatterns": [
-        {
-            "pattern": "^https://crates.io",
-        }
-    ]
-}
diff --git a/.github/workflows/release-bot.yml b/.github/workflows/release-bot.yml
deleted file mode 100644
index ed0a8e5435..0000000000
--- a/.github/workflows/release-bot.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: Pushes release updates to a pre-defined Matrix room
-on:
-  release:
-    types:
-      - edited
-      - prereleased
-      - published
-jobs:
-  ping_matrix:
-    runs-on: ubuntu-latest
-    steps:
-      - name: send message
-        uses: s3krit/matrix-message-action@v0.0.3
-        with:
-          room_id: ${{ secrets.MATRIX_ROOM_ID }}
-          access_token: ${{ secrets.MATRIX_ACCESS_TOKEN }}
-          message: "**${{github.event.repository.full_name}}:** A release has been ${{github.event.action}}
Release version [${{github.event.release.tag_name}}](${{github.event.release.html_url}})
***Description:***
${{github.event.release.body}}
"
-          server: "matrix.parity.io"
diff --git a/.gitignore b/.gitignore
index c8f1ea9567..ce302c74e1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,4 @@ rls*.log
 **/hfuzz_workspace/
 .cargo/
 .cargo-remote.toml
+*.bin
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index de1655c39d..0000000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,700 +0,0 @@
-# .gitlab-ci.yml
-#
-# substrate
-#
-# pipelines can be triggered manually in the web
-
-# SAMPLE JOB TEMPLATE - This is not a complete example but is enough to build a
-# simple CI job. For full documentation, visit https://docs.gitlab.com/ee/ci/yaml/
-#
-# my-example-job:
-#   stage:                           test # One of the stages listed below this job (required)
-#   image:                           paritytech/tools:latest # Any docker image (required)
-#   allow_failure:                   true # Allow the pipeline to continue if this job fails (default: false)
-#   needs:
-#     - job:                         test-linux # Any jobs that are required to run before this job (optional)
-#   variables:
-#     MY_ENVIRONMENT_VARIABLE:       "some useful value" # Environment variables passed to the job (optional)
-#   script:
-#     - echo "List of shell commands to run in your job"
-#     - echo "You can also just specify a script here, like so:"
-#     - ./.maintain/gitlab/my_amazing_script.sh
-
-stages:
-  - check
-  - test
-  - build
-  - publish
-  - deploy
-  - flaming-fir
-
-workflow:
-  rules:
-    - if: $CI_COMMIT_TAG
-    - if: $CI_COMMIT_BRANCH
-
-variables:                         &default-vars
-  GIT_STRATEGY:                    fetch
-  GIT_DEPTH:                       100
-  CARGO_INCREMENTAL:               0
-  DOCKER_OS:                       "debian:stretch"
-  ARCH:                            "x86_64"
-  # FIXME set to release
-  CARGO_UNLEASH_INSTALL_PARAMS:    "--version 1.0.0-alpha.11"
-  CARGO_UNLEASH_PKG_DEF:           "--skip node node-* pallet-template pallet-example pallet-example-* subkey chain-spec-builder"
-
-default:
-  cache:                           {}
-
-.collect-artifacts:                &collect-artifacts
-  artifacts:
-    name:                          "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
-    when:                          on_success
-    expire_in:                     7 days
-    paths:
-      - artifacts/
-
-.kubernetes-build:                 &kubernetes-build
-  tags:
-    - kubernetes-parity-build
-  interruptible:                   true
-
-.docker-env:                       &docker-env
-  image:                           paritytech/ci-linux:production
-  before_script:
-    - rustup show
-    - cargo --version
-    - sccache -s
-  retry:
-    max: 2
-    when:
-      - runner_system_failure
-      - unknown_failure
-      - api_failure
-  interruptible:                   true
-  tags:
-    - linux-docker
-
-.test-refs:                        &test-refs
-  rules:
-    - if: $CI_PIPELINE_SOURCE == "web"
-    - if: $CI_PIPELINE_SOURCE == "schedule"
-    - if: $CI_COMMIT_REF_NAME == "master"
-    - if: $CI_COMMIT_REF_NAME == "tags"
-    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/                         # PRs
-    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/              # i.e. v1.0, v2.1rc1
-
-.build-refs:                       &build-refs
-  rules:
-    - if: $CI_PIPELINE_SOURCE == "web"
-    - if: $CI_COMMIT_REF_NAME == "master"
-    - if: $CI_COMMIT_REF_NAME == "tags"
-    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/              # i.e. v1.0, v2.1rc1
-
-#### stage:                       .pre
-
-skip-if-draft:
-  image:                           paritytech/tools:latest
-  <<:                              *kubernetes-build
-  stage:                           .pre
-  rules:
-    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/                         # PRs
-  script:
-     - echo "Commit message is ${CI_COMMIT_MESSAGE}"
-     - echo "Ref is ${CI_COMMIT_REF_NAME}"
-     - echo "pipeline source is ${CI_PIPELINE_SOURCE}"
-     - ./.maintain/gitlab/skip_if_draft.sh
-
-#### stage:                        check
-
-check-runtime:
-  stage:                           check
-  image:                           paritytech/tools:latest
-  <<:                              *kubernetes-build
-  rules:
-    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/                         # PRs
-  variables:
-    <<:                            *default-vars
-    GITLAB_API:                    "https://gitlab.parity.io/api/v4"
-    GITHUB_API_PROJECT:            "parity%2Finfrastructure%2Fgithub-api"
-  script:
-    - ./.maintain/gitlab/check_runtime.sh
-  allow_failure:                   true
-
-check-signed-tag:
-  stage:                           check
-  image:                           paritytech/tools:latest
-  <<:                              *kubernetes-build
-  rules:
-    - if: $CI_COMMIT_REF_NAME =~ /^ci-release-.*$/
-    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/              # i.e. v1.0, v2.1rc1
-  script:
-    - ./.maintain/gitlab/check_signed.sh
-
-check-line-width:
-  stage:                           check
-  image:                           paritytech/tools:latest
-  <<:                              *kubernetes-build
-  rules:
-    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/                         # PRs
-  script:
-    - ./.maintain/gitlab/check_line_width.sh
-  allow_failure:                   true
-
-test-dependency-rules:
-  stage:                           check
-  image:                           paritytech/tools:latest
-  <<:                              *kubernetes-build
-  script:
-    - .maintain/ensure-deps.sh
-
-test-prometheus-alerting-rules:
-  stage:                           check
-  image:                           paritytech/tools:latest
-  <<:                              *kubernetes-build
-  rules:
-    - if: $CI_COMMIT_BRANCH
-      changes:
-        - .gitlab-ci.yml
-        - .maintain/monitoring/**/*
-  script:
-    - promtool check rules .maintain/monitoring/alerting-rules/alerting-rules.yaml
-    - cat .maintain/monitoring/alerting-rules/alerting-rules.yaml | promtool test rules .maintain/monitoring/alerting-rules/alerting-rule-tests.yaml
-
-#### stage:                        test
-
-cargo-audit:
-  stage:                           test
-  <<:                              *docker-env
-  rules:
-    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/                         # PRs
-      when: never
-    - if: $CI_PIPELINE_SOURCE == "web"
-    - if: $CI_PIPELINE_SOURCE == "schedule"
-    - if: $CI_COMMIT_REF_NAME == "master"
-    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/              # i.e. v1.0, v2.1rc1
-  script:
-    - cargo audit
-  allow_failure:                   true
-
-cargo-deny:
-  stage:                           test
-  <<:                              *docker-env
-  rules:
-    - if: $CI_COMMIT_MESSAGE =~ /skip-checks/
-      when: never
-    - if: $CI_PIPELINE_SOURCE == "web"
-    - if: $CI_PIPELINE_SOURCE == "schedule"
-    - if: $CI_COMMIT_REF_NAME == "master"
-    - if: $CI_COMMIT_REF_NAME == "tags"
-    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/              # i.e. v1.0, v2.1rc1
-  script:
-    - cargo deny check --hide-inclusion-graph -c .maintain/deny.toml
-  after_script:
-    - echo "___The complete log is in the artifacts___"
-    - cargo deny check -c .maintain/deny.toml 2> deny.log
-  artifacts:
-    name:                          $CI_COMMIT_SHORT_SHA
-    expire_in:                     3 days
-    when:                          always
-    paths:
-      - deny.log
-
-cargo-check-benches:
-  stage:                           test
-  <<:                              *docker-env
-  <<:                              *test-refs
-  script:
-    - 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
-
-cargo-check-subkey:
-  stage:                           test
-  <<:                              *docker-env
-  <<:                              *test-refs
-  script:
-    - cd ./bin/utils/subkey
-    - SKIP_WASM_BUILD=1 time cargo check --release
-    - sccache -s
-
-test-deterministic-wasm:
-  stage:                           test
-  <<:                              *docker-env
-  <<:                              *test-refs
-  variables:
-    <<:                            *default-vars
-    WASM_BUILD_NO_COLOR:           1
-  script:
-    # build runtime
-    - cargo build --verbose --release -p node-runtime
-    # make checksum
-    - 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
-    - cargo build --verbose --release -p node-runtime
-    # confirm checksum
-    - sha256sum -c checksum.sha256
-    - sccache -s
-
-test-linux-stable:                 &test-linux
-  stage:                           test
-  <<:                              *docker-env
-  <<:                              *test-refs
-  variables:
-    <<:                            *default-vars
-    # Enable debug assertions since we are running optimized builds for testing
-    # but still want to have debug assertions.
-    RUSTFLAGS:                     "-Cdebug-assertions=y -Dwarnings"
-    RUST_BACKTRACE:                1
-    WASM_BUILD_NO_COLOR:           1
-  script:
-    # this job runs all tests in former runtime-benchmarks, frame-staking and wasmtime tests
-    - time cargo test --workspace --locked --release --verbose --features runtime-benchmarks --manifest-path bin/node/cli/Cargo.toml
-    - SUBSTRATE_TEST_TIMEOUT=1 time cargo test -p substrate-test-utils --release --verbose --locked -- --ignored timeout
-    - sccache -s
-
-unleash-check:
-  stage:                           test
-  <<:                              *docker-env
-  rules:
-    - if: $CI_COMMIT_MESSAGE =~ /skip-checks/
-      when: never
-      # .test-refs
-    - if: $CI_COMMIT_REF_NAME == "master"
-    - if: $CI_COMMIT_REF_NAME == "tags"
-    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/              # i.e. v1.0, v2.1rc1
-  script:
-    - cargo install cargo-unleash ${CARGO_UNLEASH_INSTALL_PARAMS}
-    - cargo unleash check ${CARGO_UNLEASH_PKG_DEF}
-
-test-frame-examples-compile-to-wasm:
-  # into one job
-  stage:                           test
-  <<:                              *docker-env
-  <<:                              *test-refs
-  variables:
-    <<:                            *default-vars
-    # Enable debug assertions since we are running optimized builds for testing
-    # but still want to have debug assertions.
-    RUSTFLAGS: -Cdebug-assertions=y
-    RUST_BACKTRACE: 1
-  script:
-    - cd frame/example-offchain-worker/
-    - cargo +nightly build --target=wasm32-unknown-unknown --no-default-features
-    - cd ../example
-    - cargo +nightly build --target=wasm32-unknown-unknown --no-default-features
-    - sccache -s
-
-test-linux-stable-int:
-  <<:                              *test-linux
-  script:
-    - echo "___Logs will be partly shown at the end in case of failure.___"
-    - echo "___Full log will be saved to the job artifacts only in case of failure.___"
-    - WASM_BUILD_NO_COLOR=1
-      RUST_LOG=sync=trace,consensus=trace,client=trace,state-db=trace,db=trace,forks=trace,state_db=trace,storage_cache=trace
-        time cargo test -p node-cli --release --verbose --locked -- --ignored
-        &> ${CI_COMMIT_SHORT_SHA}_int_failure.log
-    - sccache -s
-  after_script:
-    - awk '/FAILED|^error\[/,0' ${CI_COMMIT_SHORT_SHA}_int_failure.log
-  artifacts:
-    name:                          $CI_COMMIT_SHORT_SHA
-    when:                          on_failure
-    expire_in:                     3 days
-    paths:
-      - ${CI_COMMIT_SHORT_SHA}_int_failure.log
-
-check-web-wasm:
-  stage:                           test
-  <<:                              *docker-env
-  <<:                              *test-refs
-  script:
-    # WASM support is in progress. As more and more crates support WASM, we
-    # should add entries here. See https://github.com/paritytech/substrate/issues/2416
-    # Note: we don't need to test crates imported in `bin/node/cli`
-    - time cargo build --manifest-path=client/consensus/aura/Cargo.toml --target=wasm32-unknown-unknown --features getrandom
-    # Note: the command below is a bit weird because several Cargo issues prevent us from compiling the node in a more straight-forward way.
-    - time cargo +nightly build --manifest-path=bin/node/cli/Cargo.toml --no-default-features --features browser --target=wasm32-unknown-unknown -Z features=itarget
-    # with-tracing must be explicitly activated, we run a test to ensure this works as expected in both cases
-    - time cargo +nightly test --manifest-path primitives/tracing/Cargo.toml --no-default-features
-    - time cargo +nightly test --manifest-path primitives/tracing/Cargo.toml --no-default-features --features=with-tracing
-    - sccache -s
-
-test-full-crypto-feature:
-  stage:                           test
-  <<:                              *docker-env
-  <<:                              *test-refs
-  variables:
-    <<:                            *default-vars
-    # Enable debug assertions since we are running optimized builds for testing
-    # but still want to have debug assertions.
-    RUSTFLAGS: -Cdebug-assertions=y
-    RUST_BACKTRACE: 1
-  script:
-    - cd primitives/core/
-    - time cargo +nightly build --verbose --no-default-features --features full_crypto
-    - cd ../application-crypto
-    - time cargo +nightly build --verbose --no-default-features --features full_crypto
-    - sccache -s
-
-cargo-check-macos:
-  stage:                           test
-  # shell runner on mac ignores the image set in *docker-env
-  <<:                              *docker-env
-  <<:                              *test-refs
-  script:
-    - SKIP_WASM_BUILD=1 time cargo check --release
-    - sccache -s
-  tags:
-    - osx
-
-#### stage:                        build
-
-check-polkadot-companion-status:
-  stage:                           build
-  image:                           paritytech/tools:latest
-  <<:                              *kubernetes-build
-  rules:
-    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/                         # PRs
-  script:
-    - ./.maintain/gitlab/check_polkadot_companion_status.sh
-
-check-polkadot-companion-build:
-  stage:                           build
-  <<:                              *docker-env
-  <<:                              *test-refs
-  needs:
-    - job:                         test-linux-stable-int
-      artifacts:                   false
-  script:
-    - ./.maintain/gitlab/check_polkadot_companion_build.sh
-  after_script:
-    - cd polkadot && git rev-parse --abbrev-ref HEAD
-  allow_failure:                   true
-
-test-browser-node:
-  stage:                           build
-  <<:                              *docker-env
-  <<:                              *test-refs
-  needs:
-    - job:                         check-web-wasm
-      artifacts:                   false
-  variables:
-    <<:                                         *default-vars
-    CHROMEDRIVER_ARGS:                          "--log-level=INFO --whitelisted-ips=127.0.0.1"
-    CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER: "wasm-bindgen-test-runner"
-    WASM_BINDGEN_TEST_TIMEOUT:                  120
-  script:
-    - cargo +nightly test --target wasm32-unknown-unknown -p node-browser-testing -Z features=itarget
-
-build-linux-substrate:             &build-binary
-  stage:                           build
-  <<:                              *collect-artifacts
-  <<:                              *docker-env
-  rules:
-    # .build-refs with manual on PRs
-    - if: $CI_PIPELINE_SOURCE == "web"
-    - if: $CI_COMMIT_REF_NAME == "master"
-    - if: $CI_COMMIT_REF_NAME == "tags"
-    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/              # i.e. v1.0, v2.1rc1
-    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/                         # PRs
-      when: manual
-      allow_failure: true
-  needs:
-    - job:                         test-linux-stable
-      artifacts:                   false
-  before_script:
-    - mkdir -p ./artifacts/substrate/
-  script:
-    - WASM_BUILD_NO_COLOR=1 time cargo build --release --verbose
-    - mv ./target/release/substrate ./artifacts/substrate/.
-    - echo -n "Substrate version = "
-    - if [ "${CI_COMMIT_TAG}" ]; then
-        echo "${CI_COMMIT_TAG}" | tee ./artifacts/substrate/VERSION;
-      else
-        ./artifacts/substrate/substrate --version |
-          sed -n -E 's/^substrate ([0-9.]+.*-[0-9a-f]{7,13})-.*$/\1/p' |
-            tee ./artifacts/substrate/VERSION;
-      fi
-    - sha256sum ./artifacts/substrate/substrate | tee ./artifacts/substrate/substrate.sha256
-    - printf '\n# building node-template\n\n'
-    - ./.maintain/node-template-release.sh ./artifacts/substrate/substrate-node-template.tar.gz
-    - cp -r .maintain/docker/substrate.Dockerfile ./artifacts/substrate/
-    - sccache -s
-
-build-linux-subkey:                &build-subkey
-  stage:                           build
-  <<:                              *collect-artifacts
-  <<:                              *docker-env
-  rules:
-    # .build-refs with manual on PRs
-    - if: $CI_PIPELINE_SOURCE == "web"
-    - if: $CI_COMMIT_REF_NAME == "master"
-    - if: $CI_COMMIT_REF_NAME == "tags"
-    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/              # i.e. v1.0, v2.1rc1
-    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/                         # PRs
-      when: manual
-      allow_failure: true
-  needs:
-    - job:                         cargo-check-subkey
-      artifacts:                   false
-  before_script:
-    - mkdir -p ./artifacts/subkey
-  script:
-    - cd ./bin/utils/subkey
-    - SKIP_WASM_BUILD=1 time cargo build --release --verbose
-    - cd -
-    - mv ./target/release/subkey ./artifacts/subkey/.
-    - echo -n "Subkey version = "
-    - ./artifacts/subkey/subkey --version |
-        sed -n -E 's/^subkey ([0-9.]+.*)/\1/p' |
-          tee ./artifacts/subkey/VERSION;
-    - sha256sum ./artifacts/subkey/subkey | tee ./artifacts/subkey/subkey.sha256
-    - cp -r .maintain/docker/subkey.Dockerfile ./artifacts/subkey/
-    - sccache -s
-
-build-macos-subkey:
-  <<:                              *build-subkey
-  tags:
-    - osx
-
-build-rust-doc:
-  stage:                           build
-  <<:                              *docker-env
-  <<:                              *test-refs
-  needs:
-    - job:                         test-linux-stable
-      artifacts:                   false
-  variables:
-    <<:                            *default-vars
-    RUSTFLAGS:                     -Dwarnings
-  artifacts:
-    name:                          "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}-doc"
-    when:                          on_success
-    expire_in:                     7 days
-    paths:
-    - ./crate-docs/
-  script:
-    - rm -f ./crate-docs/index.html # use it as an indicator if the job succeeds
-    - 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
-    - sccache -s
-
-#### stage:                        publish
-
-.build-push-docker-image:          &build-push-docker-image
-  <<:                              *build-refs
-  <<:                              *kubernetes-build
-  image:                           quay.io/buildah/stable
-  variables:                       &docker-build-vars
-    <<:                            *default-vars
-    GIT_STRATEGY:                  none
-    DOCKERFILE:                    $PRODUCT.Dockerfile
-    IMAGE_NAME:                    docker.io/parity/$PRODUCT
-  before_script:
-    - cd ./artifacts/$PRODUCT/
-    - VERSION="$(cat ./VERSION)"
-    - echo "${PRODUCT} version = ${VERSION}"
-    - test -z "${VERSION}" && exit 1
-  script:
-    - test "$Docker_Hub_User_Parity" -a "$Docker_Hub_Pass_Parity" ||
-        ( echo "no docker credentials provided"; exit 1 )
-    - buildah bud
-        --format=docker
-        --build-arg VCS_REF="${CI_COMMIT_SHA}"
-        --build-arg BUILD_DATE="$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
-        --tag "$IMAGE_NAME:$VERSION"
-        --tag "$IMAGE_NAME:latest"
-        --file "$DOCKERFILE" .
-    - echo "$Docker_Hub_Pass_Parity" |
-        buildah login --username "$Docker_Hub_User_Parity" --password-stdin docker.io
-    - buildah info
-    - buildah push --format=v2s2 "$IMAGE_NAME:$VERSION"
-    - buildah push --format=v2s2 "$IMAGE_NAME:latest"
-    - buildah logout "$IMAGE_NAME"
-
-publish-docker-substrate:
-  stage:                           publish
-  <<:                              *build-push-docker-image
-  # collect VERSION artifact here to pass it on to kubernetes
-  <<:                              *collect-artifacts
-  needs:
-    - job:                         build-linux-substrate
-      artifacts:                   true
-  variables:
-    <<:                            *docker-build-vars
-    PRODUCT:                       substrate
-  after_script:
-    # only VERSION information is needed for the deployment
-    - find ./artifacts/ -depth -not -name VERSION -type f -delete
-
-publish-docker-subkey:
-  stage:                           publish
-  <<:                              *build-push-docker-image
-  needs:
-    - job:                         build-linux-subkey
-      artifacts:                   true
-  variables:
-    <<:                            *docker-build-vars
-    PRODUCT:                       subkey
-
-publish-s3-release:
-  stage:                           publish
-  <<:                              *build-refs
-  <<:                              *kubernetes-build
-  needs:
-    - job:                         build-linux-substrate
-      artifacts:                   true
-    - job:                         build-linux-subkey
-      artifacts:                   true
-  image:                           paritytech/awscli:latest
-  variables:
-    GIT_STRATEGY:                  none
-    BUCKET:                        "releases.parity.io"
-    PREFIX:                        "substrate/${ARCH}-${DOCKER_OS}"
-  script:
-    - aws s3 sync ./artifacts/ s3://${BUCKET}/${PREFIX}/$(cat ./artifacts/substrate/VERSION)/
-    - echo "update objects in latest path"
-    - aws s3 sync s3://${BUCKET}/${PREFIX}/$(cat ./artifacts/substrate/VERSION)/ s3://${BUCKET}/${PREFIX}/latest/
-  after_script:
-    - aws s3 ls s3://${BUCKET}/${PREFIX}/latest/
-        --recursive --human-readable --summarize
-
-publish-s3-doc:
-  stage:                           publish
-  image:                           paritytech/awscli:latest
-  allow_failure:                   true
-  needs:
-    - job:                         build-rust-doc
-      artifacts:                   true
-    - job:                         build-linux-substrate
-      artifacts:                   false
-  <<:                              *build-refs
-  <<:                              *kubernetes-build
-  variables:
-    GIT_STRATEGY:                  none
-    BUCKET:                        "releases.parity.io"
-    PREFIX:                        "substrate-rustdoc"
-  script:
-    - test -r ./crate-docs/index.html || (
-        echo "./crate-docs/index.html not present, build:rust:doc:release job not complete";
-        exit 1
-      )
-    - aws s3 sync --delete --size-only --only-show-errors
-        ./crate-docs/ s3://${BUCKET}/${PREFIX}/
-  after_script:
-    - aws s3 ls s3://${BUCKET}/${PREFIX}/
-        --human-readable --summarize
-
-publish-draft-release:
-  stage:                           publish
-  image:                           paritytech/tools:latest
-  rules:
-    - if: $CI_COMMIT_REF_NAME =~ /^ci-release-.*$/
-    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/              # i.e. v1.0, v2.1rc1
-  script:
-    - ./.maintain/gitlab/publish_draft_release.sh
-  allow_failure:                   true
-
-publish-to-crates-io:
-  stage:                           publish
-  <<:                              *docker-env
-  rules:
-    - if: $CI_COMMIT_REF_NAME =~ /^ci-release-.*$/
-    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/              # i.e. v1.0, v2.1rc1
-  script:
-    - cargo install cargo-unleash ${CARGO_UNLEASH_INSTALL_PARAMS}
-    - cargo unleash em-dragons --no-check --owner github:paritytech:core-devs ${CARGO_UNLEASH_PKG_DEF}
-  allow_failure:                   true
-
-#### stage:                        deploy
-
-deploy-prometheus-alerting-rules:
-  stage:                           deploy
-  needs:
-    - job:                         test-prometheus-alerting-rules
-      artifacts:                   false
-  interruptible:                   true
-  retry:                           1
-  tags:
-    - kubernetes-parity-build
-  image:                           paritytech/kubetools:latest
-  environment:
-    name: parity-mgmt-polkadot-alerting
-  variables:
-    NAMESPACE:                     monitoring
-    PROMETHEUSRULE:                prometheus-k8s-rules-polkadot-alerting
-    RULES:                         .maintain/monitoring/alerting-rules/alerting-rules.yaml
-  script:
-    - echo "deploying prometheus alerting rules"
-    - kubectl -n ${NAMESPACE} patch prometheusrule ${PROMETHEUSRULE}
-        --type=merge --patch "$(sed 's/^/  /;1s/^/spec:\n/' ${RULES})"
-  rules:
-    - if: $CI_COMMIT_REF_NAME == "master"
-      changes:
-        - .gitlab-ci.yml
-        - .maintain/monitoring/**/*
-
-trigger-simnet:
-  stage:                           deploy
-  rules:
-    # this job runs only on nightly pipeline with the mentioned variable, against `master` branch
-    - if: $CI_COMMIT_REF_NAME == "master" && $CI_PIPELINE_SOURCE == "schedule" && $PIPELINE == "nightly"
-  needs:
-    - job:                         publish-docker-substrate
-      artifacts:                   false
-  trigger:
-    project:                       parity/simnet
-    branch:                        master
-    strategy:                      depend
-
-.validator-deploy:                 &validator-deploy
-  stage:                           deploy
-  rules:
-    # this job runs only on nightly pipeline with the mentioned variable, against `master` branch
-    - if: $CI_COMMIT_REF_NAME == "master" && $CI_PIPELINE_SOURCE == "schedule" && $PIPELINE == "nightly"
-  needs:
-    # script will fail if there is no artifacts/substrate/VERSION
-    - job:                         publish-docker-substrate
-      artifacts:                   true
-  image:                           parity/azure-ansible:v2
-  allow_failure:                   true
-  interruptible:                   true
-  tags:
-    - linux-docker
-
-validator 1 4:
-  <<:                              *validator-deploy
-  script:
-    - ./.maintain/flamingfir-deploy.sh flamingfir-validator1
-
-validator 2 4:
-  <<:                              *validator-deploy
-  script:
-    - ./.maintain/flamingfir-deploy.sh flamingfir-validator2
-
-validator 3 4:
-  <<:                              *validator-deploy
-  script:
-    - ./.maintain/flamingfir-deploy.sh flamingfir-validator3
-
-validator 4 4:
-  <<:                              *validator-deploy
-  script:
-    - ./.maintain/flamingfir-deploy.sh flamingfir-validator4
-
-#### stage:                        .post
-
-check-labels:
-  stage:                           .post
-  image:                           paritytech/tools:latest
-  <<:                              *kubernetes-build
-  rules:
-    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/                         # PRs
-  script:
-    - ./.maintain/gitlab/check_labels.sh
diff --git a/.maintain/gitlab/lib.sh b/.maintain/common/lib.sh
similarity index 89%
rename from .maintain/gitlab/lib.sh
rename to .maintain/common/lib.sh
index 33477b52f5..1d4be0ecc7 100755
--- a/.maintain/gitlab/lib.sh
+++ b/.maintain/common/lib.sh
@@ -66,11 +66,17 @@ has_label(){
   repo="$1"
   pr_id="$2"
   label="$3"
+
+  # These will exist if the function is called in Gitlab.
+  # If the function's called in Github, we should have GITHUB_ACCESS_TOKEN set
+  # already.
   if [ -n "$GITHUB_RELEASE_TOKEN" ]; then
-    out=$(curl -H "Authorization: token $GITHUB_RELEASE_TOKEN" -s "$api_base/$repo/pulls/$pr_id")
-  else
-    out=$(curl -H "Authorization: token $GITHUB_PR_TOKEN" -s "$api_base/$repo/pulls/$pr_id")
+    GITHUB_TOKEN="$GITHUB_RELEASE_TOKEN"
+  elif [ -n "$GITHUB_PR_TOKEN" ]; then
+    GITHUB_TOKEN="$GITHUB_PR_TOKEN"
   fi
+
+  out=$(curl -H "Authorization: token $GITHUB_TOKEN" -s "$api_base/$repo/pulls/$pr_id")
   [ -n "$(echo "$out" | tr -d '\r\n' | jq ".labels | .[] | select(.name==\"$label\")")" ]
 }
 
diff --git a/.maintain/docker/subkey.Dockerfile b/.maintain/docker/subkey.Dockerfile
deleted file mode 100644
index 9184cad5b4..0000000000
--- a/.maintain/docker/subkey.Dockerfile
+++ /dev/null
@@ -1,31 +0,0 @@
-FROM debian:stretch-slim
-
-# metadata
-ARG VCS_REF
-ARG BUILD_DATE
-
-LABEL io.parity.image.authors="devops-team@parity.io" \
-	io.parity.image.vendor="Parity Technologies" \
-	io.parity.image.title="parity/subkey" \
-	io.parity.image.description="Subkey: key generating utility for Substrate." \
-	io.parity.image.source="https://github.com/paritytech/substrate/blob/${VCS_REF}/.maintain/docker/subkey.Dockerfile" \
-	io.parity.image.revision="${VCS_REF}" \
-	io.parity.image.created="${BUILD_DATE}" \
-	io.parity.image.documentation="https://github.com/paritytech/substrate/tree/${VCS_REF}/subkey"
-
-# show backtraces
-ENV RUST_BACKTRACE 1
-
-# add user
-RUN useradd -m -u 1000 -U -s /bin/sh -d /subkey subkey
-
-# add subkey binary to docker image
-COPY ./subkey /usr/local/bin
-
-USER subkey
-
-# check if executable works in this container
-RUN /usr/local/bin/subkey --version
-
-ENTRYPOINT ["/usr/local/bin/subkey"]
-
diff --git a/.maintain/docker/substrate.Dockerfile b/.maintain/docker/substrate.Dockerfile
deleted file mode 100644
index 7cd4576a9e..0000000000
--- a/.maintain/docker/substrate.Dockerfile
+++ /dev/null
@@ -1,45 +0,0 @@
-FROM debian:stretch-slim
-
-# metadata
-ARG VCS_REF
-ARG BUILD_DATE
-
-LABEL io.parity.image.authors="devops-team@parity.io" \
-	io.parity.image.vendor="Parity Technologies" \
-	io.parity.image.title="parity/substrate" \
-	io.parity.image.description="Substrate: The platform for blockchain innovators." \
-	io.parity.image.source="https://github.com/paritytech/substrate/blob/${VCS_REF}/.maintain/docker/Dockerfile" \
-	io.parity.image.revision="${VCS_REF}" \
-	io.parity.image.created="${BUILD_DATE}" \
-	io.parity.image.documentation="https://wiki.parity.io/Parity-Substrate"
-
-# show backtraces
-ENV RUST_BACKTRACE 1
-
-# install tools and dependencies
-RUN apt-get update && \
-	DEBIAN_FRONTEND=noninteractive apt-get upgrade -y && \
-	DEBIAN_FRONTEND=noninteractive apt-get install -y \
-		libssl1.1 \
-		ca-certificates \
-		curl && \
-# apt cleanup
-	apt-get autoremove -y && \
-	apt-get clean && \
-	find /var/lib/apt/lists/ -type f -not -name lock -delete; \
-# add user
-	useradd -m -u 1000 -U -s /bin/sh -d /substrate substrate
-
-# add substrate binary to docker image
-COPY ./substrate /usr/local/bin
-
-USER substrate
-
-# check if executable works in this container
-RUN /usr/local/bin/substrate --version
-
-EXPOSE 30333 9933 9944
-VOLUME ["/substrate"]
-
-ENTRYPOINT ["/usr/local/bin/substrate"]
-
diff --git a/.maintain/flamingfir-deploy.sh b/.maintain/flamingfir-deploy.sh
deleted file mode 100755
index 8f0fb3a2bc..0000000000
--- a/.maintain/flamingfir-deploy.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash
-
-RETRY_COUNT=10
-RETRY_ATTEMPT=0
-SLEEP_TIME=15
-TARGET_HOST="$1"
-COMMIT=$(cat artifacts/substrate/VERSION)
-DOWNLOAD_URL="https://releases.parity.io/substrate/x86_64-debian:stretch/${COMMIT}/substrate/substrate"
-POST_DATA='{"extra_vars":{"artifact_path":"'${DOWNLOAD_URL}'","target_host":"'${TARGET_HOST}'"}}'
-
-JOB_ID=$(wget -O - --header "Authorization: Bearer ${AWX_TOKEN}" --header "Content-type: application/json" --post-data "${POST_DATA}" https://ansible-awx.parity.io/api/v2/job_templates/32/launch/ | jq .job)
-
-echo "Launched job: $JOB_ID"
-
-
-while [ ${RETRY_ATTEMPT} -le ${RETRY_COUNT} ] ; do
-	export RETRY_RESULT=$(wget -O - --header "Authorization: Bearer ${AWX_TOKEN}"  https://ansible-awx.parity.io/api/v2/jobs/${JOB_ID}/ | jq .status)
-	RETRY_ATTEMPT=$(( $RETRY_ATTEMPT +1 ))
-	sleep $SLEEP_TIME
-	if [ $(echo $RETRY_RESULT | egrep  -e successful -e failed) ] ; then
-            break
-        fi
-done
-
-AWX_OUTPUT=$(wget -O - --header "Authorization: Bearer ${AWX_TOKEN}"  https://ansible-awx.parity.io/api/v2/jobs/${JOB_ID}/stdout?format=txt_download)
-
-echo "AWX job log:"
-echo "${AWX_OUTPUT}"
-
-
-JOB_STATUS=$(wget -O - --header "Authorization: Bearer ${AWX_TOKEN}"  https://ansible-awx.parity.io/api/v2/jobs/${JOB_ID}/ | jq .status )
-
-echo "==================================="
-echo -e "Ansible AWX Remote Job: ${JOB_ID} \x1B[31mStatus: ${JOB_STATUS}\x1B[0m"
-echo "==================================="
diff --git a/.maintain/gitlab/check_labels.sh b/.maintain/github/check_labels.sh
similarity index 76%
rename from .maintain/gitlab/check_labels.sh
rename to .maintain/github/check_labels.sh
index 5ab099b382..75190db668 100755
--- a/.maintain/gitlab/check_labels.sh
+++ b/.maintain/github/check_labels.sh
@@ -1,11 +1,14 @@
 #!/usr/bin/env bash
 
-#shellcheck source=lib.sh
-source "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/lib.sh"
+#shellcheck source=../common/lib.sh
+source "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/../common/lib.sh"
+
+repo="$GITHUB_REPOSITORY"
+pr="$GITHUB_PR"
 
 ensure_labels() {
   for label in "$@"; do
-    if has_label 'paritytech/substrate' "$CI_COMMIT_BRANCH" "$label"; then
+    if has_label "$repo" "$pr" "$label"; then
       return 0
     fi
   done
@@ -27,7 +30,7 @@ criticality_labels=(
   'C9-critical'
 )
 
-echo "[+] Checking release notes (B) labels for $CI_COMMIT_BRANCH"
+echo "[+] Checking release notes (B) labels"
 if ensure_labels "${releasenotes_labels[@]}";  then
   echo "[+] Release notes label detected. All is well."
 else
@@ -35,7 +38,7 @@ else
   exit 1
 fi
 
-echo "[+] Checking release criticality (C) labels for $CI_COMMIT_BRANCH"
+echo "[+] Checking release criticality (C) labels"
 if ensure_labels "${criticality_labels[@]}";  then
   echo "[+] Release criticality label detected. All is well."
 else
diff --git a/.maintain/gitlab/check_line_width.sh b/.maintain/gitlab/check_line_width.sh
deleted file mode 100755
index ebab3013e4..0000000000
--- a/.maintain/gitlab/check_line_width.sh
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/sh
-#
-# check if line width of rust source files is not beyond x characters
-#
-set -e
-set -o pipefail
-
-BASE_ORIGIN="origin"
-BASE_BRANCH_NAME="master"
-LINE_WIDTH="120"
-GOOD_LINE_WIDTH="100"
-BASE_BRANCH="${BASE_ORIGIN}/${BASE_BRANCH_NAME}"
-git fetch ${BASE_ORIGIN} ${BASE_BRANCH_NAME} --depth 100
-BASE_HASH=$(git merge-base ${BASE_BRANCH} HEAD)
-
-git diff --name-only ${BASE_HASH} -- \*.rs | ( while read file
-do
-  if [ ! -f ${file} ];
-  then
-	echo "Skipping removed file."
-  elif git diff ${BASE_HASH} -- ${file} | grep -q "^+.\{$(( $LINE_WIDTH + 1 ))\}"
-  then
-    if [ -z "${FAIL}" ]
-    then
-      echo "| error!"
-      echo "| Lines must not be longer than ${LINE_WIDTH} characters."
-      echo "| "
-      echo "| see more https://github.com/paritytech/substrate/blob/master/docs/STYLE_GUIDE.md"
-      echo "|"
-      FAIL="true"
-    fi
-    echo "| file: ${file}"
-    git diff ${BASE_HASH} -- ${file} \
-      | grep -n "^+.\{$(( $LINE_WIDTH + 1))\}"
-    echo "|"
-  else
-    if git diff ${BASE_HASH} -- ${file} | grep -q "^+.\{$(( $GOOD_LINE_WIDTH + 1 ))\}"
-    then
-      if [ -z "${FAIL}" ]
-      then
-        echo "| warning!"
-        echo "| Lines should be longer than ${GOOD_LINE_WIDTH} characters only in exceptional circumstances!"
-        echo "| "
-        echo "| see more https://github.com/paritytech/substrate/blob/master/docs/STYLE_GUIDE.md"
-        echo "|"
-      fi
-      echo "| file: ${file}"
-      git diff ${BASE_HASH} -- ${file} | grep -n "^+.\{$(( $GOOD_LINE_WIDTH + 1 ))\}"
-      echo "|"
-    fi
-  fi
-done
-
-test -z "${FAIL}"
-)
diff --git a/.maintain/gitlab/check_polkadot_companion_build.sh b/.maintain/gitlab/check_polkadot_companion_build.sh
deleted file mode 100755
index e5b308d038..0000000000
--- a/.maintain/gitlab/check_polkadot_companion_build.sh
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/env sh
-#
-# check if a pr is compatible with polkadot companion pr or master if not
-# available
-#
-# to override one that was just mentioned mark companion pr in the body of the
-# polkadot pr like
-#
-# polkadot companion: paritytech/polkadot#567
-#
-
-set -e
-
-github_api_substrate_pull_url="https://api.github.com/repos/paritytech/substrate/pulls"
-# use github api v3 in order to access the data without authentication
-github_header="Authorization: token ${GITHUB_PR_TOKEN}"
-
-boldprint () { printf "|\n| \033[1m${@}\033[0m\n|\n" ; }
-boldcat () { printf "|\n"; while read l; do printf "| \033[1m${l}\033[0m\n"; done; printf "|\n" ; }
-
-
-
-boldcat <<-EOT
-
-
-check_polkadot_companion_build
-==============================
-
-this job checks if there is a string in the description of the pr like
-
-polkadot companion: paritytech/polkadot#567
-
-
-it will then run cargo check from this polkadot's branch with substrate code
-from this pull request. otherwise, it will uses master instead
-
-
-EOT
-
-# Set the user name and email to make merging work
-git config --global user.name 'CI system'
-git config --global user.email '<>'
-
-# Merge master into our branch before building Polkadot to make sure we don't miss
-# any commits that are required by Polkadot.
-git fetch --depth 100 origin
-git merge origin/master
-
-# Clone the current Polkadot master branch into ./polkadot.
-# NOTE: we need to pull enough commits to be able to find a common
-# ancestor for successfully performing merges below.
-git clone --depth 20 https://github.com/paritytech/polkadot.git
-
-cargo install -f diener
-
-cd polkadot
-
-# either it's a pull request then check for a companion otherwise use
-# polkadot:master
-if expr match "${CI_COMMIT_REF_NAME}" '^[0-9]\+$' >/dev/null
-then
-  boldprint "this is pull request no ${CI_COMMIT_REF_NAME}"
-
-  pr_data_file="$(mktemp)"
-  # get the last reference to a pr in polkadot
-  curl -sSL -H "${github_header}" -o "${pr_data_file}" \
-    "${github_api_substrate_pull_url}/${CI_COMMIT_REF_NAME}"
-
-  pr_body="$(sed -n -r 's/^[[:space:]]+"body": (".*")[^"]+$/\1/p' "${pr_data_file}")"
-
-  pr_companion="$(echo "${pr_body}" | sed -n -r \
-      -e 's;^.*[Cc]ompanion.*paritytech/polkadot#([0-9]+).*$;\1;p' \
-      -e 's;^.*[Cc]ompanion.*https://github.com/paritytech/polkadot/pull/([0-9]+).*$;\1;p' \
-    | tail -n 1)"
-
-  if [ "${pr_companion}" ]
-  then
-    boldprint "companion pr specified/detected: #${pr_companion}"
-    git fetch origin refs/pull/${pr_companion}/head:pr/${pr_companion}
-    git checkout pr/${pr_companion}
-    git merge origin/master
-  else
-    boldprint "no companion branch found - building polkadot:master"
-  fi
-  rm -f "${pr_data_file}"
-else
-  boldprint "this is not a pull request - building polkadot:master"
-fi
-
-# Patch all Substrate crates in Polkadot
-diener patch --crates-to-patch ../ --substrate
-
-# 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/gitlab/check_polkadot_companion_status.sh b/.maintain/gitlab/check_polkadot_companion_status.sh
deleted file mode 100755
index 4714baf54f..0000000000
--- a/.maintain/gitlab/check_polkadot_companion_status.sh
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/bin/sh
-#
-# check for a polkadot companion pr and ensure it has approvals and is
-# mergeable
-#
-
-github_api_substrate_pull_url="https://api.github.com/repos/paritytech/substrate/pulls"
-github_api_polkadot_pull_url="https://api.github.com/repos/paritytech/polkadot/pulls"
-# use github api v3 in order to access the data without authentication
-github_header="Authorization: token ${GITHUB_PR_TOKEN}"
-
-boldprint () { printf "|\n| \033[1m${@}\033[0m\n|\n" ; }
-boldcat () { printf "|\n"; while read l; do printf "| \033[1m${l}\033[0m\n"; done; printf "|\n" ; }
-
-
-
-boldcat <<-EOT
-
-
-check_polkadot_companion_status
-===============================
-
-this job checks if there is a string in the description of the pr like
-
-polkadot companion: paritytech/polkadot#567
-
-and checks its status.
-
-
-EOT
-
-
-if ! [ "${CI_COMMIT_REF_NAME}" -gt 0 2>/dev/null ]
-then
-  boldprint "this doesn't seem to be a pull request"
-  exit 1
-fi
-
-boldprint "this is pull request no ${CI_COMMIT_REF_NAME}"
-
-pr_body="$(curl -H "${github_header}" -s ${github_api_substrate_pull_url}/${CI_COMMIT_REF_NAME} \
-  | sed -n -r 's/^[[:space:]]+"body": (".*")[^"]+$/\1/p')"
-
-# get companion if explicitly specified
-pr_companion="$(echo "${pr_body}" | sed -n -r \
-    -e 's;^.*[Cc]ompanion.*paritytech/polkadot#([0-9]+).*$;\1;p' \
-    -e 's;^.*[Cc]ompanion.*https://github.com/paritytech/polkadot/pull/([0-9]+).*$;\1;p' \
-  | tail -n 1)"
-
-if [ -z "${pr_companion}" ]
-then
-  boldprint "no companion pr found"
-  exit 0
-fi
-
-boldprint "companion pr: #${pr_companion}"
-
-# check the status of that pull request - needs to be
-# mergable and approved
-
-curl -H "${github_header}" -sS -o companion_pr.json \
-  ${github_api_polkadot_pull_url}/${pr_companion}
-
-pr_head_sha=$(jq -r -e '.head.sha' < companion_pr.json)
-boldprint "Polkadot PR's HEAD SHA: $pr_head_sha"
-
-if jq -e .merged < companion_pr.json >/dev/null
-then
-  boldprint "polkadot pr #${pr_companion} already merged"
-  exit 0
-fi
-
-if jq -e '.mergeable' < companion_pr.json >/dev/null
-then
-  boldprint "polkadot pr #${pr_companion} mergeable"
-else
-  boldprint "polkadot pr #${pr_companion} not mergeable"
-  exit 1
-fi
-
-curl -H "${github_header}" -sS -o companion_pr_reviews.json \
-  ${github_api_polkadot_pull_url}/${pr_companion}/reviews
-
-# If there are any 'CHANGES_REQUESTED' reviews for the *current* review
-jq -r -e '.[] | select(.state == "CHANGES_REQUESTED").commit_id' \
-  < companion_pr_reviews.json > companion_pr_reviews_current.json
-while IFS= read -r line; do
-  if [ "$line" = "$pr_head_sha" ]; then
-    boldprint "polkadot pr #${pr_companion} has CHANGES_REQUESTED for the latest commit"
-    exit 1
-  fi
-done < companion_pr_reviews_current.json
-
-# Then we check for at least 1 APPROVED
-if [ -z "$(jq -r -e '.[].state | select(. == "APPROVED")' < companion_pr_reviews.json)" ]; then
-  boldprint "polkadot pr #${pr_companion} not APPROVED"
-  exit 1
-fi
-
-boldprint "polkadot pr #${pr_companion} state APPROVED"
-exit 0
-
-
diff --git a/.maintain/gitlab/check_runtime.sh b/.maintain/gitlab/check_runtime.sh
deleted file mode 100755
index 6d009c5aaf..0000000000
--- a/.maintain/gitlab/check_runtime.sh
+++ /dev/null
@@ -1,124 +0,0 @@
-#!/bin/sh
-#
-#
-# check for any changes in the node/src/runtime, frame/ and primitives/sr_* trees. if
-# there are any changes found, it should mark the PR breaksconsensus and
-# "auto-fail" the PR if there isn't a change in the runtime/src/lib.rs file
-# that alters the version.
-
-set -e # fail on any error
-
-
-
-VERSIONS_FILE="bin/node/runtime/src/lib.rs"
-
-boldprint () { printf "|\n| \033[1m${@}\033[0m\n|\n" ; }
-boldcat () { printf "|\n"; while read l; do printf "| \033[1m${l}\033[0m\n"; done; printf "|\n" ; }
-
-github_label () {
-	echo
-	echo "# run github-api job for labeling it ${1}"
-	curl -sS -X POST \
-		-F "token=${CI_JOB_TOKEN}" \
-		-F "ref=master" \
-		-F "variables[LABEL]=${1}" \
-		-F "variables[PRNO]=${CI_COMMIT_REF_NAME}" \
-		${GITLAB_API}/projects/${GITHUB_API_PROJECT}/trigger/pipeline
-}
-
-
-boldprint "latest 10 commits of ${CI_COMMIT_REF_NAME}"
-git log --graph --oneline --decorate=short -n 10
-
-boldprint "make sure the master branch and release tag are available in shallow clones"
-git fetch --depth=${GIT_DEPTH:-100} origin master
-git fetch --depth=${GIT_DEPTH:-100} origin release
-git tag -f release FETCH_HEAD
-git log -n1 release
-
-
-boldprint "check if the wasm sources changed"
-if ! git diff --name-only origin/master...${CI_COMMIT_SHA} \
-	| grep -v -e '^primitives/sr-arithmetic/fuzzer' \
-	| grep -q -e '^bin/node/src/runtime' -e '^frame/' -e '^primitives/sr-'
-then
-	boldcat <<-EOT
-
-	no changes to the runtime source code detected
-
-	EOT
-
-	exit 0
-fi
-
-
-
-# check for spec_version updates: if the spec versions changed, then there is
-# consensus-critical logic that has changed. the runtime wasm blobs must be
-# rebuilt.
-
-add_spec_version="$(git diff tags/release...${CI_COMMIT_SHA} ${VERSIONS_FILE} \
-	| sed -n -r "s/^\+[[:space:]]+spec_version: +([0-9]+),$/\1/p")"
-sub_spec_version="$(git diff tags/release...${CI_COMMIT_SHA} ${VERSIONS_FILE} \
-	| sed -n -r "s/^\-[[:space:]]+spec_version: +([0-9]+),$/\1/p")"
-
-
-
-if [ "${add_spec_version}" != "${sub_spec_version}" ]
-then
-
-	github_label "D2-breaksapi"
-
-	boldcat <<-EOT
-
-		changes to the runtime sources and changes in the spec version.
-
-		spec_version: ${sub_spec_version} -> ${add_spec_version}
-
-	EOT
-	exit 0
-
-else
-	# check for impl_version updates: if only the impl versions changed, we assume
-	# there is no consensus-critical logic that has changed.
-
-	add_impl_version="$(git diff tags/release...${CI_COMMIT_SHA} ${VERSIONS_FILE} \
-		| sed -n -r 's/^\+[[:space:]]+impl_version: +([0-9]+),$/\1/p')"
-	sub_impl_version="$(git diff tags/release...${CI_COMMIT_SHA} ${VERSIONS_FILE} \
-		| sed -n -r 's/^\-[[:space:]]+impl_version: +([0-9]+),$/\1/p')"
-
-
-	# see if the impl version changed
-	if [ "${add_impl_version}" != "${sub_impl_version}" ]
-	then
-		boldcat <<-EOT
-
-		changes to the runtime sources and changes in the impl version.
-
-		impl_version: ${sub_impl_version} -> ${add_impl_version}
-
-		EOT
-		exit 0
-	fi
-
-
-	boldcat <<-EOT
-
-	wasm source files changed but not the spec/impl version. If changes made do not alter logic,
-	just bump 'impl_version'. If they do change logic, bump 'spec_version'.
-
-	source file directories:
-	- bin/node/src/runtime
-	- frame
-	- primitives/sr-*
-
-	versions file: ${VERSIONS_FILE}
-
-	EOT
-fi
-
-# dropped through. there's something wrong;  exit 1.
-
-exit 1
-
-# vim: noexpandtab
diff --git a/.maintain/gitlab/check_signed.sh b/.maintain/gitlab/check_signed.sh
deleted file mode 100755
index 7c4cc47bab..0000000000
--- a/.maintain/gitlab/check_signed.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env bash
-
-# shellcheck source=lib.sh
-source "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/lib.sh"
-
-version="$CI_COMMIT_TAG"
-
-echo '[+] Checking tag has been signed'
-check_tag "paritytech/substrate" "$version"
-case $? in
-  0) echo '[+] Tag found and has been signed'; exit 0
-    ;;
-  1) echo '[!] Tag found but has not been signed. Aborting release.'; exit 1
-    ;;
-  2) echo '[!] Tag not found. Aborting release.'; exit 1
-esac
diff --git a/.maintain/gitlab/generate_changelog.sh b/.maintain/gitlab/generate_changelog.sh
deleted file mode 100755
index c13871f50e..0000000000
--- a/.maintain/gitlab/generate_changelog.sh
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env bash
-
-# shellcheck source=lib.sh
-source "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/lib.sh"
-
-version="$2"
-last_version="$1"
-
-all_changes="$(sanitised_git_logs "$last_version" "$version")"
-runtime_changes=""
-api_changes=""
-client_changes=""
-changes=""
-migrations=""
-
-while IFS= read -r line; do
-  pr_id=$(echo "$line" | sed -E 's/.*#([0-9]+)\)$/\1/')
-
-  # Skip if the PR has the silent label - this allows us to skip a few requests
-  if has_label 'paritytech/substrate' "$pr_id" 'B0-silent'; then
-    continue
-  fi
-  if has_label 'paritytech/substrate' "$pr_id" 'B3-apinoteworthy' ; then
-    api_changes="$api_changes
-$line"
-  fi
-  if has_label 'paritytech/substrate' "$pr_id" 'B5-clientnoteworthy'; then
-    client_changes="$client_changes
-$line"
-  fi
-  if has_label 'paritytech/substrate' "$pr_id" 'B7-runtimenoteworthy'; then
-    runtime_changes="$runtime_changes
-$line"
-  fi
-  if has_label 'paritytech/substrate' "$pr_id" 'D1-runtime-migration'; then
-    migrations="$migrations
-$line"
-  fi
-done <<< "$all_changes"
-
-# Make the substrate section if there are any substrate changes
-if [ -n "$runtime_changes" ] ||
-   [ -n "$api_changes" ] ||
-   [ -n "$client_changes" ] ||
-   [ -n "$migrations" ]; then
-  changes=$(cat << EOF
-Substrate changes
------------------
-
-EOF
-)
-  if [ -n "$runtime_changes" ]; then
-    changes="$changes
-
-Runtime
--------
-$runtime_changes"
-  fi
-  if [ -n "$client_changes" ]; then
-    changes="$changes
-
-Client
-------
-$client_changes"
-  fi
-  if [ -n "$api_changes" ]; then
-    changes="$changes
-
-API
----
-$api_changes"
-  fi
-  release_text="$release_text
-
-$changes"
-fi
-if [ -n "$migrations" ]; then
-  changes="$changes
-
-Runtime Migrations
-------------------
-$migrations"
-fi
-
-echo "$changes"
diff --git a/.maintain/gitlab/publish_draft_release.sh b/.maintain/gitlab/publish_draft_release.sh
deleted file mode 100755
index c5813718a6..0000000000
--- a/.maintain/gitlab/publish_draft_release.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env bash
-
-# shellcheck source=lib.sh
-source "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/lib.sh"
-
-version="$CI_COMMIT_TAG"
-
-# Note that this is not the last *tagged* version, but the last *published* version
-last_version=$(last_github_release 'paritytech/substrate')
-
-release_text="$(./generate_release_text.sh "$last_version" "$version")"
-
-echo "[+] Pushing release to github"
-# Create release on github
-release_name="Substrate $version"
-data=$(jq -Rs --arg version "$version" \
-  --arg release_name "$release_name" \
-  --arg release_text "$release_text" \
-'{
-  "tag_name": $version,
-  "target_commitish": "master",
-  "name": $release_name,
-  "body": $release_text,
-  "draft": true,
-  "prerelease": false
-}' < /dev/null)
-
-out=$(curl -s -X POST --data "$data" -H "Authorization: token $GITHUB_RELEASE_TOKEN" "$api_base/paritytech/substrate/releases")
-
-html_url=$(echo "$out" | jq -r .html_url)
-
-if [ "$html_url" == "null" ]
-then
-  echo "[!] Something went wrong posting:"
-  echo "$out"
-else
-  echo "[+] Release draft created: $html_url"
-fi
-
-echo '[+] Sending draft release URL to Matrix'
-
-msg_body=$(cat <Release pipeline for Substrate $version complete.
-Draft release created: $html_url
-EOF
-)
-send_message "$(structure_message "$msg_body" "$formatted_msg_body")" "$MATRIX_ROOM_ID" "$MATRIX_ACCESS_TOKEN"
-
-echo "[+] Done! Maybe the release worked..."
diff --git a/.maintain/gitlab/skip_if_draft.sh b/.maintain/gitlab/skip_if_draft.sh
deleted file mode 100755
index cf6ea6a5b3..0000000000
--- a/.maintain/gitlab/skip_if_draft.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-url="https://api.github.com/repos/paritytech/substrate/pulls/${CI_COMMIT_REF_NAME}"
-echo "[+] API URL: $url"
-
-draft_state=$(curl -H "Authorization: token ${GITHUB_PR_TOKEN}" "$url" | jq -r .draft)
-echo "[+] Draft state: $draft_state"
-
-if [ "$draft_state" = 'true' ]; then
-  echo "[!] PR is currently a draft, stopping pipeline"
-  exit 1
-else
-  echo "[+] PR is not a draft. Proceeding with CI pipeline"
-  exit 0
-fi
diff --git a/.maintain/kubernetes/Chart.yaml b/.maintain/kubernetes/Chart.yaml
deleted file mode 100644
index 8e000ae09f..0000000000
--- a/.maintain/kubernetes/Chart.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-name: substrate
-version: 0.2
-appVersion: 0.9.1
-description: "Substrate: The platform for blockchain innovators"
-home: https://substrate.network/
-icon: https://substrate.network/favicon.ico
-sources:
-  - https://github.com/paritytech/substrate/
-maintainers:
-  - name: Paritytech Devops Team
-    email: devops-team@parity.io
-tillerVersion: ">=2.8.0"
diff --git a/.maintain/kubernetes/README.md b/.maintain/kubernetes/README.md
deleted file mode 100644
index 0f3ec38990..0000000000
--- a/.maintain/kubernetes/README.md
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-# Substrate Kubernetes Helm Chart
-
-This [Helm Chart](https://helm.sh/) can be used for deploying containerized 
-**Substrate** to a [Kubernetes](https://kubernetes.io/) cluster.
-
-
-## Prerequisites
-
-- Tested on Kubernetes 1.10.7-gke.6
-
-## Installation
-
-To install the chart with the release name `my-release` into namespace 
-`my-namespace` from within this directory:
-
-```console
-$ helm install --namespace my-namespace --name my-release --values values.yaml ./
-```
-
-The command deploys Substrate on the Kubernetes cluster in the configuration 
-given in `values.yaml`. When the namespace is omitted it'll be installed in 
-the default one.
-
-
-## Removal of the Chart
-
-To uninstall/delete the `my-release` deployment:
-
-```console
-$ helm delete --namespace my-namespace my-release
-```
-
-The command removes all the Kubernetes components associated with the chart and deletes the release.
-
-
-## Upgrading
-
-Once the chart is installed and a new version should be deployed helm takes 
-care of this by
-
-```console
-$ helm upgrade --namespace my-namespace --values values.yaml my-release ./
-```
-
-
diff --git a/.maintain/kubernetes/templates/poddisruptionbudget.yaml b/.maintain/kubernetes/templates/poddisruptionbudget.yaml
deleted file mode 100644
index 56958b1fba..0000000000
--- a/.maintain/kubernetes/templates/poddisruptionbudget.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-apiVersion: policy/v1beta1
-kind: PodDisruptionBudget
-metadata:
-  name: {{ .Values.GitlabEnvSlug | default .Values.app }}
-spec:
-  selector:
-    matchLabels:
-      app: {{ .Values.GitlabEnvSlug | default .Values.app }}
-  maxUnavailable: 1
-
diff --git a/.maintain/kubernetes/templates/secrets.yaml b/.maintain/kubernetes/templates/secrets.yaml
deleted file mode 100644
index 97e73ae7ff..0000000000
--- a/.maintain/kubernetes/templates/secrets.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-{{- if .Values.validator.keys }}
-apiVersion: v1
-kind: Secret
-metadata:
-  name: {{ .Values.app }}-secrets
-  labels:
-    app: {{ .Values.GitlabEnvSlug | default .Values.app }}
-type: Opaque
-data:
-  secrets: {{ .Values.validator.keys | default "" }}
-{{- end }}
diff --git a/.maintain/kubernetes/templates/service.yaml b/.maintain/kubernetes/templates/service.yaml
deleted file mode 100644
index b14bb74c10..0000000000
--- a/.maintain/kubernetes/templates/service.yaml
+++ /dev/null
@@ -1,54 +0,0 @@
-# see:
-# https://kubernetes.io/docs/tutorials/services/
-# https://kubernetes.io/docs/concepts/services-networking/service/
-# headless service for rpc
-apiVersion: v1
-kind: Service
-metadata:
-  name: {{ .Values.app }}-rpc
-spec:
-  ports:
-  - port: 9933
-    name: http-rpc
-  - port: 9944
-    name: websocket-rpc
-  selector:
-    app: {{ .Values.GitlabEnvSlug | default .Values.app }}
-  sessionAffinity: None
-  type: ClusterIP
-  clusterIP: None
----
-{{- if .Values.listen_node_port }}
-apiVersion: v1
-kind: Service
-metadata:
-  name: {{ .Values.app }}
-spec:
-  ports:
-  - port: 30333
-    name: p2p
-    nodePort: 30333
-    protocol: TCP
-  selector:
-    app: {{ .Values.GitlabEnvSlug | default .Values.app }}
-  sessionAffinity: None
-  type: NodePort
-  # don't route external traffic to non-local pods
-  externalTrafficPolicy: Local
-{{- else if .Values.validator.keys }}
-{{- $root := . -}}
-{{- range until (int .Values.nodes.replicas) }}
----
-kind: Service
-apiVersion: v1
-metadata:
-  name: {{ $root.Values.app }}-{{ . }}
-spec:
-  selector:
-    statefulset.kubernetes.io/pod-name: {{ $root.Values.app }}-{{ . }}
-  ports:
-    - port: 30333
-      targetPort: 30333
-      protocol: TCP
-{{- end }}
-{{- end }}
diff --git a/.maintain/kubernetes/templates/serviceaccount.yaml b/.maintain/kubernetes/templates/serviceaccount.yaml
deleted file mode 100644
index 53d016bffe..0000000000
--- a/.maintain/kubernetes/templates/serviceaccount.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-{{- if .Values.rbac.enable }}
-# service account for substrate pods themselves
-# no permissions for the api are required
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    app: {{ .Values.GitlabEnvSlug | default .Values.app }}
-  name: {{ .Values.rbac.name }}
-{{- end }}
diff --git a/.maintain/kubernetes/templates/statefulset.yaml b/.maintain/kubernetes/templates/statefulset.yaml
deleted file mode 100644
index 0f34b3507a..0000000000
--- a/.maintain/kubernetes/templates/statefulset.yaml
+++ /dev/null
@@ -1,139 +0,0 @@
-# https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/
-# https://cloud.google.com/kubernetes-engine/docs/concepts/statefulset
-apiVersion: apps/v1
-kind: StatefulSet
-metadata:
-  name: {{ .Values.app }}
-spec:
-  selector:
-    matchLabels:
-      app: {{ .Values.GitlabEnvSlug | default .Values.app }}
-  serviceName: {{ .Values.app }}
-  replicas: {{ .Values.nodes.replicas }}
-  updateStrategy:
-    type: RollingUpdate
-  podManagementPolicy: Parallel
-  template:
-    metadata:
-      labels:
-        app: {{ .Values.GitlabEnvSlug | default .Values.app }}
-    spec:
-      {{- if .Values.rbac.enable }}
-      serviceAccountName: {{ .Values.rbac.name }}
-      {{- else }}
-      serviceAccountName: default
-      {{- end }}
-      affinity:
-        nodeAffinity:
-          requiredDuringSchedulingIgnoredDuringExecution:
-            nodeSelectorTerms:
-            - matchExpressions:
-                - key: node
-                  operator: In
-                  values:
-                  - substrate
-        {{- if .Values.listen_node_port }}
-        podAntiAffinity:
-          requiredDuringSchedulingIgnoredDuringExecution:
-            - labelSelector:
-                matchExpressions:
-                  - key: "app"
-                    operator: In
-                    values:
-                    - {{ .Values.app }}
-              topologyKey: "kubernetes.io/hostname"
-        {{- end }}
-      terminationGracePeriodSeconds: 300
-      {{- if .Values.validator.keys }}
-      volumes:
-        - name: {{ .Values.app }}-validator-secrets
-          secret:
-            secretName: {{ .Values.app }}-secrets
-      initContainers:
-      - name: prepare-secrets
-        image: busybox
-        command: [ "/bin/sh" ]
-        args:
-          - -c
-          - sed -n -r "s/^${POD_NAME}-key ([^ ]+)$/\1/p" /etc/validator/secrets > {{ .Values.image.basepath }}/key;
-            sed -n -r "s/^${POD_NAME}-node-key ([^ ]+)$/\1/p" /etc/validator/secrets > {{ .Values.image.basepath }}/node-key;
-            sed -n -r "s/^${POD_NAME}-name ([^ ]+)$/\1/p" /etc/validator/secrets > {{ .Values.image.basepath }}/name;
-            test -s {{ .Values.image.basepath }}/name || echo "${POD_NAME}" > {{ .Values.image.basepath }}/name
-        env:
-          # from (workaround for hostname)
-          # https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/
-          - name: POD_NAME
-            valueFrom:
-              fieldRef:
-                fieldPath: metadata.name
-        volumeMounts:
-        - name: {{ .Values.app }}-validator-secrets
-          readOnly: true
-          mountPath: "/etc/validator"
-        - name: {{ .Values.app }}dir
-          mountPath: {{ .Values.image.basepath }}
-      {{- end }}
-      containers:
-      - name: {{ .Values.app }}
-        imagePullPolicy: "{{ .Values.image.pullPolicy }}"
-        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
-        {{- if .Values.resources }}
-        resources:
-          requests:
-            memory: {{ .Values.resources.memory }}
-            cpu: {{ .Values.resources.cpu }}
-        {{- end }}
-        ports:
-        - containerPort: 30333
-          name: p2p
-        - containerPort: 9933
-          name: http-rpc
-        - containerPort: 9944
-          name: websocket-rpc
-        command: ["/bin/sh"]
-        args:
-          - -c
-          - exec /usr/local/bin/substrate
-            --base-path {{ .Values.image.basepath }}
-            {{- if .Values.validator.keys }}
-            --validator
-            --name $(cat {{ .Values.image.basepath }}/name)
-            --key $(cat {{ .Values.image.basepath }}/key)
-            --node-key $(cat {{ .Values.image.basepath }}/node-key)
-            {{- else }}
-            --name $(POD_NAME)
-            {{- end }}
-            {{- range .Values.nodes.args }} {{ . }} {{- end }}
-        env:
-          - name: POD_NAME
-            valueFrom:
-              fieldRef:
-                fieldPath: metadata.name
-        volumeMounts:
-        - name: {{ .Values.app }}dir
-          mountPath: {{ .Values.image.basepath }}
-        readinessProbe:
-          httpGet:
-            path: /health
-            port: http-rpc
-          initialDelaySeconds: 10
-          periodSeconds: 10
-        livenessProbe:
-          httpGet:
-            path: /health
-            port: http-rpc
-          initialDelaySeconds: 10
-          periodSeconds: 10
-      securityContext:
-        runAsUser: 1000
-        fsGroup: 1000
-  volumeClaimTemplates:
-  - metadata:
-      name: {{ .Values.app }}dir
-    spec:
-      accessModes: [ "ReadWriteOnce" ]
-      storageClassName: ssd
-      resources:
-        requests:
-          storage: 32Gi
-
diff --git a/.maintain/kubernetes/values.yaml b/.maintain/kubernetes/values.yaml
deleted file mode 100644
index 4c3cb5c7d7..0000000000
--- a/.maintain/kubernetes/values.yaml
+++ /dev/null
@@ -1,59 +0,0 @@
-# set tag manually --set image.tag=latest
-image:
-  repository: parity/substrate
-  tag: latest
-  pullPolicy: Always
-  basepath: /substrate
-
-
-# if set to true a service account for substrate will be created
-rbac:
-  enable: true
-  name: substrate
-
-
-# name of the statefulset
-app: substrate
-listen_node_port: true
-
-nodes:
-  replicas: 2
-  args:
-    # name and data directory are set by the chart itself
-    # key and node-key may be provided on commandline invocation
-    #
-    # - --chain
-    # - krummelanke
-    # serve rpc within the local network
-    # - fenced off the world via firewall
-    # - used for health checks
-    - --rpc-external
-    - --ws-external
-    # - --log
-    # - sub-libp2p=trace
-
-
-validator: {}
-  # providing 'keys' string via --set commandline parameter will run the nodes
-  # in validator mode (--validator).
-  #
-  # name, key and node-key can be given in a base64 encoded keyfile string (at
-  # validator.keys) which has the following format:
-  #
-  # substrate-0-name 
-  # substrate-0-key 
-  # substrate-0-node-key 
-  # substrate-1-name 
-  # substrate-1-key 
-  # substrate-1-node-key 
-  #
-  # pod names are canonical. changing these or providing different amount of
-  # keys than the replicas count will lead to behavior no one ever has
-  # experienced before.
-
-
-# maybe adopt resource limits here to the nodes of the pool
-# resources:
-#   memory: "5Gi"
-#   cpu: "1.5"
-
diff --git a/.maintain/monitoring/alerting-rules/alerting-rules.yaml b/.maintain/monitoring/alerting-rules/alerting-rules.yaml
index cf00d7e2b9..5ee2376677 100644
--- a/.maintain/monitoring/alerting-rules/alerting-rules.yaml
+++ b/.maintain/monitoring/alerting-rules/alerting-rules.yaml
@@ -108,6 +108,13 @@ groups:
     annotations:
       message: 'The node {{ $labels.instance }} has less than 3 peers for more
       than 15 minutes'
+  - alert: NoIncomingConnection
+    expr: increase(polkadot_sub_libp2p_incoming_connections_total[20m]) == 0
+    labels:
+      severity: warning
+    annotations:
+      message: 'The node {{ $labels.instance }} has not received any new incoming
+      TCP connection in the past 20 minutes. Is it connected to the Internet?'
 
   ##############################################################################
   # System
diff --git a/.maintain/monitoring/grafana-dashboards/substrate-networking.json b/.maintain/monitoring/grafana-dashboards/substrate-networking.json
index d2abfd1cb8..0b157e7205 100644
--- a/.maintain/monitoring/grafana-dashboards/substrate-networking.json
+++ b/.maintain/monitoring/grafana-dashboards/substrate-networking.json
@@ -74,7 +74,7 @@
   "gnetId": null,
   "graphTooltip": 0,
   "id": null,
-  "iteration": 1610462565248,
+  "iteration": 1613393276921,
   "links": [],
   "panels": [
     {
@@ -963,7 +963,8 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "irate(${metric_namespace}_sub_libp2p_requests_out_started_total{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])",
+          "expr": "irate(${metric_namespace}_sub_libp2p_requests_out_success_total_sum{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m]) + on(instance) sum(irate(${metric_namespace}_sub_libp2p_requests_out_failure_total{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance)",
+          "hide": false,
           "interval": "",
           "legendFormat": "{{instance}}",
           "refId": "A"
@@ -989,6 +990,7 @@
       },
       "yaxes": [
         {
+          "$$hashKey": "object:209",
           "format": "reqps",
           "label": null,
           "logBase": 1,
@@ -997,6 +999,7 @@
           "show": true
         },
         {
+          "$$hashKey": "object:210",
           "format": "short",
           "label": null,
           "logBase": 1,
@@ -1032,7 +1035,7 @@
         "y": 51
       },
       "hiddenSeries": false,
-      "id": 151,
+      "id": 448,
       "legend": {
         "avg": false,
         "current": false,
@@ -1060,9 +1063,11 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "irate(${metric_namespace}_sub_libp2p_requests_in_success_total_count{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])",
+          "expr": "sum(irate(${metric_namespace}_sub_libp2p_requests_out_failure_total{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[$__rate_interval])) by (instance, reason)",
+          "hide": false,
           "interval": "",
-          "legendFormat": "{{instance}}",
+          "intervalFactor": 1,
+          "legendFormat": "{{reason}}",
           "refId": "A"
         }
       ],
@@ -1070,7 +1075,7 @@
       "timeFrom": null,
       "timeRegions": [],
       "timeShift": null,
-      "title": "Requests served per second",
+      "title": "Outbound requests failures",
       "tooltip": {
         "shared": true,
         "sort": 2,
@@ -1086,6 +1091,7 @@
       },
       "yaxes": [
         {
+          "$$hashKey": "object:209",
           "format": "reqps",
           "label": null,
           "logBase": 1,
@@ -1094,6 +1100,7 @@
           "show": true
         },
         {
+          "$$hashKey": "object:210",
           "format": "short",
           "label": null,
           "logBase": 1,
@@ -1227,7 +1234,7 @@
         "y": 59
       },
       "hiddenSeries": false,
-      "id": 258,
+      "id": 257,
       "legend": {
         "avg": false,
         "current": false,
@@ -1239,7 +1246,7 @@
       },
       "lines": true,
       "linewidth": 1,
-      "nullPointMode": "null",
+      "nullPointMode": "null as zero",
       "options": {
         "alertThreshold": true
       },
@@ -1255,7 +1262,8 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "histogram_quantile(0.5, sum(rate(${metric_namespace}_sub_libp2p_requests_in_success_total_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le))",
+          "expr": "histogram_quantile(0.99, sum(rate(${metric_namespace}_sub_libp2p_requests_out_success_total_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le)) > 0",
+          "instant": false,
           "interval": "",
           "legendFormat": "{{instance}}",
           "refId": "A"
@@ -1265,7 +1273,7 @@
       "timeFrom": null,
       "timeRegions": [],
       "timeShift": null,
-      "title": "Median request serving time",
+      "title": "99th percentile request answer time",
       "tooltip": {
         "shared": true,
         "sort": 2,
@@ -1324,7 +1332,7 @@
         "y": 63
       },
       "hiddenSeries": false,
-      "id": 257,
+      "id": 151,
       "legend": {
         "avg": false,
         "current": false,
@@ -1336,7 +1344,7 @@
       },
       "lines": true,
       "linewidth": 1,
-      "nullPointMode": "null as zero",
+      "nullPointMode": "null",
       "options": {
         "alertThreshold": true
       },
@@ -1352,8 +1360,7 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "histogram_quantile(0.99, sum(rate(${metric_namespace}_sub_libp2p_requests_out_success_total_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le)) > 0",
-          "instant": false,
+          "expr": "irate(${metric_namespace}_sub_libp2p_requests_in_success_total_count{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])",
           "interval": "",
           "legendFormat": "{{instance}}",
           "refId": "A"
@@ -1363,7 +1370,7 @@
       "timeFrom": null,
       "timeRegions": [],
       "timeShift": null,
-      "title": "99th percentile request answer time",
+      "title": "Requests served per second",
       "tooltip": {
         "shared": true,
         "sort": 2,
@@ -1379,7 +1386,7 @@
       },
       "yaxes": [
         {
-          "format": "s",
+          "format": "reqps",
           "label": null,
           "logBase": 1,
           "max": null,
@@ -1422,7 +1429,7 @@
         "y": 67
       },
       "hiddenSeries": false,
-      "id": 259,
+      "id": 449,
       "legend": {
         "avg": false,
         "current": false,
@@ -1434,7 +1441,7 @@
       },
       "lines": true,
       "linewidth": 1,
-      "nullPointMode": "null as zero",
+      "nullPointMode": "null",
       "options": {
         "alertThreshold": true
       },
@@ -1450,9 +1457,11 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "histogram_quantile(0.99, sum(rate(${metric_namespace}_sub_libp2p_requests_in_success_total_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le))",
+          "expr": "sum(irate(${metric_namespace}_sub_libp2p_requests_in_failure_total{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[$__rate_interval])) by (instance, reason)",
+          "hide": false,
           "interval": "",
-          "legendFormat": "{{instance}}",
+          "intervalFactor": 1,
+          "legendFormat": "{{reason}}",
           "refId": "A"
         }
       ],
@@ -1460,9 +1469,9 @@
       "timeFrom": null,
       "timeRegions": [],
       "timeShift": null,
-      "title": "99th percentile request serving time",
+      "title": "Inbound requests failures",
       "tooltip": {
-        "shared": false,
+        "shared": true,
         "sort": 2,
         "value_type": "individual"
       },
@@ -1476,7 +1485,8 @@
       },
       "yaxes": [
         {
-          "format": "s",
+          "$$hashKey": "object:209",
+          "format": "reqps",
           "label": null,
           "logBase": 1,
           "max": null,
@@ -1484,6 +1494,7 @@
           "show": true
         },
         {
+          "$$hashKey": "object:210",
           "format": "short",
           "label": null,
           "logBase": 1,
@@ -1519,7 +1530,7 @@
         "y": 71
       },
       "hiddenSeries": false,
-      "id": 287,
+      "id": 258,
       "legend": {
         "avg": false,
         "current": false,
@@ -1531,7 +1542,7 @@
       },
       "lines": true,
       "linewidth": 1,
-      "nullPointMode": "null as zero",
+      "nullPointMode": "null",
       "options": {
         "alertThreshold": true
       },
@@ -1547,10 +1558,9 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "avg(irate(${metric_namespace}_sub_libp2p_requests_out_failure_total{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (reason)",
-          "instant": false,
+          "expr": "histogram_quantile(0.5, sum(rate(${metric_namespace}_sub_libp2p_requests_in_success_total_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le))",
           "interval": "",
-          "legendFormat": "{{reason}}",
+          "legendFormat": "{{instance}}",
           "refId": "A"
         }
       ],
@@ -1558,7 +1568,7 @@
       "timeFrom": null,
       "timeRegions": [],
       "timeShift": null,
-      "title": "Outgoing request failures per second",
+      "title": "Median request serving time",
       "tooltip": {
         "shared": true,
         "sort": 2,
@@ -1574,7 +1584,7 @@
       },
       "yaxes": [
         {
-          "format": "short",
+          "format": "s",
           "label": null,
           "logBase": 1,
           "max": null,
@@ -1617,7 +1627,7 @@
         "y": 75
       },
       "hiddenSeries": false,
-      "id": 286,
+      "id": 259,
       "legend": {
         "avg": false,
         "current": false,
@@ -1645,10 +1655,9 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "avg(irate(${metric_namespace}_sub_libp2p_requests_in_failure_total{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (reason)",
-          "instant": false,
+          "expr": "histogram_quantile(0.99, sum(rate(${metric_namespace}_sub_libp2p_requests_in_success_total_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le))",
           "interval": "",
-          "legendFormat": "{{reason}}",
+          "legendFormat": "{{instance}}",
           "refId": "A"
         }
       ],
@@ -1656,9 +1665,9 @@
       "timeFrom": null,
       "timeRegions": [],
       "timeShift": null,
-      "title": "Ingoing request failures per second",
+      "title": "99th percentile request serving time",
       "tooltip": {
-        "shared": true,
+        "shared": false,
         "sort": 2,
         "value_type": "individual"
       },
@@ -1672,7 +1681,7 @@
       },
       "yaxes": [
         {
-          "format": "short",
+          "format": "s",
           "label": null,
           "logBase": 1,
           "max": null,
@@ -1845,7 +1854,7 @@
       "lines": true,
       "linewidth": 1,
       "maxPerRow": 12,
-      "nullPointMode": "null as zero",
+      "nullPointMode": "connected",
       "options": {
         "alertThreshold": true
       },
@@ -1871,7 +1880,7 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "avg by (direction) (irate(${metric_namespace}_sub_libp2p_notifications_sizes_count{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[$__interval]))",
+          "expr": "avg by (direction) (irate(${metric_namespace}_sub_libp2p_notifications_sizes_count{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[$__rate_interval]))",
           "interval": "",
           "legendFormat": "{{direction}}",
           "refId": "A"
@@ -1958,7 +1967,7 @@
       "lines": true,
       "linewidth": 1,
       "maxPerRow": 12,
-      "nullPointMode": "null as zero",
+      "nullPointMode": "connected",
       "options": {
         "alertThreshold": true
       },
@@ -1984,7 +1993,7 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "avg(irate(${metric_namespace}_sub_libp2p_notifications_sizes_sum{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[$__interval])) by (direction)",
+          "expr": "avg(irate(${metric_namespace}_sub_libp2p_notifications_sizes_sum{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[$__rate_interval])) by (direction)",
           "instant": false,
           "interval": "",
           "legendFormat": "{{direction}}",
@@ -2674,7 +2683,7 @@
         "allValue": null,
         "current": {},
         "datasource": "$data_source",
-        "definition": "${metric_namespace}_sub_libp2p_requests_out_started_total{instance=~\"${nodename}\"}",
+        "definition": "${metric_namespace}_sub_libp2p_requests_in_success_total_count{instance=~\"${nodename}\"}",
         "error": null,
         "hide": 2,
         "includeAll": true,
@@ -2682,7 +2691,7 @@
         "multi": false,
         "name": "request_protocol",
         "options": [],
-        "query": "${metric_namespace}_sub_libp2p_requests_out_started_total{instance=~\"${nodename}\"}",
+        "query": "${metric_namespace}_sub_libp2p_requests_in_success_total_count{instance=~\"${nodename}\"}",
         "refresh": 1,
         "regex": "/protocol=\"(.*?)\"/",
         "skipUrlSync": false,
@@ -2707,6 +2716,7 @@
         "name": "data_source",
         "options": [],
         "query": "prometheus",
+        "queryValue": "",
         "refresh": 1,
         "regex": "",
         "skipUrlSync": false,
@@ -2756,5 +2766,5 @@
   "timezone": "utc",
   "title": "Substrate Networking",
   "uid": "vKVuiD9Zk",
-  "version": 147
-}
+  "version": 154
+}
\ No newline at end of file
diff --git a/.maintain/monitoring/grafana-dashboards/substrate-service-tasks.json b/.maintain/monitoring/grafana-dashboards/substrate-service-tasks.json
index a3db46ec6d..944c9fb50c 100644
--- a/.maintain/monitoring/grafana-dashboards/substrate-service-tasks.json
+++ b/.maintain/monitoring/grafana-dashboards/substrate-service-tasks.json
@@ -37,6 +37,7 @@
   "annotations": {
     "list": [
       {
+        "$$hashKey": "object:326",
         "builtIn": 1,
         "datasource": "-- Grafana --",
         "enable": true,
@@ -48,6 +49,7 @@
         "type": "dashboard"
       },
       {
+        "$$hashKey": "object:327",
         "datasource": "$data_source",
         "enable": true,
         "expr": "increase(${metric_namespace}_tasks_ended_total{reason=\"panic\", instance=~\"${nodename}\"}[10m])",
@@ -64,6 +66,7 @@
         "type": "tags"
       },
       {
+        "$$hashKey": "object:621",
         "datasource": "$data_source",
         "enable": true,
         "expr": "changes(${metric_namespace}_process_start_time_seconds{instance=~\"${nodename}\"}[10m])",
@@ -81,7 +84,7 @@
   "gnetId": null,
   "graphTooltip": 0,
   "id": null,
-  "iteration": 1610462629581,
+  "iteration": 1613393319015,
   "links": [],
   "panels": [
     {
@@ -164,7 +167,7 @@
       },
       "lines": false,
       "linewidth": 1,
-      "nullPointMode": "null as zero",
+      "nullPointMode": "null",
       "options": {
         "alertThreshold": true
       },
@@ -180,7 +183,7 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "irate(${metric_namespace}_tasks_polling_duration_sum{instance=~\"${nodename}\"}[10m])",
+          "expr": "irate(${metric_namespace}_tasks_polling_duration_sum{instance=~\"${nodename}\"}[$__rate_interval])",
           "interval": "",
           "legendFormat": "{{task_name}}",
           "refId": "A"
@@ -206,6 +209,7 @@
       },
       "yaxes": [
         {
+          "$$hashKey": "object:2721",
           "format": "percentunit",
           "label": null,
           "logBase": 1,
@@ -214,6 +218,7 @@
           "show": true
         },
         {
+          "$$hashKey": "object:2722",
           "format": "short",
           "label": null,
           "logBase": 1,
@@ -266,7 +271,7 @@
       },
       "lines": true,
       "linewidth": 2,
-      "nullPointMode": "null",
+      "nullPointMode": "connected",
       "options": {
         "alertThreshold": true
       },
@@ -282,7 +287,7 @@
       "steppedLine": true,
       "targets": [
         {
-          "expr": "irate(${metric_namespace}_tasks_polling_duration_count{instance=~\"${nodename}\"}[10m])",
+          "expr": "irate(${metric_namespace}_tasks_polling_duration_count{instance=~\"${nodename}\"}[$__rate_interval])",
           "interval": "",
           "legendFormat": "{{task_name}}",
           "refId": "A"
@@ -308,6 +313,7 @@
       },
       "yaxes": [
         {
+          "$$hashKey": "object:2571",
           "format": "cps",
           "label": null,
           "logBase": 1,
@@ -316,6 +322,7 @@
           "show": true
         },
         {
+          "$$hashKey": "object:2572",
           "format": "short",
           "label": null,
           "logBase": 1,
@@ -382,7 +389,7 @@
       "steppedLine": true,
       "targets": [
         {
-          "expr": "irate(${metric_namespace}_tasks_spawned_total{instance=~\"${nodename}\"}[10m])",
+          "expr": "irate(${metric_namespace}_tasks_spawned_total{instance=~\"${nodename}\"}[$__rate_interval])",
           "interval": "",
           "legendFormat": "{{task_name}}",
           "refId": "A"
@@ -408,6 +415,7 @@
       },
       "yaxes": [
         {
+          "$$hashKey": "object:771",
           "format": "short",
           "label": null,
           "logBase": 10,
@@ -416,6 +424,7 @@
           "show": true
         },
         {
+          "$$hashKey": "object:772",
           "format": "short",
           "label": null,
           "logBase": 1,
@@ -466,7 +475,7 @@
       },
       "lines": true,
       "linewidth": 1,
-      "nullPointMode": "null as zero",
+      "nullPointMode": "connected",
       "options": {
         "alertThreshold": true
       },
@@ -508,6 +517,7 @@
       },
       "yaxes": [
         {
+          "$$hashKey": "object:919",
           "format": "short",
           "label": null,
           "logBase": 10,
@@ -516,6 +526,7 @@
           "show": true
         },
         {
+          "$$hashKey": "object:920",
           "format": "short",
           "label": null,
           "logBase": 1,
@@ -585,7 +596,7 @@
       "steppedLine": true,
       "targets": [
         {
-          "expr": "irate(${metric_namespace}_tasks_polling_duration_bucket{instance=~\"${nodename}\", le=\"+Inf\"}[10m])\n    - ignoring(le)\n  irate(${metric_namespace}_tasks_polling_duration_bucket{instance=~\"${nodename}\", le=\"1.024\"}[10m]) > 0",
+          "expr": "irate(${metric_namespace}_tasks_polling_duration_bucket{instance=~\"${nodename}\", le=\"+Inf\"}[$__rate_interval])\n    - ignoring(le)\n  irate(${metric_namespace}_tasks_polling_duration_bucket{instance=~\"${nodename}\", le=\"1.024\"}[$__rate_interval]) > 0",
           "interval": "",
           "legendFormat": "{{task_name}}",
           "refId": "A"
@@ -611,6 +622,7 @@
       },
       "yaxes": [
         {
+          "$$hashKey": "object:3040",
           "decimals": null,
           "format": "cps",
           "label": "Calls to `Future::poll`/second",
@@ -620,6 +632,7 @@
           "show": true
         },
         {
+          "$$hashKey": "object:3041",
           "format": "short",
           "label": null,
           "logBase": 1,
@@ -683,7 +696,7 @@
       },
       "lines": true,
       "linewidth": 1,
-      "nullPointMode": "null",
+      "nullPointMode": "connected",
       "options": {
         "alertThreshold": true
       },
@@ -725,6 +738,7 @@
       },
       "yaxes": [
         {
+          "$$hashKey": "object:626",
           "format": "short",
           "label": null,
           "logBase": 1,
@@ -733,6 +747,7 @@
           "show": true
         },
         {
+          "$$hashKey": "object:627",
           "format": "short",
           "label": null,
           "logBase": 1,
@@ -782,7 +797,7 @@
       },
       "lines": true,
       "linewidth": 1,
-      "nullPointMode": "null",
+      "nullPointMode": "connected",
       "options": {
         "alertThreshold": true
       },
@@ -798,7 +813,7 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "irate(${metric_namespace}_unbounded_channel_len{instance=~\"${nodename}\", action = \"send\"}[10m])",
+          "expr": "irate(${metric_namespace}_unbounded_channel_len{instance=~\"${nodename}\", action = \"send\"}[$__rate_interval])",
           "interval": "",
           "legendFormat": "{{entity}}",
           "refId": "B"
@@ -824,6 +839,7 @@
       },
       "yaxes": [
         {
+          "$$hashKey": "object:626",
           "format": "cps",
           "label": null,
           "logBase": 1,
@@ -832,6 +848,7 @@
           "show": true
         },
         {
+          "$$hashKey": "object:627",
           "format": "short",
           "label": null,
           "logBase": 1,
@@ -938,5 +955,5 @@
   "timezone": "utc",
   "title": "Substrate Service Tasks",
   "uid": "3LA6XNqZz",
-  "version": 59
-}
+  "version": 60
+}
\ No newline at end of file
diff --git a/.rustfmt.toml b/.rustfmt.toml
new file mode 100644
index 0000000000..5438b7f75d
--- /dev/null
+++ b/.rustfmt.toml
@@ -0,0 +1,4 @@
+# Conform to: https://wiki.parity.io/Substrate-Style-Guide
+reorder_imports = true
+hard_tabs = true
+max_width = 120
diff --git a/Cargo.lock b/Cargo.lock
index 6a7e638aee..3c4681ed35 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -175,11 +175,10 @@ dependencies = [
 
 [[package]]
 name = "assert_cmd"
-version = "1.0.3"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2475b58cd94eb4f70159f4fd8844ba3b807532fe3131b3373fae060bbe30396"
+checksum = "3dc1679af9a1ab4bea16f228b05d18f8363f8327b1fa8db00d2760cfafc6b61e"
 dependencies = [
- "bstr",
  "doc-comment",
  "predicates",
  "predicates-core",
@@ -193,6 +192,16 @@ version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "695579f0f2520f3774bb40461e5adb066459d4e0af4d59d20175484fb8e9edf1"
 
+[[package]]
+name = "async-attributes"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5"
+dependencies = [
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "async-channel"
 version = "1.5.1"
@@ -294,6 +303,7 @@ version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d9f06685bad74e0570f5213741bea82158279a4103d988e57bfada11ad230341"
 dependencies = [
+ "async-attributes",
  "async-channel",
  "async-global-executor",
  "async-io",
@@ -346,6 +356,19 @@ dependencies = [
  "pin-project-lite 0.2.4",
 ]
 
+[[package]]
+name = "asynchronous-codec"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0de5164e5edbf51c45fb8c2d9664ae1c095cce1b265ecf7569093c0d66ef690"
+dependencies = [
+ "bytes 1.0.1",
+ "futures-sink",
+ "futures-util",
+ "memchr",
+ "pin-project-lite 0.2.4",
+]
+
 [[package]]
 name = "atomic"
 version = "0.5.0"
@@ -1464,9 +1487,9 @@ dependencies = [
 
 [[package]]
 name = "env_logger"
-version = "0.8.3"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f"
+checksum = "f26ecb66b4bdca6c1409b40fb255eefc2bd4f6d135dab3c3124f80ffa2a9661e"
 dependencies = [
  "atty",
  "humantime 2.1.0",
@@ -1590,9 +1613,9 @@ dependencies = [
 
 [[package]]
 name = "finality-grandpa"
-version = "0.13.0"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cd795898c348a8ec9edc66ec9e014031c764d4c88cc26d09b492cd93eb41339"
+checksum = "c6447e2f8178843749e8c8003206def83ec124a7859475395777a28b5338647c"
 dependencies = [
  "either",
  "futures 0.3.12",
@@ -1660,12 +1683,13 @@ dependencies = [
 
 [[package]]
 name = "frame-benchmarking"
-version = "3.0.0"
+version = "3.1.0"
 dependencies = [
  "frame-support",
  "frame-system",
  "hex-literal",
  "linregress",
+ "log",
  "parity-scale-codec",
  "paste 1.0.4",
  "serde",
@@ -1746,7 +1770,6 @@ dependencies = [
  "pretty_assertions",
  "serde",
  "smallvec 1.6.1",
- "sp-api",
  "sp-arithmetic",
  "sp-core",
  "sp-inherents",
@@ -1756,7 +1779,6 @@ dependencies = [
  "sp-state-machine",
  "sp-std",
  "sp-tracing",
- "substrate-test-runtime-client",
 ]
 
 [[package]]
@@ -1817,6 +1839,7 @@ dependencies = [
  "criterion",
  "frame-support",
  "impl-trait-for-tuples",
+ "log",
  "parity-scale-codec",
  "serde",
  "sp-core",
@@ -1851,6 +1874,17 @@ dependencies = [
  "sp-api",
 ]
 
+[[package]]
+name = "frame-try-runtime"
+version = "0.9.0"
+dependencies = [
+ "frame-support",
+ "parity-scale-codec",
+ "sp-api",
+ "sp-runtime",
+ "sp-std",
+]
+
 [[package]]
 name = "fs-swap"
 version = "0.2.5"
@@ -2935,16 +2969,15 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
 
 [[package]]
 name = "libp2p"
-version = "0.34.0"
+version = "0.35.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5133112ce42be9482f6a87be92a605dd6bbc9e93c297aee77d172ff06908f3a"
+checksum = "adc225a49973cf9ab10d0cdd6a4b8f0cda299df9b760824bbb623f15f8f0c95a"
 dependencies = [
  "atomic",
  "bytes 1.0.1",
  "futures 0.3.12",
  "lazy_static",
  "libp2p-core",
- "libp2p-core-derive",
  "libp2p-deflate",
  "libp2p-dns",
  "libp2p-floodsub",
@@ -2959,6 +2992,7 @@ dependencies = [
  "libp2p-pnet",
  "libp2p-request-response",
  "libp2p-swarm",
+ "libp2p-swarm-derive",
  "libp2p-tcp",
  "libp2p-uds",
  "libp2p-wasm-ext",
@@ -2973,9 +3007,9 @@ dependencies = [
 
 [[package]]
 name = "libp2p-core"
-version = "0.27.0"
+version = "0.27.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dad04d3cef6c1df366a6ab58c9cf8b06497699e335d83ac2174783946ff847d6"
+checksum = "8a2d56aadc2c2bf22cd7797f86e56a65b5b3994a0136b65be3106938acae7a26"
 dependencies = [
  "asn1_der",
  "bs58",
@@ -3000,21 +3034,11 @@ dependencies = [
  "sha2 0.9.3",
  "smallvec 1.6.1",
  "thiserror",
- "unsigned-varint 0.6.0",
+ "unsigned-varint 0.7.0",
  "void",
  "zeroize",
 ]
 
-[[package]]
-name = "libp2p-core-derive"
-version = "0.21.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4bc40943156e42138d22ed3c57ff0e1a147237742715937622a99b10fbe0156"
-dependencies = [
- "quote",
- "syn",
-]
-
 [[package]]
 name = "libp2p-deflate"
 version = "0.27.1"
@@ -3057,11 +3081,11 @@ dependencies = [
 
 [[package]]
 name = "libp2p-gossipsub"
-version = "0.27.0"
+version = "0.28.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12451ba9493e87c91baf2a6dffce9ddf1fbc807a0861532d7cf477954f8ebbee"
+checksum = "502dc5fcbfec4aa1c63ef3f7307ffe20e90c1a1387bf23ed0bec087f2dde58a1"
 dependencies = [
- "asynchronous-codec",
+ "asynchronous-codec 0.6.0",
  "base64 0.13.0",
  "byteorder",
  "bytes 1.0.1",
@@ -3077,7 +3101,7 @@ dependencies = [
  "regex",
  "sha2 0.9.3",
  "smallvec 1.6.1",
- "unsigned-varint 0.6.0",
+ "unsigned-varint 0.7.0",
  "wasm-timer",
 ]
 
@@ -3099,12 +3123,12 @@ dependencies = [
 
 [[package]]
 name = "libp2p-kad"
-version = "0.28.0"
+version = "0.28.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "456f5de8e283d7800ca848b9b9a4e2a578b790bd8ae582b885e831353cf0e5df"
+checksum = "cf3da6c9acbcc05f93235d201d7d45ef4e8b88a45d8836f98becd8b4d443f066"
 dependencies = [
  "arrayvec 0.5.2",
- "asynchronous-codec",
+ "asynchronous-codec 0.6.0",
  "bytes 1.0.1",
  "either",
  "fnv",
@@ -3118,16 +3142,16 @@ dependencies = [
  "sha2 0.9.3",
  "smallvec 1.6.1",
  "uint",
- "unsigned-varint 0.6.0",
+ "unsigned-varint 0.7.0",
  "void",
  "wasm-timer",
 ]
 
 [[package]]
 name = "libp2p-mdns"
-version = "0.28.0"
+version = "0.28.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b974db63233fc0e199f4ede7794294aae285c96f4b6010f853eac4099ef08590"
+checksum = "0e9e6374814d1b118d97ccabdfc975c8910bd16dc38a8bc058eeb08bf2080fe1"
 dependencies = [
  "async-io",
  "data-encoding",
@@ -3146,11 +3170,11 @@ dependencies = [
 
 [[package]]
 name = "libp2p-mplex"
-version = "0.27.0"
+version = "0.27.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2705dc94b01ab9e3779b42a09bbf3712e637ed213e875c30face247291a85af0"
+checksum = "350ce8b3923594aedabd5d6e3f875d058435052a29c3f32df378bc70d10be464"
 dependencies = [
- "asynchronous-codec",
+ "asynchronous-codec 0.6.0",
  "bytes 1.0.1",
  "futures 0.3.12",
  "libp2p-core",
@@ -3159,7 +3183,7 @@ dependencies = [
  "parking_lot 0.11.1",
  "rand 0.7.3",
  "smallvec 1.6.1",
- "unsigned-varint 0.6.0",
+ "unsigned-varint 0.7.0",
 ]
 
 [[package]]
@@ -3201,18 +3225,18 @@ dependencies = [
 
 [[package]]
 name = "libp2p-plaintext"
-version = "0.27.0"
+version = "0.27.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48e8c1ec305c9949351925cdc7196b9570f4330477f5e47fbf5bb340b57e26ed"
+checksum = "9d58defcadb646ae4b033e130b48d87410bf76394dc3335496cae99dac803e61"
 dependencies = [
- "asynchronous-codec",
+ "asynchronous-codec 0.6.0",
  "bytes 1.0.1",
  "futures 0.3.12",
  "libp2p-core",
  "log",
  "prost",
  "prost-build",
- "unsigned-varint 0.6.0",
+ "unsigned-varint 0.7.0",
  "void",
 ]
 
@@ -3232,9 +3256,9 @@ dependencies = [
 
 [[package]]
 name = "libp2p-request-response"
-version = "0.9.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d37637a4b33b5390322ccc068a33897d0aa541daf4fec99f6a7efbf37295346e"
+checksum = "10e5552827c33d8326502682da73a0ba4bfa40c1b55b216af3c303f32169dd89"
 dependencies = [
  "async-trait",
  "bytes 1.0.1",
@@ -3246,15 +3270,15 @@ dependencies = [
  "minicbor",
  "rand 0.7.3",
  "smallvec 1.6.1",
- "unsigned-varint 0.6.0",
+ "unsigned-varint 0.7.0",
  "wasm-timer",
 ]
 
 [[package]]
 name = "libp2p-swarm"
-version = "0.27.1"
+version = "0.27.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4f89ebb4d8953bda12623e9871959fe728dea3bf6eae0421dc9c42dc821e488"
+checksum = "7955b973e1fd2bd61ffd43ce261c1223f61f4aacd5bae362a924993f9a25fd98"
 dependencies = [
  "either",
  "futures 0.3.12",
@@ -3266,11 +3290,21 @@ dependencies = [
  "wasm-timer",
 ]
 
+[[package]]
+name = "libp2p-swarm-derive"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c564ebaa36a64839f51eaddb0243aaaa29ce64affb56129193cc3248b72af273"
+dependencies = [
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "libp2p-tcp"
-version = "0.27.0"
+version = "0.27.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dbd3d7076a478ac5a6aca55e74bdc250ac539b95de09b9d09915e0b8d01a6b2"
+checksum = "88a5aef80e519a6cb8e2663605142f97baaaea1a252eecbf8756184765f7471b"
 dependencies = [
  "async-io",
  "futures 0.3.12",
@@ -3329,9 +3363,9 @@ dependencies = [
 
 [[package]]
 name = "libp2p-yamux"
-version = "0.30.0"
+version = "0.30.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "490b8b27fc40fe35212df1b6a3d14bffaa4117cbff956fdc2892168a371102ad"
+checksum = "4819358c542a86ff95f6ae691efb4b94ddaf477079b01a686f5705b79bfc232a"
 dependencies = [
  "futures 0.3.12",
  "libp2p-core",
@@ -3452,9 +3486,9 @@ dependencies = [
 
 [[package]]
 name = "lru"
-version = "0.6.3"
+version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3aae342b73d57ad0b8b364bd12584819f2c1fe9114285dfcf8b0722607671635"
+checksum = "1f374d42cdfc1d7dbf3d3dec28afab2eb97ffbf43a3234d795b5986dbf4b90ba"
 dependencies = [
  "hashbrown",
 ]
@@ -3870,6 +3904,7 @@ name = "node-cli"
 version = "2.0.0"
 dependencies = [
  "assert_cmd",
+ "async-std",
  "frame-benchmarking-cli",
  "frame-support",
  "frame-system",
@@ -3919,6 +3954,7 @@ dependencies = [
  "sc-transaction-pool",
  "serde",
  "serde_json",
+ "soketto",
  "sp-authority-discovery",
  "sp-consensus",
  "sp-consensus-babe",
@@ -3938,6 +3974,7 @@ dependencies = [
  "substrate-build-script-utils",
  "substrate-frame-cli",
  "tempfile",
+ "try-runtime-cli",
  "wasm-bindgen",
  "wasm-bindgen-futures",
 ]
@@ -3965,6 +4002,7 @@ dependencies = [
  "parity-scale-codec",
  "sc-executor",
  "sp-application-crypto",
+ "sp-consensus-babe",
  "sp-core",
  "sp-externalities",
  "sp-io",
@@ -4061,7 +4099,9 @@ dependencies = [
  "frame-system",
  "frame-system-benchmarking",
  "frame-system-rpc-runtime-api",
+ "frame-try-runtime",
  "hex-literal",
+ "log",
  "node-primitives",
  "pallet-assets",
  "pallet-authority-discovery",
@@ -4074,7 +4114,9 @@ dependencies = [
  "pallet-contracts-primitives",
  "pallet-contracts-rpc-runtime-api",
  "pallet-democracy",
+ "pallet-election-provider-multi-phase",
  "pallet-elections-phragmen",
+ "pallet-gilt",
  "pallet-grandpa",
  "pallet-identity",
  "pallet-im-online",
@@ -4488,6 +4530,7 @@ dependencies = [
  "frame-benchmarking",
  "frame-support",
  "frame-system",
+ "log",
  "pallet-authorship",
  "pallet-balances",
  "pallet-offences",
@@ -4501,7 +4544,7 @@ dependencies = [
  "sp-consensus-babe",
  "sp-consensus-vrf",
  "sp-core",
- "sp-inherents",
+ "sp-election-providers",
  "sp-io",
  "sp-runtime",
  "sp-session",
@@ -4517,6 +4560,7 @@ dependencies = [
  "frame-benchmarking",
  "frame-support",
  "frame-system",
+ "log",
  "pallet-transaction-payment",
  "parity-scale-codec",
  "serde",
@@ -4552,6 +4596,7 @@ dependencies = [
  "frame-support",
  "frame-system",
  "hex-literal",
+ "log",
  "pallet-balances",
  "parity-scale-codec",
  "serde",
@@ -4563,13 +4608,14 @@ dependencies = [
 
 [[package]]
 name = "pallet-contracts"
-version = "2.0.1"
+version = "3.0.0"
 dependencies = [
  "assert_matches",
  "frame-benchmarking",
  "frame-support",
  "frame-system",
  "hex-literal",
+ "log",
  "pallet-balances",
  "pallet-contracts-primitives",
  "pallet-contracts-proc-macro",
@@ -4594,7 +4640,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-contracts-primitives"
-version = "2.0.1"
+version = "3.0.0"
 dependencies = [
  "bitflags",
  "parity-scale-codec",
@@ -4604,7 +4650,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-contracts-proc-macro"
-version = "0.1.0"
+version = "3.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4613,7 +4659,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-contracts-rpc"
-version = "0.8.1"
+version = "3.0.0"
 dependencies = [
  "jsonrpc-core",
  "jsonrpc-core-client",
@@ -4632,7 +4678,7 @@ dependencies = [
 
 [[package]]
 name = "pallet-contracts-rpc-runtime-api"
-version = "0.8.1"
+version = "3.0.0"
 dependencies = [
  "pallet-contracts-primitives",
  "parity-scale-codec",
@@ -4661,6 +4707,33 @@ dependencies = [
  "substrate-test-utils",
 ]
 
+[[package]]
+name = "pallet-election-provider-multi-phase"
+version = "3.0.0"
+dependencies = [
+ "frame-benchmarking",
+ "frame-support",
+ "frame-system",
+ "hex-literal",
+ "log",
+ "pallet-balances",
+ "parity-scale-codec",
+ "parking_lot 0.11.1",
+ "paste 1.0.4",
+ "rand 0.7.3",
+ "serde",
+ "sp-arithmetic",
+ "sp-core",
+ "sp-election-providers",
+ "sp-io",
+ "sp-npos-elections",
+ "sp-runtime",
+ "sp-std",
+ "sp-tracing",
+ "static_assertions",
+ "substrate-test-utils",
+]
+
 [[package]]
 name = "pallet-elections"
 version = "3.0.0"
@@ -4685,6 +4758,7 @@ dependencies = [
  "frame-support",
  "frame-system",
  "hex-literal",
+ "log",
  "pallet-balances",
  "parity-scale-codec",
  "serde",
@@ -4719,6 +4793,7 @@ dependencies = [
  "frame-support",
  "frame-system",
  "lite-json",
+ "log",
  "parity-scale-codec",
  "serde",
  "sp-core",
@@ -4743,6 +4818,23 @@ dependencies = [
  "sp-tasks",
 ]
 
+[[package]]
+name = "pallet-gilt"
+version = "3.0.0"
+dependencies = [
+ "frame-benchmarking",
+ "frame-support",
+ "frame-system",
+ "pallet-balances",
+ "parity-scale-codec",
+ "serde",
+ "sp-arithmetic",
+ "sp-core",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+]
+
 [[package]]
 name = "pallet-grandpa"
 version = "3.0.0"
@@ -4751,6 +4843,7 @@ dependencies = [
  "frame-benchmarking",
  "frame-support",
  "frame-system",
+ "log",
  "pallet-authorship",
  "pallet-balances",
  "pallet-offences",
@@ -4762,6 +4855,7 @@ dependencies = [
  "serde",
  "sp-application-crypto",
  "sp-core",
+ "sp-election-providers",
  "sp-finality-grandpa",
  "sp-io",
  "sp-keyring",
@@ -4795,6 +4889,7 @@ dependencies = [
  "frame-benchmarking",
  "frame-support",
  "frame-system",
+ "log",
  "pallet-authorship",
  "pallet-session",
  "parity-scale-codec",
@@ -4859,7 +4954,7 @@ name = "pallet-mmr"
 version = "3.0.0"
 dependencies = [
  "ckb-merkle-mountain-range",
- "env_logger 0.8.3",
+ "env_logger 0.8.2",
  "frame-benchmarking",
  "frame-support",
  "frame-system",
@@ -4880,6 +4975,7 @@ dependencies = [
  "frame-support",
  "frame-system",
  "hex-literal",
+ "log",
  "parity-scale-codec",
  "serde",
  "sp-api",
@@ -4925,6 +5021,7 @@ version = "2.0.0"
 dependencies = [
  "frame-support",
  "frame-system",
+ "log",
  "parity-scale-codec",
  "serde",
  "sp-core",
@@ -4939,6 +5036,7 @@ version = "3.0.0"
 dependencies = [
  "frame-support",
  "frame-system",
+ "log",
  "pallet-balances",
  "parity-scale-codec",
  "serde",
@@ -4968,6 +5066,7 @@ dependencies = [
  "parity-scale-codec",
  "serde",
  "sp-core",
+ "sp-election-providers",
  "sp-io",
  "sp-runtime",
  "sp-staking",
@@ -5029,6 +5128,7 @@ dependencies = [
  "frame-benchmarking",
  "frame-support",
  "frame-system",
+ "log",
  "parity-scale-codec",
  "serde",
  "sp-core",
@@ -5090,6 +5190,7 @@ dependencies = [
  "rand 0.7.3",
  "serde",
  "sp-core",
+ "sp-election-providers",
  "sp-io",
  "sp-runtime",
  "sp-session",
@@ -5120,6 +5221,7 @@ dependencies = [
  "frame-support",
  "frame-system",
  "hex",
+ "log",
  "pallet-authorship",
  "pallet-balances",
  "pallet-session",
@@ -5131,6 +5233,7 @@ dependencies = [
  "serde",
  "sp-application-crypto",
  "sp-core",
+ "sp-election-providers",
  "sp-io",
  "sp-npos-elections",
  "sp-runtime",
@@ -5158,6 +5261,7 @@ dependencies = [
  "parity-scale-codec",
  "serde",
  "sp-core",
+ "sp-election-providers",
  "sp-io",
  "sp-npos-elections",
  "sp-runtime",
@@ -5210,6 +5314,7 @@ dependencies = [
  "frame-support",
  "frame-system",
  "impl-trait-for-tuples",
+ "log",
  "parity-scale-codec",
  "serde",
  "sp-core",
@@ -5276,6 +5381,7 @@ dependencies = [
 name = "pallet-transaction-payment-rpc-runtime-api"
 version = "3.0.0"
 dependencies = [
+ "frame-support",
  "pallet-transaction-payment",
  "parity-scale-codec",
  "sp-api",
@@ -5353,9 +5459,9 @@ dependencies = [
 
 [[package]]
 name = "parity-multiaddr"
-version = "0.11.0"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bfda2e46fc5e14122649e2645645a81ee5844e0fb2e727ef560cc71a8b2d801"
+checksum = "d2c6805f98667a3828afb2ec2c396a8d610497e8d546f5447188aae47c5a79ec"
 dependencies = [
  "arrayref",
  "bs58",
@@ -5365,7 +5471,7 @@ dependencies = [
  "percent-encoding 2.1.0",
  "serde",
  "static_assertions",
- "unsigned-varint 0.6.0",
+ "unsigned-varint 0.7.0",
  "url 2.2.0",
 ]
 
@@ -5871,7 +5977,7 @@ dependencies = [
 
 [[package]]
 name = "prml-attestation"
-version = "2.0.0"
+version = "3.0.0"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
@@ -5886,7 +5992,7 @@ dependencies = [
 
 [[package]]
 name = "prml-generic-asset"
-version = "2.0.0"
+version = "3.0.0"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
@@ -5902,7 +6008,7 @@ dependencies = [
 
 [[package]]
 name = "prml-generic-asset-rpc"
-version = "2.0.0"
+version = "3.0.0"
 dependencies = [
  "jsonrpc-core",
  "jsonrpc-core-client",
@@ -5920,7 +6026,7 @@ dependencies = [
 
 [[package]]
 name = "prml-generic-asset-rpc-runtime-api"
-version = "2.0.0"
+version = "3.0.0"
 dependencies = [
  "parity-scale-codec",
  "prml-generic-asset",
@@ -6108,7 +6214,7 @@ version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
 dependencies = [
- "env_logger 0.8.3",
+ "env_logger 0.8.2",
  "log",
  "rand 0.8.3",
 ]
@@ -6126,9 +6232,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.9"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
+checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
 dependencies = [
  "proc-macro2",
 ]
@@ -6435,6 +6541,24 @@ dependencies = [
  "winapi 0.3.9",
 ]
 
+[[package]]
+name = "remote-externalities"
+version = "0.9.0"
+dependencies = [
+ "async-std",
+ "env_logger 0.8.2",
+ "futures 0.3.12",
+ "hex-literal",
+ "jsonrpc-core-client",
+ "log",
+ "parity-scale-codec",
+ "sc-rpc",
+ "sc-rpc-api",
+ "sp-core",
+ "sp-io",
+ "tokio 0.1.22",
+]
+
 [[package]]
 name = "remove_dir_all"
 version = "0.5.3"
@@ -6677,7 +6801,6 @@ dependencies = [
  "sp-api",
  "sp-block-builder",
  "sp-blockchain",
- "sp-consensus",
  "sp-core",
  "sp-inherents",
  "sp-runtime",
@@ -7165,6 +7288,7 @@ version = "0.9.0"
 dependencies = [
  "assert_matches",
  "derive_more",
+ "dyn-clone",
  "finality-grandpa",
  "fork-tree",
  "futures 0.3.12",
@@ -7239,21 +7363,28 @@ dependencies = [
 
 [[package]]
 name = "sc-finality-grandpa-warp-sync"
-version = "0.8.0"
+version = "0.9.0"
 dependencies = [
  "derive_more",
+ "finality-grandpa",
  "futures 0.3.12",
  "log",
  "num-traits",
  "parity-scale-codec",
  "parking_lot 0.11.1",
  "prost",
+ "rand 0.8.3",
+ "sc-block-builder",
  "sc-client-api",
  "sc-finality-grandpa",
  "sc-network",
  "sc-service",
  "sp-blockchain",
+ "sp-consensus",
+ "sp-finality-grandpa",
+ "sp-keyring",
  "sp-runtime",
+ "substrate-test-runtime-client",
 ]
 
 [[package]]
@@ -7318,7 +7449,7 @@ dependencies = [
  "assert_matches",
  "async-std",
  "async-trait",
- "asynchronous-codec",
+ "asynchronous-codec 0.5.0",
  "bitflags",
  "bs58",
  "bytes 1.0.1",
@@ -7635,6 +7766,7 @@ dependencies = [
  "tokio 0.2.25",
  "tracing",
  "tracing-futures",
+ "tracing-log",
  "tracing-subscriber",
  "wasm-timer",
 ]
@@ -8218,6 +8350,7 @@ name = "sp-api"
 version = "3.0.0"
 dependencies = [
  "hash-db",
+ "log",
  "parity-scale-codec",
  "sp-api-proc-macro",
  "sp-core",
@@ -8245,6 +8378,7 @@ name = "sp-api-test"
 version = "2.0.1"
 dependencies = [
  "criterion",
+ "log",
  "parity-scale-codec",
  "rustversion",
  "sc-block-builder",
@@ -8254,6 +8388,7 @@ dependencies = [
  "sp-core",
  "sp-runtime",
  "sp-state-machine",
+ "sp-tracing",
  "sp-version",
  "substrate-test-runtime-client",
  "trybuild",
@@ -8698,12 +8833,15 @@ dependencies = [
  "rand 0.7.3",
  "serde",
  "serde_json",
+ "sp-api",
  "sp-application-crypto",
  "sp-arithmetic",
  "sp-core",
  "sp-io",
  "sp-state-machine",
  "sp-std",
+ "sp-tracing",
+ "substrate-test-runtime-client",
 ]
 
 [[package]]
@@ -9446,9 +9584,9 @@ dependencies = [
 
 [[package]]
 name = "thread_local"
-version = "1.1.2"
+version = "1.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8208a331e1cb318dd5bd76951d2b8fc48ca38a69f5f4e4af1b6a9f8c6236915"
+checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
 dependencies = [
  "once_cell",
 ]
@@ -9961,6 +10099,27 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
 
+[[package]]
+name = "try-runtime-cli"
+version = "0.9.0"
+dependencies = [
+ "frame-try-runtime",
+ "log",
+ "parity-scale-codec",
+ "remote-externalities",
+ "sc-cli",
+ "sc-client-api",
+ "sc-executor",
+ "sc-service",
+ "sp-api",
+ "sp-blockchain",
+ "sp-core",
+ "sp-externalities",
+ "sp-runtime",
+ "sp-state-machine",
+ "structopt",
+]
+
 [[package]]
 name = "trybuild"
 version = "1.0.39"
@@ -10078,7 +10237,19 @@ version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "35581ff83d4101e58b582e607120c7f5ffb17e632a980b1f38334d76b36908b2"
 dependencies = [
- "asynchronous-codec",
+ "asynchronous-codec 0.5.0",
+ "bytes 1.0.1",
+ "futures-io",
+ "futures-util",
+]
+
+[[package]]
+name = "unsigned-varint"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f8d425fafb8cd76bc3f22aace4af471d3156301d7508f2107e98fbeae10bc7f"
+dependencies = [
+ "asynchronous-codec 0.6.0",
  "bytes 1.0.1",
  "futures-io",
  "futures-util",
@@ -10213,9 +10384,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.69"
+version = "0.2.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e"
+checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
 dependencies = [
  "cfg-if 1.0.0",
  "serde",
@@ -10225,9 +10396,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.69"
+version = "0.2.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62"
+checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7"
 dependencies = [
  "bumpalo",
  "lazy_static",
@@ -10252,9 +10423,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.69"
+version = "0.2.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084"
+checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -10262,9 +10433,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.69"
+version = "0.2.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549"
+checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -10275,9 +10446,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.69"
+version = "0.2.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158"
+checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64"
 
 [[package]]
 name = "wasm-bindgen-test"
@@ -10693,9 +10864,9 @@ dependencies = [
 
 [[package]]
 name = "yamux"
-version = "0.8.0"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aeb8c4043cac71c3c299dff107171c220d179492350ea198e109a414981b83c"
+checksum = "1cc7bd8c983209ed5d527f44b01c41b7dc146fd960c61cf9e1d25399841dc271"
 dependencies = [
  "futures 0.3.12",
  "log",
diff --git a/Cargo.toml b/Cargo.toml
index 21244dae4b..f08a59a4a7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -73,11 +73,14 @@ members = [
 	"frame/contracts/rpc",
 	"frame/contracts/rpc/runtime-api",
 	"frame/democracy",
+	"frame/try-runtime",
 	"frame/elections",
+	"frame/election-provider-multi-phase",
 	"frame/example",
 	"frame/example-offchain-worker",
 	"frame/example-parallel",
 	"frame/executive",
+	"frame/gilt",
 	"frame/grandpa",
 	"frame/identity",
 	"frame/im-online",
@@ -175,17 +178,6 @@ members = [
 	"primitives/utils",
 	"primitives/version",
 	"primitives/wasm-interface",
-	# plug modules
-	"prml/attestation",
-	"prml/support",
-	# "prml/consortium-permission",
-	# doughnut disabled
-	# "prml/doughnut",
-	"prml/generic-asset",
-	"prml/generic-asset/rpc",
-	"prml/generic-asset/rpc/runtime-api",
-	# "prml/validator-manager",
-	# end plug modules
 	"test-utils/client",
 	"test-utils/derive",
 	"test-utils/runtime",
@@ -196,11 +188,23 @@ members = [
 	"utils/build-script-utils",
 	"utils/fork-tree",
 	"utils/frame/benchmarking-cli",
+	"utils/frame/remote-externalities",
 	"utils/frame/frame-utilities-cli",
+	"utils/frame/try-runtime/cli",
 	"utils/frame/rpc/support",
 	"utils/frame/rpc/system",
 	"utils/prometheus",
 	"utils/wasm-builder",
+	"prml/support",
+	"prml/attestation",
+	"prml/generic-asset",
+	"prml/generic-asset/rpc",
+	"prml/generic-asset/rpc/runtime-api",
+]
+exclude = [
+	"prml/consortium-permission",
+	"prml/doughnut",
+	"prml/validator-manager",
 ]
 
 # The list of dependencies below (which can be both direct and indirect dependencies) are crates
diff --git a/Process.json b/Process.json
deleted file mode 100644
index 540bd64431..0000000000
--- a/Process.json
+++ /dev/null
@@ -1,29 +0,0 @@
-[{
-	"project_name": "Networking",
-	"owner": "tomaka",
-	"matrix_room_id": "!vUADSGcyXmxhKLeDsW:matrix.parity.io"
-},
-{	"project_name": "Client",
-	"owner": "gnunicorn",
-	"matrix_room_id": "!aenJixaHcSKbJOWxYk:matrix.parity.io"
-},
-{
-	"project_name": "Runtime",
-	"owner": "gavofyork",
-	"matrix_room_id": "!yBKstWVBkwzUkPslsp:matrix.parity.io"
-},
-{
-	"project_name": "Consensus",
-	"owner": "andresilva",
-	"matrix_room_id": "!XdNWDTfVNFVixljKZU:matrix.parity.io"
-},
-{
-	"project_name": "Smart Contracts",
-	"owner": "pepyakin",
-	"matrix_room_id": "!yBKstWVBkwzUkPslsp:matrix.parity.io"
-},
-{
-	"project_name": "Benchmarking and Weights",
-	"owner": "shawntabrizi",
-	"matrix_room_id": "!pZPWqCRLVtORZTEsEf:matrix.parity.io"
-}]
diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml
index 464b07cb98..2d36d3c469 100644
--- a/bin/node-template/node/Cargo.toml
+++ b/bin/node-template/node/Cargo.toml
@@ -48,7 +48,7 @@ substrate-frame-rpc-system = { version = "3.0.0", path = "../../../utils/frame/r
 pallet-transaction-payment-rpc = { version = "3.0.0", path = "../../../frame/transaction-payment/rpc/" }
 
 # These dependencies are used for runtime benchmarking
-frame-benchmarking = { version = "3.0.0", path = "../../../frame/benchmarking" }
+frame-benchmarking = { version = "3.1.0", path = "../../../frame/benchmarking" }
 frame-benchmarking-cli = { version = "3.0.0", path = "../../../utils/frame/benchmarking-cli" }
 
 node-template-runtime = { version = "2.0.0", path = "../runtime" }
diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs
index 4061dce438..92518ef22d 100644
--- a/bin/node-template/node/src/service.rs
+++ b/bin/node-template/node/src/service.rs
@@ -11,6 +11,7 @@ pub use sc_executor::NativeExecutor;
 use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair};
 use sc_finality_grandpa::SharedVoterState;
 use sc_keystore::LocalKeystore;
+use sc_telemetry::TelemetrySpan;
 
 // Our native executor instance.
 native_executor_instance!(
@@ -72,7 +73,7 @@ pub fn new_partial(config: &Configuration) -> Result Result
 		})
 	};
 
+	let telemetry_span = TelemetrySpan::new();
+	let _telemetry_span_entered = telemetry_span.enter();
+
 	let (_rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks(
 		sc_service::SpawnTasksParams {
 			network: network.clone(),
@@ -176,6 +180,7 @@ pub fn new_full(mut config: Configuration) -> Result
 			network_status_sinks,
 			system_rpc_tx,
 			config,
+			telemetry_span: Some(telemetry_span.clone()),
 		},
 	)?;
 
@@ -224,7 +229,7 @@ pub fn new_full(mut config: Configuration) -> Result
 		name: Some(name),
 		observer_enabled: false,
 		keystore,
-		is_authority: role.is_network_authority(),
+		is_authority: role.is_authority(),
 	};
 
 	if enable_grandpa {
@@ -290,7 +295,7 @@ pub fn new_light(mut config: Configuration) -> Result
 		Some(Box::new(grandpa_block_import)),
 		client.clone(),
 		InherentDataProviders::new(),
-		&task_manager.spawn_handle(),
+		&task_manager.spawn_essential_handle(),
 		config.prometheus_registry(),
 		sp_consensus::NeverCanAuthor,
 	)?;
@@ -312,6 +317,9 @@ pub fn new_light(mut config: Configuration) -> Result
 		);
 	}
 
+	let telemetry_span = TelemetrySpan::new();
+	let _telemetry_span_entered = telemetry_span.enter();
+
 	sc_service::spawn_tasks(sc_service::SpawnTasksParams {
 		remote_blockchain: Some(backend.remote_blockchain()),
 		transaction_pool,
@@ -325,6 +333,7 @@ pub fn new_light(mut config: Configuration) -> Result
 		network,
 		network_status_sinks,
 		system_rpc_tx,
+		telemetry_span: Some(telemetry_span.clone()),
 	})?;
 
 	network_starter.start_network();
diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml
index a13d05082b..e6c0c5ac06 100644
--- a/bin/node-template/pallets/template/Cargo.toml
+++ b/bin/node-template/pallets/template/Cargo.toml
@@ -51,3 +51,4 @@ std = [
 	'frame-support/std',
 	'frame-system/std'
 ]
+try-runtime = ["frame-support/try-runtime"]
diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml
index dd907f55fb..de69419b92 100644
--- a/bin/node-template/runtime/Cargo.toml
+++ b/bin/node-template/runtime/Cargo.toml
@@ -41,7 +41,7 @@ frame-system-rpc-runtime-api = { version = "3.0.0", default-features = false, pa
 pallet-transaction-payment-rpc-runtime-api = { version = "3.0.0", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" }
 
 # Used for runtime benchmarking
-frame-benchmarking = { version = "3.0.0", default-features = false, path = "../../../frame/benchmarking", optional = true }
+frame-benchmarking = { version = "3.1.0", default-features = false, path = "../../../frame/benchmarking", optional = true }
 frame-system-benchmarking = { version = "3.0.0", default-features = false, path = "../../../frame/system/benchmarking", optional = true }
 hex-literal = { version = "0.3.1", optional = true }
 
diff --git a/bin/node/bench/src/construct.rs b/bin/node/bench/src/construct.rs
index a8a02f19c3..b64ffec641 100644
--- a/bin/node/bench/src/construct.rs
+++ b/bin/node/bench/src/construct.rs
@@ -48,7 +48,7 @@ use sp_transaction_pool::{
 	TransactionStatusStreamFor,
 	TxHash,
 };
-use sp_consensus::{Environment, Proposer, RecordProof};
+use sp_consensus::{Environment, Proposer};
 
 use crate::{
 	common::SizeType,
@@ -170,7 +170,6 @@ impl core::Benchmark for ConstructionBenchmark {
 				inherent_data_providers.create_inherent_data().expect("Create inherent data failed"),
 				Default::default(),
 				std::time::Duration::from_secs(20),
-				RecordProof::Yes,
 			),
 		).map(|r| r.block).expect("Proposing failed");
 
diff --git a/bin/node/browser-testing/Cargo.toml b/bin/node/browser-testing/Cargo.toml
index 66e7b398dd..fe83cc65ba 100644
--- a/bin/node/browser-testing/Cargo.toml
+++ b/bin/node/browser-testing/Cargo.toml
@@ -8,14 +8,14 @@ license = "Apache-2.0"
 
 [dependencies]
 futures-timer = "3.0.2"
-libp2p = { version = "0.34.0", default-features = false }
+libp2p = { version = "0.35.1", default-features = false }
 jsonrpc-core = "15.0.0"
 serde = "1.0.106"
 serde_json = "1.0.48"
-wasm-bindgen = { version = "=0.2.69", features = ["serde-serialize"] }
+wasm-bindgen = { version = "=0.2.70", features = ["serde-serialize"] }
 wasm-bindgen-futures = "0.4.18"
 wasm-bindgen-test = "0.3.18"
 futures = "0.3.9"
 
-node-cli = { path = "../cli", default-features = false, features = ["browser"] , version = "2.0.0"}
-sc-rpc-api = { path = "../../../client/rpc-api" , version = "0.9.0"}
+node-cli = { path = "../cli", default-features = false, features = ["browser"], version = "2.0.0"}
+sc-rpc-api = { path = "../../../client/rpc-api", version = "0.9.0"}
diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml
index f85a89bdc9..6c5fd9c3a1 100644
--- a/bin/node/cli/Cargo.toml
+++ b/bin/node/cli/Cargo.toml
@@ -75,12 +75,12 @@ sc-service = { version = "0.9.0", default-features = false, path = "../../../cli
 sc-tracing = { version = "3.0.0", path = "../../../client/tracing" }
 sc-telemetry = { version = "3.0.0", path = "../../../client/telemetry" }
 sc-authority-discovery = { version = "0.9.0",  path = "../../../client/authority-discovery" }
-sc-finality-grandpa-warp-sync = { version = "0.8.0", path = "../../../client/finality-grandpa-warp-sync", optional = true }
+sc-finality-grandpa-warp-sync = { version = "0.9.0", path = "../../../client/finality-grandpa-warp-sync", optional = true }
 
 # frame dependencies
 pallet-indices = { version = "3.0.0", path = "../../../frame/indices" }
 pallet-timestamp = { version = "3.0.0", default-features = false, path = "../../../frame/timestamp" }
-pallet-contracts = { version = "2.0.0", path = "../../../frame/contracts" }
+pallet-contracts = { version = "3.0.0", path = "../../../frame/contracts" }
 frame-system = { version = "3.0.0", path = "../../../frame/system" }
 pallet-balances = { version = "3.0.0", path = "../../../frame/balances" }
 pallet-transaction-payment = { version = "3.0.0", path = "../../../frame/transaction-payment" }
@@ -100,6 +100,7 @@ node-executor = { version = "2.0.0", path = "../executor" }
 sc-cli = { version = "0.9.0", optional = true, path = "../../../client/cli" }
 frame-benchmarking-cli = { version = "3.0.0", optional = true, path = "../../../utils/frame/benchmarking-cli" }
 node-inspect = { version = "0.8.0", optional = true, path = "../inspect" }
+try-runtime-cli = { version = "0.9.0", optional = true, path = "../../../utils/frame/try-runtime/cli" }
 
 # WASM-specific dependencies
 wasm-bindgen = { version = "0.2.57", optional = true }
@@ -125,6 +126,8 @@ nix = "0.19"
 serde_json = "1.0"
 regex = "1"
 platforms = "1.1"
+async-std = { version = "1.6.5", features = ["attributes"] }
+soketto = "0.4.2"
 
 [build-dependencies]
 structopt = { version = "0.3.8", optional = true }
@@ -132,6 +135,7 @@ node-inspect = { version = "0.8.0", optional = true, path = "../inspect" }
 frame-benchmarking-cli = { version = "3.0.0", optional = true, path = "../../../utils/frame/benchmarking-cli" }
 substrate-build-script-utils = { version = "3.0.0", optional = true, path = "../../../utils/build-script-utils" }
 substrate-frame-cli = { version = "3.0.0", optional = true, path = "../../../utils/frame/frame-utilities-cli" }
+try-runtime-cli = { version = "0.9.0", optional = true, path = "../../../utils/frame/try-runtime/cli" }
 
 [build-dependencies.sc-cli]
 version = "0.9.0"
@@ -156,8 +160,15 @@ cli = [
 	"sc-finality-grandpa-warp-sync",
 	"structopt",
 	"substrate-build-script-utils",
+	"try-runtime-cli",
 ]
 runtime-benchmarks = [
 	"node-runtime/runtime-benchmarks",
 	"frame-benchmarking-cli",
 ]
+# Enable features that allow the runtime to be tried and debugged. Name might be subject to change
+# in the near future.
+try-runtime = [
+	"node-runtime/try-runtime",
+	"try-runtime-cli",
+]
diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs
index 7de9cfd0b6..db268ad105 100644
--- a/bin/node/cli/src/chain_spec.rs
+++ b/bin/node/cli/src/chain_spec.rs
@@ -326,6 +326,7 @@ pub fn testnet_genesis(
 			max_members: 999,
 		}),
 		pallet_vesting: Some(Default::default()),
+		pallet_gilt: Some(Default::default()),
 	}
 }
 
diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs
index 63a07e00e2..9b80a3e345 100644
--- a/bin/node/cli/src/cli.rs
+++ b/bin/node/cli/src/cli.rs
@@ -47,6 +47,11 @@ pub enum Subcommand {
 	#[structopt(name = "benchmark", about = "Benchmark runtime pallets.")]
 	Benchmark(frame_benchmarking_cli::BenchmarkCmd),
 
+	/// Try some experimental command on the runtime. This includes migration and runtime-upgrade
+	/// testing.
+	#[cfg(feature = "try-runtime")]
+	TryRuntime(try_runtime_cli::TryRuntimeCmd),
+
 	/// Verify a signature for a message, provided on STDIN, with a given (public or secret) key.
 	Verify(VerifyCmd),
 
diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs
index 461930a613..ece97436bf 100644
--- a/bin/node/cli/src/command.rs
+++ b/bin/node/cli/src/command.rs
@@ -149,5 +149,20 @@ pub fn run() -> Result<()> {
 				Ok((cmd.run(client, backend), task_manager))
 			})
 		},
+		#[cfg(feature = "try-runtime")]
+		Some(Subcommand::TryRuntime(cmd)) => {
+			let runner = cli.create_runner(cmd)?;
+			runner.async_run(|config| {
+				// we don't need any of the components of new_partial, just a runtime, or a task
+				// manager to do `async_run`.
+				let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry);
+				let task_manager = sc_service::TaskManager::new(
+					config.task_executor.clone(),
+					registry,
+				).map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?;
+
+				Ok((cmd.run::(config), task_manager))
+			})
+		}
 	}
 }
diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs
index 815ea243ce..970e8606c7 100644
--- a/bin/node/cli/src/service.rs
+++ b/bin/node/cli/src/service.rs
@@ -34,7 +34,7 @@ use sp_runtime::traits::Block as BlockT;
 use futures::prelude::*;
 use sc_client_api::{ExecutorProvider, RemoteBackend};
 use node_executor::Executor;
-use sc_telemetry::TelemetryConnectionNotifier;
+use sc_telemetry::{TelemetryConnectionNotifier, TelemetrySpan};
 
 type FullClient = sc_service::TFullClient;
 type FullBackend = sc_service::TFullBackend;
@@ -95,7 +95,7 @@ pub fn new_partial(config: &Configuration) -> Result Result<(
 		client.clone(),
 		select_chain.clone(),
 		inherent_data_providers.clone(),
-		&task_manager.spawn_handle(),
+		&task_manager.spawn_essential_handle(),
 		config.prometheus_registry(),
 		sp_consensus::NeverCanAuthor,
 	)?;
@@ -435,6 +444,9 @@ pub fn new_light_base(mut config: Configuration) -> Result<(
 
 	let rpc_extensions = node_rpc::create_light(light_deps);
 
+	let telemetry_span = TelemetrySpan::new();
+	let _telemetry_span_entered = telemetry_span.enter();
+
 	let (rpc_handlers, telemetry_connection_notifier) =
 		sc_service::spawn_tasks(sc_service::SpawnTasksParams {
 			on_demand: Some(on_demand),
@@ -446,6 +458,7 @@ pub fn new_light_base(mut config: Configuration) -> Result<(
 			config, backend, network_status_sinks, system_rpc_tx,
 			network: network.clone(),
 			task_manager: &mut task_manager,
+			telemetry_span: Some(telemetry_span.clone()),
 		})?;
 
 	Ok((
@@ -472,7 +485,6 @@ mod tests {
 	use sc_consensus_epochs::descendent_query;
 	use sp_consensus::{
 		Environment, Proposer, BlockImportParams, BlockOrigin, ForkChoiceStrategy, BlockImport,
-		RecordProof,
 	};
 	use node_primitives::{Block, DigestItem, Signature};
 	use node_runtime::{BalancesCall, Call, UncheckedExtrinsic, Address};
@@ -605,7 +617,6 @@ mod tests {
 						inherent_data,
 						digest,
 						std::time::Duration::from_secs(1),
-						RecordProof::Yes,
 					).await
 				}).expect("Error making test block").block;
 
@@ -619,9 +630,7 @@ mod tests {
 					sp_consensus_babe::AuthorityId::ID,
 					&alice.to_public_crypto_pair(),
 					&to_sign,
-				).unwrap()
-				 .try_into()
-				 .unwrap();
+				).unwrap().unwrap().try_into().unwrap();
 				let item = ::babe_seal(
 					signature,
 				);
diff --git a/bin/node/cli/tests/telemetry.rs b/bin/node/cli/tests/telemetry.rs
new file mode 100644
index 0000000000..0b90f56a03
--- /dev/null
+++ b/bin/node/cli/tests/telemetry.rs
@@ -0,0 +1,102 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use assert_cmd::cargo::cargo_bin;
+use nix::sys::signal::{kill, Signal::SIGINT};
+use nix::unistd::Pid;
+use std::convert::TryInto;
+use std::process;
+
+pub mod common;
+pub mod websocket_server;
+
+#[async_std::test]
+async fn telemetry_works() {
+	let config = websocket_server::Config {
+		capacity: 1,
+		max_frame_size: 1048 * 1024,
+		send_buffer_len: 32,
+		bind_address: "127.0.0.1:0".parse().unwrap(),
+	};
+	let mut server = websocket_server::WsServer::new(config).await.unwrap();
+
+	let addr = server.local_addr().unwrap();
+
+	let server_task = async_std::task::spawn(async move {
+		loop {
+			use websocket_server::Event;
+			match server.next_event().await {
+				// New connection on the listener.
+				Event::ConnectionOpen { address } => {
+					println!("New connection from {:?}", address);
+					server.accept();
+				}
+
+				// Received a message from a connection.
+				Event::BinaryFrame { message, .. } => {
+					let json: serde_json::Value = serde_json::from_slice(&message).unwrap();
+					let object = json
+						.as_object()
+						.unwrap()
+						.get("payload")
+						.unwrap()
+						.as_object()
+						.unwrap();
+					if matches!(object.get("best"), Some(serde_json::Value::String(_))) {
+						break;
+					}
+				}
+
+				Event::TextFrame { .. } => panic!("Got a TextFrame over the socket, this is a bug"),
+
+				// Connection has been closed.
+				Event::ConnectionError { .. } => {}
+			}
+		}
+	});
+
+	let mut substrate = process::Command::new(cargo_bin("substrate"));
+
+	let mut substrate = substrate
+		.args(&["--dev", "--tmp", "--telemetry-url"])
+		.arg(format!("ws://{} 10", addr))
+		.stdout(process::Stdio::piped())
+		.stderr(process::Stdio::piped())
+		.stdin(process::Stdio::null())
+		.spawn()
+		.unwrap();
+
+	server_task.await;
+
+	assert!(
+		substrate.try_wait().unwrap().is_none(),
+		"the process should still be running"
+	);
+
+	// Stop the process
+	kill(Pid::from_raw(substrate.id().try_into().unwrap()), SIGINT).unwrap();
+	assert!(common::wait_for(&mut substrate, 40)
+		.map(|x| x.success())
+		.unwrap_or_default());
+
+	let output = substrate.wait_with_output().unwrap();
+
+	println!("{}", String::from_utf8(output.stdout).unwrap());
+	eprintln!("{}", String::from_utf8(output.stderr).unwrap());
+	assert!(output.status.success());
+}
diff --git a/bin/node/cli/tests/websocket_server.rs b/bin/node/cli/tests/websocket_server.rs
new file mode 100644
index 0000000000..a8af1c3599
--- /dev/null
+++ b/bin/node/cli/tests/websocket_server.rs
@@ -0,0 +1,281 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use async_std::net::{TcpListener, TcpStream};
+use core::pin::Pin;
+use futures::prelude::*;
+use soketto::handshake::{server::Response, Server};
+use std::{io, net::SocketAddr};
+
+/// Configuration for a [`WsServer`].
+pub struct Config {
+	/// IP address to try to bind to.
+	pub bind_address: SocketAddr,
+
+	/// Maximum size, in bytes, of a frame sent by the remote.
+	///
+	/// Since the messages are entirely buffered before being returned, a maximum value is
+	/// necessary in order to prevent malicious clients from sending huge frames that would
+	/// occupy a lot of memory.
+	pub max_frame_size: usize,
+
+	/// Number of pending messages to buffer up for sending before the socket is considered
+	/// unresponsive.
+	pub send_buffer_len: usize,
+
+	/// Pre-allocated capacity for the list of connections.
+	pub capacity: usize,
+}
+
+/// Identifier for a connection with regard to a [`WsServer`].
+///
+/// After a connection has been closed, its [`ConnectionId`] might be reused.
+#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
+pub struct ConnectionId(u64);
+
+/// A WebSocket message.
+pub enum Message {
+	Text(String),
+	Binary(Vec),
+}
+
+/// WebSockets listening socket and list of open connections.
+pub struct WsServer {
+	/// Value passed through [`Config::max_frame_size`].
+	max_frame_size: usize,
+
+	/// Endpoint for incoming TCP sockets.
+	listener: TcpListener,
+
+	/// Pending incoming connection to accept. Accepted by calling [`WsServer::accept`].
+	pending_incoming: Option,
+
+	/// List of TCP connections that are currently negotiating the WebSocket handshake.
+	///
+	/// The output can be an error if the handshake fails.
+	negotiating: stream::FuturesUnordered<
+		Pin<
+			Box<
+				dyn Future