Merge branch 'master' into gav-xcm-v3

This commit is contained in:
Keith Yeung
2022-03-08 22:58:14 -08:00
174 changed files with 11477 additions and 5059 deletions
+1 -1
View File
@@ -146,7 +146,7 @@ Until #631 is done, running the benchmarks is a manual process:
1. Connect to the bechmarking machine
2. Make sure no one else is using the machine with `htop check`
3. Pull in the branch of Cumulus that has the version of Statemine you want to release
4. Recompile `cargo build --release --features runtime-benchmarks`
4. Recompile `cargo build --profile production --locked --features runtime-benchmarks`
5. From the root directory run `nohup ./scripts/benchmarks.sh &` (it will take quite a few hours)
6. Checkout in your local machine to the branch of cumulus that has the version of Statemine you want to release
7. `scp` from the host to your local machine the weights for Statemine, Westmint and Statemint you'll find in:
+25
View File
@@ -0,0 +1,25 @@
version: 2
updates:
- package-ecosystem: "cargo"
directory: "/"
labels: ["A2-insubstantial", "B0-silent", "C1-low 📌"]
# Handle updates for crates from github.com/paritytech/substrate manually.
ignore:
- dependency-name: "substrate-*"
- dependency-name: "sc-*"
- dependency-name: "sp-*"
- dependency-name: "frame-*"
- dependency-name: "fork-tree"
- dependency-name: "remote-externalities"
- dependency-name: "pallet-*"
- dependency-name: "beefy-*"
- dependency-name: "try-runtime-*"
- dependency-name: "test-runner"
- dependency-name: "generate-bags"
- dependency-name: "sub-tokens"
- dependency-name: "polkadot-*"
- dependency-name: "xcm*"
- dependency-name: "kusama-*"
- dependency-name: "westend-*"
schedule:
interval: "daily"
+13 -5
View File
@@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
runtime: ["shell", "statemine", "statemint", "westmint", "rococo-parachain"]
runtime: ["shell", "statemine", "statemint", "westmint", "rococo-parachain", "canvas-kusama"]
steps:
- name: Checkout sources
uses: actions/checkout@v2
@@ -100,7 +100,7 @@ jobs:
- name: Prepare tooling
run: |
cd cumulus/scripts/changelog
gem install bundler changelogerator
gem install bundler changelogerator:0.9.1
bundle install
changelogerator --help
@@ -120,7 +120,8 @@ jobs:
WESTMINT_DIGEST: ${{ github.workspace}}/westmint-srtool-json/westmint_srtool_output.json
STATEMINE_DIGEST: ${{ github.workspace}}/statemine-srtool-json/statemine_srtool_output.json
STATEMINT_DIGEST: ${{ github.workspace}}/statemint-srtool-json/statemint_srtool_output.json
ROCOCO_DIGEST: ${{ github.workspace}}/rococo-parachain-srtool-json/rococo-parachain_srtool_output.json
ROCOCO_PARA_DIGEST: ${{ github.workspace}}/rococo-parachain-srtool-json/rococo-parachain_srtool_output.json
CANVAS_KUSAMA_DIGEST: ${{ github.workspace}}/canvas-kusama-srtool-json/canvas-kusama_srtool_output.json
REF1: ${{ github.event.inputs.ref1 }}
REF2: ${{ github.event.inputs.ref2 }}
PRE_RELEASE: ${{ github.event.inputs.pre_release }}
@@ -132,7 +133,8 @@ jobs:
ls -al $WESTMINT_DIGEST
ls -al $STATEMINE_DIGEST
ls -al $STATEMINT_DIGEST
ls -al $ROCOCO_DIGEST
ls -al $ROCOCO_PARA_DIGEST
ls -al $CANVAS_KUSAMA_DIGEST
echo "The diff will be computed from $REF1 to $REF2"
cd cumulus/scripts/changelog
@@ -166,7 +168,7 @@ jobs:
RUNTIME_DIR: polkadot-parachains
strategy:
matrix:
runtime: ["shell", "statemine", "statemint", "westmint", "rococo-parachain"]
runtime: ["shell", "statemine", "statemint", "westmint", "rococo-parachain", "canvas-kusama"]
steps:
- name: Checkout sources
uses: actions/checkout@v2
@@ -192,6 +194,12 @@ jobs:
echo "Found version: >$runtime_ver<"
echo "::set-output name=runtime_ver::$runtime_ver"
- name: Fix parachain runtime name
id: fix-runtime-path
run: |
cd "${{ matrix.runtime }}-runtime/"
mv "$(sed 's/-parachain/_parachain/' <<< ${{ matrix.runtime }})_runtime.compact.compressed.wasm" "${{ matrix.runtime }}_runtime.compact.compressed.wasm" || true
- name: Upload compressed ${{ matrix.runtime }} wasm
uses: actions/upload-release-asset@v1
env:
@@ -0,0 +1,121 @@
name: Release - Docker (Manual)
# This workflow fetches the binaries, checks sha256 and GPG
# signatures, then builds an injected docker
# image and publishes it.
on:
workflow_dispatch:
inputs:
tag:
description: release tag to build image for
default: polkadot-v0.9.17
required: true
prerelease:
description: is prerelease
default: false
required: true
jobs:
docker_build_publish:
env:
BINARY: polkadot-collator
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
with:
ref: ${{ github.event.release.tag_name }}
- name: Fetch files from release
run: |
echo "Repo: ${{ github.event.repository.full_name }}"
for f in $BINARY $BINARY.asc $BINARY.sha256; do
URL="https://github.com/${{ github.event.repository.full_name }}/releases/download/${{ github.event.inputs.tag }}/$f"
echo " - Fetching $f from $URL"
wget "$URL" -O "$f"
done
chmod a+x $BINARY
ls -al
- name: Check files
run: |
ls -al *collator*
shasum -a 256 -c $BINARY.sha256
sha_result=$?
KEY_PARITY_SEC=9D4B2B6EB8F97156D19669A9FF0812D491B96798
KEY_CHEVDOR=2835EAF92072BC01D188AF2C4A092B93E97CE1E2
KEYSERVER=keyserver.ubuntu.com
gpg --keyserver $KEYSERVER --receive-keys $KEY_PARITY_SEC
if [[ ${{ github.event.inputs.prerelease }} == "true" ]]; then
gpg --keyserver $KEYSERVER --receive-keys $KEY_CHEVDOR
fi
gpg --verify $BINARY.asc
gpg_result=$?
echo sha_result: $sha_result
echo gpg_result: $gpg_result
# If it fails, it would fail earlier but a second check
# does not hurt in case of refactoring...
if [[ $sha_result -ne 0 || $gpg_result -ne 0 ]]; then
echo "Check failed, exiting with error"
exit 1
else
echo "Checks passed"
fi
- name: Build injected image
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
run: |
export OWNER=$DOCKERHUB_USERNAME
mkdir -p target/release
cp -f $BINARY* target/release/
./docker/scripts/build-injected-image.sh
- name: Login to Dockerhub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Tag and Publish
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
run: |
docker run --pull never --rm $DOCKERHUB_USERNAME/$BINARY --version
VERSION=$(docker run --pull never --rm $DOCKERHUB_USERNAME/$BINARY --version | awk '{ print $2 }' )
SEMVER=$( echo $VERSION | cut -f1 -d- )
GITREF=$( echo $VERSION | cut -f2 -d- )
PRE=${{ github.event.inputs.prerelease }}
PRE_STR=""
echo "SEMVER=$SEMVER"
echo "GITREF=$GITREF"
echo "PRE=$PRE"
# Build a tag such as:
# 1.2.3-8a1201273 or
# 1.2.3-pre-8a1201273 for pre-releases
[[ $PRE == "true" ]] && PRE_STR="-pre"
TAG=${SEMVER}${PRE_STR}-${GITREF}
echo "PRE_STR=$PRE_STR"
echo "TAG=$TAG"
docker tag $DOCKERHUB_USERNAME/$BINARY $DOCKERHUB_USERNAME/$BINARY:$TAG
docker push $DOCKERHUB_USERNAME/$BINARY:$TAG
if [[ $PRE != "true" ]]; then
docker tag $DOCKERHUB_USERNAME/$BINARY $DOCKERHUB_USERNAME/$BINARY:latest
docker tag $DOCKERHUB_USERNAME/$BINARY $DOCKERHUB_USERNAME/$BINARY:$SEMVER
docker push $DOCKERHUB_USERNAME/$BINARY:latest
docker push $DOCKERHUB_USERNAME/$BINARY:$SEMVER
fi
docker images | grep $DOCKERHUB_USERNAME/$BINARY
+10 -9
View File
@@ -24,18 +24,18 @@ jobs:
- name: Fetch files from release
run: |
echo Repo: ${{ github.event.repository.full_name }}
echo "Repo: ${{ github.event.repository.full_name }}"
echo Name: ${{ github.event.release.name }}
echo Tag: ${{ github.event.release.tag_name }}
echo Draft: ${{ github.event.release.draft }}
echo Prerelease: ${{ github.event.release.prerelease }}
echo Assets: ${{ github.event.release.assets }}
echo "Name: ${{ github.event.release.name }}"
echo "Tag: ${{ github.event.release.tag_name }}"
echo "Draft: ${{ github.event.release.draft }}"
echo "Prerelease: ${{ github.event.release.prerelease }}"
echo "Assets: ${{ github.event.release.assets }}"
for f in $BINARY $BINARY.asc $BINARY.sha256; do
URL="https://github.com/${{ github.event.repository.full_name }}/releases/download/${{ github.event.release.tag_name }}/$f"
echo " - Fetching $f from $URL"
wget $URL -O $f
wget "$URL" -O "$f"
done
chmod a+x $BINARY
ls -al
@@ -48,10 +48,11 @@ jobs:
KEY_PARITY_SEC=9D4B2B6EB8F97156D19669A9FF0812D491B96798
KEY_CHEVDOR=2835EAF92072BC01D188AF2C4A092B93E97CE1E2
KEYSERVER=keyserver.ubuntu.com
gpg --receive-keys $KEY_PARITY_SEC
gpg --keyserver $KEYSERVER --receive-keys $KEY_PARITY_SEC
if [[ ${{ github.event.release.prerelease }} == "true" ]]; then
gpg --receive-keys $KEY_CHEVDOR
gpg --keyserver $KEYSERVER --receive-keys $KEY_CHEVDOR
fi
gpg --verify $BINARY.asc
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
chain: ["statemine", "westmint", "statemint", "rococo-parachain", "shell"]
chain: ["statemine", "westmint", "statemint", "rococo-parachain", "shell", "canvas-kusama"]
steps:
- uses: actions/checkout@v2
with:
+16
View File
@@ -17,6 +17,7 @@ variables: &default-vars
CI_IMAGE: "paritytech/ci-linux:production"
DOCKER_OS: "debian:stretch"
ARCH: "x86_64"
WASM_BUILD_WORKSPACE_HINT: "/builds/parity/cumulus/"
.rust-info-script: &rust-info-script
- rustup show
@@ -113,6 +114,8 @@ check-runtime-benchmarks:
script:
# Check that the node will compile with `runtime-benchmarks` feature flag.
- time cargo check --all --features runtime-benchmarks
# Check that parachain-template will compile with `runtime-benchmarks` feature flag.
- time cargo check -p parachain-template-node --features runtime-benchmarks
- sccache -s
cargo-check-try-runtime:
@@ -121,6 +124,8 @@ cargo-check-try-runtime:
script:
# Check that the node will compile with `try-runtime` feature flag.
- time cargo check --all --features try-runtime
# Check that parachain-template will compile with `try-runtime` feature flag.
- time cargo check -p parachain-template-node --features try-runtime
- sccache -s
cargo-check-benches:
@@ -130,6 +135,17 @@ cargo-check-benches:
- time cargo check --all --benches
- sccache -s
check-rustdoc:
stage: test
<<: *docker-env
variables:
<<: *default-vars
SKIP_WASM_BUILD: 1
RUSTDOCFLAGS: "-Dwarnings"
script:
- time cargo +nightly doc --workspace --all-features --verbose --no-deps
- sccache -s
#### stage: publish
publish-s3:
Generated
+2261 -1432
View File
File diff suppressed because it is too large Load Diff
+9
View File
@@ -8,6 +8,8 @@ members = [
"client/pov-recovery",
"client/service",
"client/relay-chain-interface",
"client/relay-chain-inprocess-interface",
"client/relay-chain-rpc-interface",
"pallets/aura-ext",
"pallets/collator-selection",
"pallets/dmp-queue",
@@ -31,6 +33,7 @@ members = [
"polkadot-parachains/statemint",
"polkadot-parachains/statemine",
"polkadot-parachains/westmint",
"polkadot-parachains/canvas-kusama",
"test/client",
"test/relay-sproof-builder",
"test/relay-validation-worker-provider",
@@ -40,3 +43,9 @@ members = [
[profile.release]
panic = "unwind"
opt-level = 3
[profile.production]
inherits = "release"
lto = true
codegen-units = 1
+118 -22
View File
@@ -1,4 +1,9 @@
# Cumulus :cloud:
# Cumulus ☁️
This repository contains both the Cumulus SDK and also specific chains implemented
on top of this SDK.
## Cumulus SDK
A set of tools for writing [Substrate](https://substrate.io/)-based
[Polkadot](https://wiki.polkadot.network/en/)
@@ -14,9 +19,9 @@ make it easy to write parachains for Polkadot by leveraging the power of Substra
Cumulus clouds are shaped sort of like dots; together they form a system that is intricate,
beautiful and functional.
## Consensus
### Consensus
[`cumulus-consensus`](consensus) is a
[`parachain-consensus`](https://github.com/paritytech/cumulus/blob/master/client/consensus/common/src/parachain_consensus.rs) is a
[consensus engine](https://docs.substrate.io/v3/advanced/consensus) for Substrate
that follows a Polkadot
[relay chain](https://wiki.polkadot.network/docs/en/learn-architecture#relay-chain). This will run
@@ -25,18 +30,18 @@ to follow,
[finalize](https://wiki.polkadot.network/docs/en/learn-consensus#probabilistic-vs-provable-finality),
and treat as best.
## Collator
### Collator
A Polkadot [collator](https://wiki.polkadot.network/docs/en/learn-collator) for the parachain is
implemented by [`cumulus-collator`](collator).
implemented by the `polkadot-collator` binary.
# Statemint 🪙
## Statemint 🪙
This repository also contains the Statemint runtime (as well as the canary runtime Statemine and the
test runtime Westmint).
Statemint is a common good parachain providing an asset store for the Polkadot ecosystem.
## Build & Launch a Node
### Build & Launch a Node
To run a Statemine or Westmint node (Statemint is not deployed, yet) you will need to compile the
`polkadot-collator` binary:
@@ -54,14 +59,104 @@ CHAIN=westmint # or statemine
Refer to the [setup instructions below](#local-setup) to run a local network for development.
# Rococo :crown:
## Canvas 🧑‍🎨
[![matrix][k1]][k2] [![discord][l1]][l2]
[k1]: https://img.shields.io/badge/matrix-chat-brightgreen.svg?style=flat
[k2]: https://riot.im/app/#/room/#ink:matrix.parity.io
[l1]: https://img.shields.io/discord/722223075629727774?style=flat-square&label=discord
[l2]: https://discord.com/invite/wGUDt2p
This is a node implementation of `Canvas`, a common good parachain for `pallet-contracts`
based wasm smart contracts. Right now this repository only contains the `canvas-kusama` runtime
which we plan to use for both Rococo and Kusama.
If you have any questions, feel free to talk to us on [Element][k2] or on [Discord][l2]
(in the [`ink_smart-contracts`](https://discord.com/channels/722223075629727774/765280480609828864) channel).
## Developing Smart Contracts for Canvas
![Canvas Overview](./docs/canvas-overview.svg)
This node contains Substrate's smart contracts module the
[`contracts`](https://github.com/paritytech/substrate/tree/master/frame/contracts) pallet.
This `contracts` pallet takes smart contracts as WebAssembly blobs and defines an API
for everything a smart contract needs (storage access, …).
As long as a programming language compiles to WebAssembly and there exists an implementation
of this API in it, you can write a smart contract for this pallet and thus for Canvas in
that language.
This is a list of languages you can currently choose from:
* [Parity's ink!](https://github.com/paritytech/ink) for Rust
* [ask!](https://github.com/patractlabs/ask) for Assembly Script
* The [Solang](https://github.com/hyperledger-labs/solang) compiler for Solidity
There are also different user interfaces and command-line tools you can use to deploy
or interact with contracts:
* [polkadot-js](https://polkadot.js.org/apps/)
* [Canvas UI](https://paritytech.github.io/canvas-ui/) (outdated)
If you are looking for a quickstart, we can recommend
[ink!'s Guided Tutorial for Beginners](https://docs.substrate.io/tutorials/v3/ink-workshop/pt1/).
### Build & Launch a Node
To run a Canvas node that connects to Rococo (Kusama and Polkadot parachains are not deployed, yet)
you will need to compile the `polkadot-collator` binary:
```bash
cargo build --release --locked -p polkadot-collator
```
Once the executable is built, launch the parachain node via:
```bash
./target/release/polkadot-collator --chain rocanvas
```
Refer to the [setup instructions below](#local-setup) to run a local network for development.
### Rococo Deployment
We have a live deployment of the Canvas parachain on [Rococo](https://wiki.polkadot.network/docs/build-pdk#rococo-testnet)
a testnet for Polkadot and Kusama parachains.
You can interact with the network through Polkadot JS Apps,
[click here for a direct link to Canvas](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-canvas-rpc.polkadot.io#/explorer).
The Canvas parachain uses the Rococo relay chain's native token (ROC) instead of having its own token.
Due to this you'll need ROC in order to deploy contracts on Canvas.
As a first step, you should create an account. See [here](https://wiki.polkadot.network/docs/learn-account-generation)
for a detailed guide.
As a second step, you have to get ROC testnet tokens through the [Rococo Faucet](https://wiki.polkadot.network/docs/learn-DOT#getting-rococo-tokens).
This is a chat room in which you need to write:
```bash
!drip YOUR_SS_58_ADDRESS:1002
```
The number `1002` is the parachain id of Canvas on Rococo, by supplying it the faucet will teleport ROC
tokens directly to your account on the parachain.
If everything worked out, the teleported ROC tokens will show up under
[the "Accounts" tab for Canvas](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-canvas-rpc.polkadot.io#/accounts).
Once you have ROC on Canvas you can deploy a contract as you would normally.
If you're unsure about this, our [guided tutorial](https://docs.substrate.io/tutorials/v3/ink-workshop/pt1/)
will clarify that for you in no time.
## Rococo 👑
[Rococo](https://polkadot.js.org/apps/?rpc=wss://rococo-rpc.polkadot.io) is becoming a [Community Parachain Testbed](https://polkadot.network/blog/rococo-revamp-becoming-a-community-parachain-testbed/) for parachain teams in the Polkadot ecosystem. It supports multiple parachains with the differentiation of long-term connections and recurring short-term connections, to see which parachains are currently connected and how long they will be connected for [see here](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-rpc.polkadot.io#/parachains).
Rococo is an elaborate style of design and the name describes the painstaking effort that has gone
into this project.
## Build & Launch Rococo Collators
### Build & Launch Rococo Collators
Collators are similar to validators in the relay chain. These nodes build the blocks that will
eventually be included by the relay chain for a parachain.
@@ -92,19 +187,21 @@ Once the executable is built, launch collators for each parachain (repeat once e
./target/release/polkadot-collator --chain $CHAIN --validator
```
## Parachains
### Parachains
- [Canvas - WASM Smart Contract](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-canvas-rpc.polkadot.io#/explorer)
* [Statemint](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-statemint-rpc.polkadot.io#/explorer)
* [Canvas on Rococo](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-canvas-rpc.polkadot.io#/explorer)
* [RILT](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo.kilt.io#/explorer)
The network uses horizontal message passing (HRMP) to enable communication between parachains and
the relay chain and, in turn, between parachains. This means that every message is sent to the relay
chain, and from the relay chain to its destination parachain.
## Local Setup
### Local Setup
Launch a local setup including a Relay Chain and a Parachain.
### Launch the Relay Chain
#### Launch the Relay Chain
```bash
# Compile Polkadot with the real overseer feature
@@ -121,7 +218,7 @@ cargo build --release
./target/release/polkadot --chain rococo-local-cfde.json --bob --tmp --port 30334
```
### Launch the Parachain
#### Launch the Parachain
```bash
# Compile
@@ -129,27 +226,26 @@ git clone https://github.com/paritytech/cumulus
cargo build --release
# Export genesis state
# --parachain-id 200 as an example that can be chosen freely. Make sure to everywhere use the same parachain id
./target/release/polkadot-collator export-genesis-state --parachain-id 200 > genesis-state
./target/release/polkadot-collator export-genesis-state > genesis-state
# Export genesis wasm
./target/release/polkadot-collator export-genesis-wasm > genesis-wasm
# Collator1
./target/release/polkadot-collator --collator --alice --force-authoring --tmp --parachain-id <parachain_id_u32_type_range> --port 40335 --ws-port 9946 -- --execution wasm --chain ../polkadot/rococo-local-cfde.json --port 30335
./target/release/polkadot-collator --collator --alice --force-authoring --tmp --port 40335 --ws-port 9946 -- --execution wasm --chain ../polkadot/rococo-local-cfde.json --port 30335
# Collator2
./target/release/polkadot-collator --collator --bob --force-authoring --tmp --parachain-id <parachain_id_u32_type_range> --port 40336 --ws-port 9947 -- --execution wasm --chain ../polkadot/rococo-local-cfde.json --port 30336
./target/release/polkadot-collator --collator --bob --force-authoring --tmp --port 40336 --ws-port 9947 -- --execution wasm --chain ../polkadot/rococo-local-cfde.json --port 30336
# Parachain Full Node 1
./target/release/polkadot-collator --tmp --parachain-id <parachain_id_u32_type_range> --port 40337 --ws-port 9948 -- --execution wasm --chain ../polkadot/rococo-local-cfde.json --port 30337
./target/release/polkadot-collator --tmp --port 40337 --ws-port 9948 -- --execution wasm --chain ../polkadot/rococo-local-cfde.json --port 30337
```
### Register the parachain
#### Register the parachain
![image](https://user-images.githubusercontent.com/2915325/99548884-1be13580-2987-11eb-9a8b-20be658d34f9.png)
## Containerize
### Containerize
After building `polkadot-collator` with cargo or with Parity CI image as documented in [this chapter](#build--launch-rococo-collators),
the following will allow producing a new docker image where the compiled binary is injected:
@@ -166,5 +262,5 @@ docker build --tag $OWNER/$IMAGE_NAME --file ./docker/polkadot-collator_builder.
You may then run your new container:
```bash
docker run --rm -it $OWNER/$IMAGE_NAME --collator --tmp --parachain-id 1000 --execution wasm --chain /specs/westmint.json
docker run --rm -it $OWNER/$IMAGE_NAME --collator --tmp --execution wasm --chain /specs/westmint.json
```
+3 -2
View File
@@ -5,8 +5,9 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[dependencies]
structopt = "0.3.3"
clap = { version = "3.1", features = ["derive"] }
# Substrate dependencies
# Substrate
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
url = "2.2.2"
+65 -11
View File
@@ -18,7 +18,7 @@
#![warn(missing_docs)]
use sc_cli;
use clap::Parser;
use sc_service::{
config::{PrometheusConfig, TelemetryEndpoints},
BasePath, TransactionPoolOptions,
@@ -28,21 +28,21 @@ use std::{
io::{self, Write},
net::SocketAddr,
};
use structopt::StructOpt;
use url::Url;
/// The `purge-chain` command used to remove the whole chain: the parachain and the relay chain.
#[derive(Debug, StructOpt)]
#[derive(Debug, Parser)]
pub struct PurgeChainCmd {
/// The base struct of the purge-chain command.
#[structopt(flatten)]
#[clap(flatten)]
pub base: sc_cli::PurgeChainCmd,
/// Only delete the para chain database
#[structopt(long, aliases = &["para"])]
#[clap(long, aliases = &["para"])]
pub parachain: bool,
/// Only delete the relay chain database
#[structopt(long, aliases = &["relay"])]
#[clap(long, aliases = &["relay"])]
pub relaychain: bool,
}
@@ -54,8 +54,9 @@ impl PurgeChainCmd {
relay_config: sc_service::Configuration,
) -> sc_cli::Result<()> {
let databases = match (self.parachain, self.relaychain) {
(true, true) | (false, false) =>
vec![("parachain", para_config.database), ("relaychain", relay_config.database)],
(true, true) | (false, false) => {
vec![("parachain", para_config.database), ("relaychain", relay_config.database)]
},
(true, false) => vec![("parachain", para_config.database)],
(false, true) => vec![("relaychain", relay_config.database)],
};
@@ -118,18 +119,54 @@ impl sc_cli::CliConfiguration for PurgeChainCmd {
}
}
fn validate_relay_chain_url(arg: &str) -> Result<(), String> {
let url = Url::parse(arg).map_err(|e| e.to_string())?;
if url.scheme() == "ws" {
Ok(())
} else {
Err(format!(
"'{}' URL scheme not supported. Only websocket RPC is currently supported",
url.scheme()
))
}
}
/// The `run` command used to run a node.
#[derive(Debug, StructOpt)]
#[derive(Debug, Parser)]
pub struct RunCmd {
/// The cumulus RunCmd inherents from sc_cli's
#[structopt(flatten)]
#[clap(flatten)]
pub base: sc_cli::RunCmd,
/// Run node as collator.
///
/// Note that this is the same as running with `--validator`.
#[structopt(long, conflicts_with = "validator")]
#[clap(long, conflicts_with = "validator")]
pub collator: bool,
/// EXPERIMENTAL: Specify an URL to a relay chain full node to communicate with.
#[clap(
long,
parse(try_from_str),
validator = validate_relay_chain_url,
conflicts_with = "collator",
conflicts_with = "validator",
conflicts_with = "alice",
conflicts_with = "bob",
conflicts_with = "charlie",
conflicts_with = "dave",
conflicts_with = "eve",
conflicts_with = "ferdie"
)]
pub relay_chain_rpc_url: Option<Url>,
}
/// Options only relevant for collator nodes
#[derive(Clone, Debug)]
pub struct CollatorOptions {
/// Location of relay chain full node
pub relay_chain_rpc_url: Option<Url>,
}
/// A non-redundant version of the `RunCmd` that sets the `validator` field when the
@@ -149,6 +186,11 @@ impl RunCmd {
NormalizedRunCmd { base: new_base }
}
/// Create [`CollatorOptions`] representing options only relevant to parachain collator nodes
pub fn collator_options(&self) -> CollatorOptions {
CollatorOptions { relay_chain_rpc_url: self.relay_chain_rpc_url.clone() }
}
}
impl sc_cli::CliConfiguration for NormalizedRunCmd {
@@ -231,6 +273,14 @@ impl sc_cli::CliConfiguration for NormalizedRunCmd {
self.base.rpc_methods()
}
fn rpc_max_payload(&self) -> sc_cli::Result<Option<usize>> {
self.base.rpc_max_payload()
}
fn ws_max_out_buffer_capacity(&self) -> sc_cli::Result<Option<usize>> {
self.base.ws_max_out_buffer_capacity()
}
fn transaction_pool(&self) -> sc_cli::Result<TransactionPoolOptions> {
self.base.transaction_pool()
}
@@ -239,6 +289,10 @@ impl sc_cli::CliConfiguration for NormalizedRunCmd {
self.base.max_runtime_instances()
}
fn runtime_cache_size(&self) -> sc_cli::Result<u8> {
self.base.runtime_cache_size()
}
fn base_path(&self) -> sc_cli::Result<Option<BasePath>> {
self.base.base_path()
}
+24 -25
View File
@@ -5,42 +5,41 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[dependencies]
# Substrate dependencies
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] }
futures = { version = "0.3.1", features = ["compat"] }
parking_lot = "0.12.0"
tracing = "0.1.25"
# Substrate
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot dependencies
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Polkadot
polkadot-node-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-overseer = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-subsystem = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-overseer = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus dependencies
cumulus-client-network = { path = "../network" }
# Cumulus
cumulus-client-consensus-common = { path = "../consensus/common" }
cumulus-client-network = { path = "../network" }
cumulus-primitives-core = { path = "../../primitives/core" }
cumulus-relay-chain-interface = { path = "../relay-chain-interface" }
# Other dependencies
codec = { package = "parity-scale-codec", version = "2.3.0", features = [ "derive" ] }
futures = { version = "0.3.1", features = ["compat"] }
parking_lot = "0.10.2"
tracing = "0.1.25"
[dev-dependencies]
# Polkadot dependencies
polkadot-node-subsystem-test-helpers = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus dependencies
cumulus-test-runtime = { path = "../../test/runtime" }
cumulus-test-client = { path = "../../test/client" }
# Substrate dependencies
async-trait = "0.1.42"
# Substrate
sp-maybe-compressed-blob = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Other dependencies
async-trait = "0.1.42"
# Polkadot
polkadot-node-subsystem-test-helpers = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus
cumulus-test-client = { path = "../../test/client" }
cumulus-test-runtime = { path = "../../test/runtime" }
+66 -25
View File
@@ -18,11 +18,12 @@
use cumulus_client_network::WaitToAnnounce;
use cumulus_primitives_core::{
relay_chain::Hash as PHash, CollectCollationInfo, ParachainBlockData, PersistedValidationData,
relay_chain::Hash as PHash, CollationInfo, CollectCollationInfo, ParachainBlockData,
PersistedValidationData,
};
use sc_client_api::BlockBackend;
use sp_api::ProvideRuntimeApi;
use sp_api::{ApiExt, ProvideRuntimeApi};
use sp_consensus::BlockStatus;
use sp_core::traits::SpawnNamed;
use sp_runtime::{
@@ -32,11 +33,11 @@ use sp_runtime::{
use cumulus_client_consensus_common::ParachainConsensus;
use polkadot_node_primitives::{
BlockData, Collation, CollationGenerationConfig, CollationResult, PoV,
BlockData, Collation, CollationGenerationConfig, CollationResult, MaybeCompressedPoV, PoV,
};
use polkadot_node_subsystem::messages::{CollationGenerationMessage, CollatorProtocolMessage};
use polkadot_overseer::Handle as OverseerHandle;
use polkadot_primitives::v1::{CollatorPair, HeadData, Id as ParaId};
use polkadot_primitives::v1::{CollatorPair, Id as ParaId};
use codec::{Decode, Encode};
use futures::{channel::oneshot, FutureExt};
@@ -144,30 +145,58 @@ where
}
}
/// Fetch the collation info from the runtime.
///
/// Returns `Ok(Some(_))` on success, `Err(_)` on error or `Ok(None)` if the runtime api isn't implemented by the runtime.
fn fetch_collation_info(
&self,
block_hash: Block::Hash,
header: &Block::Header,
) -> Result<Option<CollationInfo>, sp_api::ApiError> {
let runtime_api = self.runtime_api.runtime_api();
let block_id = BlockId::Hash(block_hash);
let api_version =
match runtime_api.api_version::<dyn CollectCollationInfo<Block>>(&block_id)? {
Some(version) => version,
None => {
tracing::error!(
target: LOG_TARGET,
"Could not fetch `CollectCollationInfo` runtime api version."
);
return Ok(None)
},
};
let collation_info = if api_version < 2 {
#[allow(deprecated)]
runtime_api
.collect_collation_info_before_version_2(&block_id)?
.into_latest(header.encode().into())
} else {
runtime_api.collect_collation_info(&block_id, header)?
};
Ok(Some(collation_info))
}
fn build_collation(
&mut self,
&self,
block: ParachainBlockData<Block>,
block_hash: Block::Hash,
pov: PoV,
) -> Option<Collation> {
let block_data = BlockData(block.encode());
let header = block.into_header();
let head_data = HeadData(header.encode());
let collation_info = match self
.runtime_api
.runtime_api()
.collect_collation_info(&BlockId::Hash(block_hash))
{
Ok(ci) => ci,
Err(e) => {
let collation_info = self
.fetch_collation_info(block_hash, block.header())
.map_err(|e| {
tracing::error!(
target: LOG_TARGET,
error = ?e,
"Failed to collect collation info.",
);
return None
},
};
)
})
.ok()
.flatten()?;
Some(Collation {
upward_messages: collation_info.upward_messages,
@@ -175,8 +204,8 @@ where
processed_downward_messages: collation_info.processed_downward_messages,
horizontal_messages: collation_info.horizontal_messages,
hrmp_watermark: collation_info.hrmp_watermark,
head_data,
proof_of_validity: PoV { block_data },
head_data: collation_info.head_data,
proof_of_validity: MaybeCompressedPoV::Compressed(pov),
})
}
@@ -244,8 +273,17 @@ where
b.storage_proof().encode().len() as f64 / 1024f64,
);
let pov =
polkadot_node_primitives::maybe_compress_pov(PoV { block_data: BlockData(b.encode()) });
tracing::info!(
target: LOG_TARGET,
"Compressed PoV size: {}kb",
pov.block_data.0.len() as f64 / 1024f64,
);
let block_hash = b.header().hash();
let collation = self.build_collation(b, block_hash)?;
let collation = self.build_collation(b, block_hash, pov)?;
let (result_sender, signed_stmt_recv) = oneshot::channel();
@@ -422,10 +460,13 @@ mod tests {
.expect("Collation is build")
.collation;
let block_data = collation.proof_of_validity.block_data;
let pov = collation.proof_of_validity.into_compressed();
let decompressed =
sp_maybe_compressed_blob::decompress(&pov.block_data.0, 1024 * 1024 * 10).unwrap();
let block =
ParachainBlockData::<Block>::decode(&mut &block_data.0[..]).expect("Is a valid block");
ParachainBlockData::<Block>::decode(&mut &decompressed[..]).expect("Is a valid block");
assert_eq!(1, *block.header().number());
+18 -19
View File
@@ -6,30 +6,29 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[dependencies]
# Substrate dependencies
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master" }
async-trait = "0.1.42"
codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] }
futures = { version = "0.3.8", features = ["compat"] }
tracing = "0.1.31"
# Substrate
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus-slots = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Cumulus dependencies
# Cumulus
cumulus-client-consensus-common = { path = "../common" }
cumulus-primitives-core = { path = "../../../primitives/core" }
# Other deps
futures = { version = "0.3.8", features = ["compat"] }
codec = { package = "parity-scale-codec", version = "2.3.0", features = [ "derive" ] }
tracing = "0.1.22"
async-trait = "0.1.42"
+8 -12
View File
@@ -14,11 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
//! The AuRa consensus algoritm for parachains.
//! The AuRa consensus algorithm for parachains.
//!
//! This extends the Substrate provided AuRa consensus implementation to make it compatible for
//! parachains. The main entry points for of this consensus algorithm are [`build_aura_consensus`]
//! and [`import_queue`].
//! parachains. The main entry points for of this consensus algorithm are [`AuraConsensus::build`]
//! and [`fn@import_queue`].
//!
//! For more information about AuRa, the Substrate crate should be checked.
@@ -36,10 +36,8 @@ use sc_telemetry::TelemetryHandle;
use sp_api::ProvideRuntimeApi;
use sp_application_crypto::AppPublic;
use sp_blockchain::HeaderBackend;
use sp_consensus::{
EnableProofRecording, Environment, ProofRecording, Proposer, SlotData, SyncOracle,
};
use sp_consensus_aura::AuraApi;
use sp_consensus::{EnableProofRecording, Environment, ProofRecording, Proposer, SyncOracle};
use sp_consensus_aura::{AuraApi, SlotDuration};
use sp_core::crypto::Pair;
use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvider};
use sp_keystore::SyncCryptoStorePtr;
@@ -49,9 +47,7 @@ use std::{convert::TryFrom, hash::Hash, sync::Arc};
mod import_queue;
pub use import_queue::{build_verifier, import_queue, BuildVerifierParams, ImportQueueParams};
pub use sc_consensus_aura::{
slot_duration, AuraVerifier, BuildAuraWorkerParams, SlotDuration, SlotProportion,
};
pub use sc_consensus_aura::{slot_duration, AuraVerifier, BuildAuraWorkerParams, SlotProportion};
pub use sc_consensus_slots::InherentDataProviderExt;
const LOG_TARGET: &str = "aura::cumulus";
@@ -201,7 +197,7 @@ where
inherent_data_providers.slot(),
inherent_data_providers.timestamp(),
inherent_data,
self.slot_duration.slot_duration(),
self.slot_duration.as_duration(),
parent.clone(),
// Set the block limit to 50% of the maximum PoV size.
//
@@ -216,7 +212,7 @@ where
}
}
/// Paramaters of [`build_aura_consensus`].
/// Parameters of [`AuraConsensus::build`].
pub struct BuildAuraConsensusParams<PF, BI, CIDP, Client, BS, SO> {
pub proposer_factory: PF,
pub create_inherent_data_providers: CIDP,
+24 -24
View File
@@ -6,32 +6,32 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[dependencies]
# Substrate deps
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot deps
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus deps
cumulus-relay-chain-interface = { path = "../../relay-chain-interface" }
# Other deps
futures = { version = "0.3.8", features = ["compat"] }
codec = { package = "parity-scale-codec", version = "2.3.0", features = [ "derive" ] }
tracing = "0.1.25"
async-trait = "0.1.42"
codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] }
tracing = "0.1.31"
async-trait = "0.1.52"
dyn-clone = "1.0.4"
# Substrate
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus
cumulus-relay-chain-interface = { path = "../../relay-chain-interface" }
[dev-dependencies]
# Substrate deps
sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Cumulus dependencies
cumulus-test-client = { path = "../../../test/client" }
# Other deps
futures-timer = "3.0.2"
# Substrate
sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Cumulus
cumulus-test-client = { path = "../../../test/client" }
+1 -1
View File
@@ -104,7 +104,7 @@ where
mut block_import_params: sc_consensus::BlockImportParams<Block, Self::Transaction>,
cache: std::collections::HashMap<sp_consensus::CacheKeyId, Vec<u8>>,
) -> Result<sc_consensus::ImportResult, Self::Error> {
// Best block is determined by the relay chain, or if we are doing the intial sync
// Best block is determined by the relay chain, or if we are doing the initial sync
// we import all blocks as new best.
block_import_params.fork_choice = Some(sc_consensus::ForkChoiceStrategy::Custom(
block_import_params.origin == sp_consensus::BlockOrigin::NetworkInitialSync,
@@ -14,26 +14,30 @@
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
use cumulus_relay_chain_interface::RelayChainInterface;
use async_trait::async_trait;
use cumulus_relay_chain_interface::{RelayChainInterface, RelayChainResult};
use sc_client_api::{
Backend, BlockBackend, BlockImportNotification, BlockchainEvents, Finalizer, UsageProvider,
};
use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy};
use sp_blockchain::{Error as ClientError, Result as ClientResult};
use sp_blockchain::Error as ClientError;
use sp_consensus::{BlockOrigin, BlockStatus};
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, Header as HeaderT},
};
use polkadot_primitives::v1::{Block as PBlock, Id as ParaId, OccupiedCoreAssumption};
use polkadot_primitives::v1::{Hash as PHash, Id as ParaId, OccupiedCoreAssumption};
use codec::Decode;
use futures::{future, select, FutureExt, Stream, StreamExt};
use futures::{select, FutureExt, Stream, StreamExt};
use std::{pin::Pin, sync::Arc};
const LOG_TARGET: &str = "cumulus-consensus";
/// Helper for the relay chain client. This is expected to be a lightweight handle like an `Arc`.
#[async_trait]
pub trait RelaychainClient: Clone + 'static {
/// The error type for interacting with the Polkadot client.
type Error: std::fmt::Debug + Send;
@@ -42,17 +46,17 @@ pub trait RelaychainClient: Clone + 'static {
type HeadStream: Stream<Item = Vec<u8>> + Send + Unpin;
/// Get a stream of new best heads for the given parachain.
fn new_best_heads(&self, para_id: ParaId) -> Self::HeadStream;
async fn new_best_heads(&self, para_id: ParaId) -> RelayChainResult<Self::HeadStream>;
/// Get a stream of finalized heads for the given parachain.
fn finalized_heads(&self, para_id: ParaId) -> Self::HeadStream;
async fn finalized_heads(&self, para_id: ParaId) -> RelayChainResult<Self::HeadStream>;
/// Returns the parachain head for the given `para_id` at the given block id.
fn parachain_head_at(
async fn parachain_head_at(
&self,
at: &BlockId<PBlock>,
at: PHash,
para_id: ParaId,
) -> ClientResult<Option<Vec<u8>>>;
) -> RelayChainResult<Option<Vec<u8>>>;
}
/// Follow the finalized head of the given parachain.
@@ -66,7 +70,13 @@ where
R: RelaychainClient,
B: Backend<Block>,
{
let mut finalized_heads = relay_chain.finalized_heads(para_id);
let mut finalized_heads = match relay_chain.finalized_heads(para_id).await {
Ok(finalized_heads_stream) => finalized_heads_stream,
Err(err) => {
tracing::error!(target: LOG_TARGET, error = ?err, "Unable to retrieve finalized heads stream.");
return
},
};
loop {
let finalized_head = if let Some(h) = finalized_heads.next().await {
@@ -113,7 +123,7 @@ where
/// Run the parachain consensus.
///
/// This will follow the given `relay_chain` to act as consesus for the parachain that corresponds
/// This will follow the given `relay_chain` to act as consensus for the parachain that corresponds
/// to the given `para_id`. It will set the new best block of the parachain as it gets aware of it.
/// The same happens for the finalized block.
///
@@ -165,7 +175,14 @@ async fn follow_new_best<P, R, Block, B>(
R: RelaychainClient,
B: Backend<Block>,
{
let mut new_best_heads = relay_chain.new_best_heads(para_id).fuse();
let mut new_best_heads = match relay_chain.new_best_heads(para_id).await {
Ok(best_heads_stream) => best_heads_stream.fuse(),
Err(err) => {
tracing::error!(target: LOG_TARGET, error = ?err, "Unable to retrieve best heads stream.");
return
},
};
let mut imported_blocks = parachain.import_notification_stream().fuse();
// The unset best header of the parachain. Will be `Some(_)` when we have imported a relay chain
// block before the parachain block it included. In this case we need to wait for this block to
@@ -368,6 +385,7 @@ where
}
}
#[async_trait]
impl<RCInterface> RelaychainClient for RCInterface
where
RCInterface: RelayChainInterface + Clone + 'static,
@@ -376,39 +394,41 @@ where
type HeadStream = Pin<Box<dyn Stream<Item = Vec<u8>> + Send>>;
fn new_best_heads(&self, para_id: ParaId) -> Self::HeadStream {
async fn new_best_heads(&self, para_id: ParaId) -> RelayChainResult<Self::HeadStream> {
let relay_chain = self.clone();
self.import_notification_stream()
let new_best_notification_stream = self
.new_best_notification_stream()
.await?
.filter_map(move |n| {
future::ready(if n.is_new_best {
relay_chain.parachain_head_at(&BlockId::hash(n.hash), para_id).ok().flatten()
} else {
None
})
let relay_chain = relay_chain.clone();
async move { relay_chain.parachain_head_at(n.hash(), para_id).await.ok().flatten() }
})
.boxed()
.boxed();
Ok(new_best_notification_stream)
}
fn finalized_heads(&self, para_id: ParaId) -> Self::HeadStream {
async fn finalized_heads(&self, para_id: ParaId) -> RelayChainResult<Self::HeadStream> {
let relay_chain = self.clone();
self.finality_notification_stream()
let finality_notification_stream = self
.finality_notification_stream()
.await?
.filter_map(move |n| {
future::ready(
relay_chain.parachain_head_at(&BlockId::hash(n.hash), para_id).ok().flatten(),
)
let relay_chain = relay_chain.clone();
async move { relay_chain.parachain_head_at(n.hash(), para_id).await.ok().flatten() }
})
.boxed()
.boxed();
Ok(finality_notification_stream)
}
fn parachain_head_at(
async fn parachain_head_at(
&self,
at: &BlockId<PBlock>,
at: PHash,
para_id: ParaId,
) -> ClientResult<Option<Vec<u8>>> {
) -> RelayChainResult<Option<Vec<u8>>> {
self.persisted_validation_data(at, para_id, OccupiedCoreAssumption::TimedOut)
.await
.map(|s| s.map(|s| s.parent_head.0))
.map_err(Into::into)
}
}
+10 -7
View File
@@ -16,17 +16,19 @@
use crate::*;
use async_trait::async_trait;
use codec::Encode;
use cumulus_relay_chain_interface::RelayChainResult;
use cumulus_test_client::{
runtime::{Block, Header},
Backend, Client, InitBlockBuilder, TestClientBuilder, TestClientBuilderExt,
};
use futures::{channel::mpsc, executor::block_on, select, FutureExt, Stream, StreamExt};
use futures_timer::Delay;
use polkadot_primitives::v1::{Block as PBlock, Id as ParaId};
use polkadot_primitives::v1::Id as ParaId;
use sc_client_api::UsageProvider;
use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy};
use sp_blockchain::{Error as ClientError, Result as ClientResult};
use sp_blockchain::Error as ClientError;
use sp_consensus::BlockOrigin;
use sp_runtime::generic::BlockId;
use std::{
@@ -66,12 +68,13 @@ impl Relaychain {
}
}
#[async_trait]
impl crate::parachain_consensus::RelaychainClient for Relaychain {
type Error = ClientError;
type HeadStream = Box<dyn Stream<Item = Vec<u8>> + Send + Unpin>;
fn new_best_heads(&self, _: ParaId) -> Self::HeadStream {
async fn new_best_heads(&self, _: ParaId) -> RelayChainResult<Self::HeadStream> {
let stream = self
.inner
.lock()
@@ -80,10 +83,10 @@ impl crate::parachain_consensus::RelaychainClient for Relaychain {
.take()
.expect("Should only be called once");
Box::new(stream.map(|v| v.encode()))
Ok(Box::new(stream.map(|v| v.encode())))
}
fn finalized_heads(&self, _: ParaId) -> Self::HeadStream {
async fn finalized_heads(&self, _: ParaId) -> RelayChainResult<Self::HeadStream> {
let stream = self
.inner
.lock()
@@ -92,10 +95,10 @@ impl crate::parachain_consensus::RelaychainClient for Relaychain {
.take()
.expect("Should only be called once");
Box::new(stream.map(|v| v.encode()))
Ok(Box::new(stream.map(|v| v.encode())))
}
fn parachain_head_at(&self, _: &BlockId<PBlock>, _: ParaId) -> ClientResult<Option<Vec<u8>>> {
async fn parachain_head_at(&self, _: PHash, _: ParaId) -> RelayChainResult<Option<Vec<u8>>> {
unimplemented!("Not required for tests")
}
}
+14 -17
View File
@@ -6,27 +6,24 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[dependencies]
# Substrate deps
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
async-trait = "0.1.42"
futures = { version = "0.3.8", features = ["compat"] }
parking_lot = "0.12.0"
tracing = "0.1.31"
# Substrate
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot dependencies
# Cumulus dependencies
# Cumulus
cumulus-client-consensus-common = { path = "../common" }
cumulus-primitives-core = { path = "../../../primitives/core" }
cumulus-relay-chain-interface = { path = "../../relay-chain-interface" }
# Other deps
futures = { version = "0.3.8", features = ["compat"] }
tracing = "0.1.22"
async-trait = "0.1.42"
parking_lot = "0.10.2"
+4 -4
View File
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
//! The relay-chain provided consensus algoritm for parachains.
//! The relay-chain provided consensus algorithm for parachains.
//!
//! This is the simplest consensus algorithm you can use when developing a parachain. It is a
//! permission-less consensus algorithm that doesn't require any staking or similar to join as a
@@ -28,7 +28,7 @@
//! 3. The parachain validators validate at most X different parachain candidates, where X is the
//! total number of parachain validators.
//!
//! 4. The parachain candidate that is backed by the most validators is choosen by the relay-chain
//! 4. The parachain candidate that is backed by the most validators is chosen by the relay-chain
//! block producer to be added as backed candidate on chain.
//!
//! 5. After the parachain candidate got backed and included, all collators start at 1.
@@ -176,7 +176,7 @@ where
.propose(
inherent_data,
Default::default(),
//TODO: Fix this.
// TODO: Fix this.
Duration::from_millis(500),
// Set the block limit to 50% of the maximum PoV size.
//
@@ -217,7 +217,7 @@ where
}
}
/// Paramaters of [`build_relay_chain_consensus`].
/// Parameters of [`build_relay_chain_consensus`].
pub struct BuildRelayChainConsensusParams<PF, BI, CIDP, RCInterface> {
pub para_id: ParaId,
pub proposer_factory: PF,
+39 -37
View File
@@ -6,50 +6,52 @@ description = "Cumulus-specific networking protocol"
edition = "2021"
[dependencies]
# Substrate deps
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot deps
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" }
cumulus-relay-chain-interface = { path = "../relay-chain-interface" }
# other deps
codec = { package = "parity-scale-codec", version = "2.3.0", features = [ "derive" ] }
async-trait = "0.1.52"
codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] }
derive_more = "0.99.2"
futures = { version = "0.3.1", features = ["compat"] }
futures-timer = "3.0.2"
tracing = "0.1.22"
parking_lot = "0.11.1"
derive_more = "0.99.2"
async-trait = "0.1.52"
parking_lot = "0.12.0"
tracing = "0.1.31"
# Substrate
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot
polkadot-node-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus
cumulus-relay-chain-interface = { path = "../relay-chain-interface" }
[dev-dependencies]
tokio = { version = "1.10", features = ["macros"] }
portpicker = "0.1.1"
tokio = { version = "1.17.0", features = ["macros"] }
url = "2.2.2"
# Cumulus deps
cumulus-test-service = { path = "../../test/service" }
cumulus-primitives-core = { path = "../../primitives/core" }
cumulus-relay-chain-local = { path = "../relay-chain-local" }
# Polkadot deps
polkadot-test-client = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-client = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# substrate deps
# Substrate
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot
polkadot-client = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-test-client = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus
cumulus-primitives-core = { path = "../../primitives/core" }
cumulus-relay-chain-inprocess-interface = { path = "../relay-chain-inprocess-interface" }
cumulus-test-service = { path = "../../test/service" }
+78 -77
View File
@@ -24,25 +24,18 @@ use sp_consensus::block_validation::{
BlockAnnounceValidator as BlockAnnounceValidatorT, Validation,
};
use sp_core::traits::SpawnNamed;
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, Header as HeaderT},
};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
use cumulus_relay_chain_interface::RelayChainInterface;
use polkadot_node_primitives::{CollationSecondedSignal, Statement};
use polkadot_parachain::primitives::HeadData;
use polkadot_primitives::v1::{
Block as PBlock, CandidateReceipt, CompactStatement, Hash as PHash, Id as ParaId,
OccupiedCoreAssumption, SigningContext, UncheckedSigned,
CandidateReceipt, CompactStatement, Hash as PHash, Id as ParaId, OccupiedCoreAssumption,
SigningContext, UncheckedSigned,
};
use codec::{Decode, DecodeAll, Encode};
use futures::{
channel::oneshot,
future::{ready, FutureExt},
Future,
};
use futures::{channel::oneshot, future::FutureExt, Future};
use std::{convert::TryFrom, fmt, marker::PhantomData, pin::Pin, sync::Arc};
@@ -128,7 +121,7 @@ impl BlockAnnounceData {
/// Check the signature of the statement.
///
/// Returns an `Err(_)` if it failed.
fn check_signature<RCInterface>(
async fn check_signature<RCInterface>(
self,
relay_chain_client: &RCInterface,
) -> Result<Validation, BlockAnnounceError>
@@ -137,17 +130,16 @@ impl BlockAnnounceData {
{
let validator_index = self.statement.unchecked_validator_index();
let runtime_api_block_id = BlockId::Hash(self.relay_parent);
let session_index = match relay_chain_client.session_index_for_child(&runtime_api_block_id)
{
Ok(r) => r,
Err(e) => return Err(BlockAnnounceError(format!("{:?}", e))),
};
let session_index =
match relay_chain_client.session_index_for_child(self.relay_parent).await {
Ok(r) => r,
Err(e) => return Err(BlockAnnounceError(format!("{:?}", e))),
};
let signing_context = SigningContext { parent_hash: self.relay_parent, session_index };
// Check that the signer is a legit validator.
let authorities = match relay_chain_client.validators(&runtime_api_block_id) {
let authorities = match relay_chain_client.validators(self.relay_parent).await {
Ok(r) => r,
Err(e) => return Err(BlockAnnounceError(format!("{:?}", e))),
};
@@ -164,7 +156,7 @@ impl BlockAnnounceData {
};
// Check statement is correctly signed.
if self.statement.try_into_checked(&signing_context, &signer).is_err() {
if self.statement.try_into_checked(&signing_context, signer).is_err() {
tracing::debug!(
target: LOG_TARGET,
"Block announcement justification signature is invalid.",
@@ -215,13 +207,14 @@ impl TryFrom<&'_ CollationSecondedSignal> for BlockAnnounceData {
/// will call this validator and provides the extra data that was attached to the announcement.
/// We call this extra data `justification`.
/// It is expected that the attached data is a SCALE encoded [`BlockAnnounceData`]. The
/// statement is checked to be a [`CompactStatement::Candidate`] and that it is signed by an active
/// statement is checked to be a [`CompactStatement::Seconded`] and that it is signed by an active
/// parachain validator.
///
/// If no justification was provided we check if the block announcement is at the tip of the known
/// chain. If it is at the tip, it is required to provide a justification or otherwise we reject
/// it. However, if the announcement is for a block below the tip the announcement is accepted
/// as it probably comes from a node that is currently syncing the chain.
#[derive(Clone)]
pub struct BlockAnnounceValidator<Block, RCInterface> {
phantom: PhantomData<Block>,
relay_chain_interface: RCInterface,
@@ -234,11 +227,7 @@ where
{
/// Create a new [`BlockAnnounceValidator`].
pub fn new(relay_chain_interface: RCInterface, para_id: ParaId) -> Self {
Self {
phantom: Default::default(),
relay_chain_interface: relay_chain_interface.clone(),
para_id,
}
Self { phantom: Default::default(), relay_chain_interface, para_id }
}
}
@@ -247,13 +236,14 @@ where
RCInterface: RelayChainInterface + Clone,
{
/// Get the included block of the given parachain in the relay chain.
fn included_block(
async fn included_block(
relay_chain_interface: &RCInterface,
block_id: &BlockId<PBlock>,
hash: PHash,
para_id: ParaId,
) -> Result<Block::Header, BoxedError> {
let validation_data = relay_chain_interface
.persisted_validation_data(block_id, para_id, OccupiedCoreAssumption::TimedOut)
.persisted_validation_data(hash, para_id, OccupiedCoreAssumption::TimedOut)
.await
.map_err(|e| Box::new(BlockAnnounceError(format!("{:?}", e))) as Box<_>)?
.ok_or_else(|| {
Box::new(BlockAnnounceError("Could not find parachain head in relay chain".into()))
@@ -269,56 +259,58 @@ where
}
/// Get the backed block hash of the given parachain in the relay chain.
fn backed_block_hash(
async fn backed_block_hash(
relay_chain_interface: &RCInterface,
block_id: &BlockId<PBlock>,
hash: PHash,
para_id: ParaId,
) -> Result<Option<PHash>, BoxedError> {
let candidate_receipt = relay_chain_interface
.candidate_pending_availability(block_id, para_id)
.candidate_pending_availability(hash, para_id)
.await
.map_err(|e| Box::new(BlockAnnounceError(format!("{:?}", e))) as Box<_>)?;
Ok(candidate_receipt.map(|cr| cr.descriptor.para_head))
}
/// Handle a block announcement with empty data (no statement) attached to it.
fn handle_empty_block_announce_data(
async fn handle_empty_block_announce_data(
&self,
header: Block::Header,
) -> impl Future<Output = Result<Validation, BoxedError>> {
) -> Result<Validation, BoxedError> {
let relay_chain_interface = self.relay_chain_interface.clone();
let para_id = self.para_id;
async move {
// Check if block is equal or higher than best (this requires a justification)
let relay_chain_best_hash = relay_chain_interface.best_block_hash();
let runtime_api_block_id = BlockId::Hash(relay_chain_best_hash);
let block_number = header.number();
// Check if block is equal or higher than best (this requires a justification)
let relay_chain_best_hash = relay_chain_interface
.best_block_hash()
.await
.map_err(|e| Box::new(e) as Box<_>)?;
let block_number = header.number();
let best_head =
Self::included_block(&relay_chain_interface, &runtime_api_block_id, para_id)?;
let known_best_number = best_head.number();
let backed_block =
|| Self::backed_block_hash(&relay_chain_interface, &runtime_api_block_id, para_id);
let best_head =
Self::included_block(&relay_chain_interface, relay_chain_best_hash, para_id).await?;
let known_best_number = best_head.number();
let backed_block = || async {
Self::backed_block_hash(&relay_chain_interface, relay_chain_best_hash, para_id).await
};
if best_head == header {
tracing::debug!(target: LOG_TARGET, "Announced block matches best block.",);
if best_head == header {
tracing::debug!(target: LOG_TARGET, "Announced block matches best block.",);
Ok(Validation::Success { is_new_best: true })
} else if Some(HeadData(header.encode()).hash()) == backed_block()? {
tracing::debug!(target: LOG_TARGET, "Announced block matches latest backed block.",);
Ok(Validation::Success { is_new_best: true })
} else if Some(HeadData(header.encode()).hash()) == backed_block().await? {
tracing::debug!(target: LOG_TARGET, "Announced block matches latest backed block.",);
Ok(Validation::Success { is_new_best: true })
} else if block_number >= known_best_number {
tracing::debug!(
Ok(Validation::Success { is_new_best: true })
} else if block_number >= known_best_number {
tracing::debug!(
target: LOG_TARGET,
"Validation failed because a justification is needed if the block at the top of the chain."
);
Ok(Validation::Failure { disconnect: false })
} else {
Ok(Validation::Success { is_new_best: false })
}
Ok(Validation::Failure { disconnect: false })
} else {
Ok(Validation::Success { is_new_best: false })
}
}
}
@@ -331,32 +323,40 @@ where
fn validate(
&mut self,
header: &Block::Header,
mut data: &[u8],
data: &[u8],
) -> Pin<Box<dyn Future<Output = Result<Validation, BoxedError>> + Send>> {
if self.relay_chain_interface.is_major_syncing() {
return ready(Ok(Validation::Success { is_new_best: false })).boxed()
}
if data.is_empty() {
return self.handle_empty_block_announce_data(header.clone()).boxed()
}
let block_announce_data = match BlockAnnounceData::decode_all(&mut data) {
Ok(r) => r,
Err(err) =>
return async move {
Err(Box::new(BlockAnnounceError(format!(
"Can not decode the `BlockAnnounceData`: {:?}",
err
))) as Box<_>)
}
.boxed(),
};
let relay_chain_interface = self.relay_chain_interface.clone();
let data = data.to_vec();
let header = header.clone();
let header_encoded = header.encode();
let block_announce_validator = self.clone();
async move {
let relay_chain_is_syncing = relay_chain_interface
.is_major_syncing()
.await
.map_err(|e| {
tracing::error!(target: LOG_TARGET, "Unable to determine sync status. {}", e)
})
.unwrap_or(false);
if relay_chain_is_syncing {
return Ok(Validation::Success { is_new_best: false })
}
if data.is_empty() {
return block_announce_validator.handle_empty_block_announce_data(header).await
}
let block_announce_data = match BlockAnnounceData::decode_all(&mut data.as_slice()) {
Ok(r) => r,
Err(err) =>
return Err(Box::new(BlockAnnounceError(format!(
"Can not decode the `BlockAnnounceData`: {:?}",
err
))) as Box<_>),
};
if let Err(e) = block_announce_data.validate(header_encoded) {
return Ok(e)
}
@@ -370,6 +370,7 @@ where
block_announce_data
.check_signature(&relay_chain_interface)
.await
.map_err(|e| Box::new(e) as Box<_>)
}
.boxed()
+76 -73
View File
@@ -16,15 +16,15 @@
use super::*;
use async_trait::async_trait;
use cumulus_relay_chain_interface::WaitError;
use cumulus_relay_chain_local::{check_block_in_chain, BlockCheckStatus};
use cumulus_relay_chain_inprocess_interface::{check_block_in_chain, BlockCheckStatus};
use cumulus_relay_chain_interface::{RelayChainError, RelayChainResult};
use cumulus_test_service::runtime::{Block, Hash, Header};
use futures::{executor::block_on, poll, task::Poll, FutureExt, StreamExt};
use futures::{executor::block_on, poll, task::Poll, FutureExt, Stream, StreamExt};
use parking_lot::Mutex;
use polkadot_node_primitives::{SignedFullStatement, Statement};
use polkadot_primitives::v1::{
Block as PBlock, CandidateCommitments, CandidateDescriptor, CollatorPair,
CommittedCandidateReceipt, Hash as PHash, HeadData, Id as ParaId, InboundDownwardMessage,
CandidateCommitments, CandidateDescriptor, CollatorPair, CommittedCandidateReceipt,
Hash as PHash, HeadData, Header as PHeader, Id as ParaId, InboundDownwardMessage,
InboundHrmpMessage, OccupiedCoreAssumption, PersistedValidationData, SessionIndex,
SigningContext, ValidationCodeHash, ValidatorId,
};
@@ -77,53 +77,47 @@ impl DummyRelayChainInterface {
#[async_trait]
impl RelayChainInterface for DummyRelayChainInterface {
fn validators(
&self,
_: &cumulus_primitives_core::relay_chain::BlockId,
) -> Result<Vec<ValidatorId>, sp_api::ApiError> {
async fn validators(&self, _: PHash) -> RelayChainResult<Vec<ValidatorId>> {
Ok(self.data.lock().validators.clone())
}
fn block_status(
&self,
block_id: cumulus_primitives_core::relay_chain::BlockId,
) -> Result<sp_blockchain::BlockStatus, sp_blockchain::Error> {
self.relay_backend.blockchain().status(block_id)
async fn best_block_hash(&self) -> RelayChainResult<PHash> {
Ok(self.relay_backend.blockchain().info().best_hash)
}
fn best_block_hash(&self) -> PHash {
self.relay_backend.blockchain().info().best_hash
}
fn retrieve_dmq_contents(&self, _: ParaId, _: PHash) -> Option<Vec<InboundDownwardMessage>> {
unimplemented!("Not needed for test")
}
fn retrieve_all_inbound_hrmp_channel_contents(
async fn retrieve_dmq_contents(
&self,
_: ParaId,
_: PHash,
) -> Option<BTreeMap<ParaId, Vec<InboundHrmpMessage>>> {
Some(BTreeMap::new())
) -> RelayChainResult<Vec<InboundDownwardMessage>> {
unimplemented!("Not needed for test")
}
fn persisted_validation_data(
async fn retrieve_all_inbound_hrmp_channel_contents(
&self,
_: &cumulus_primitives_core::relay_chain::BlockId,
_: ParaId,
_: PHash,
) -> RelayChainResult<BTreeMap<ParaId, Vec<InboundHrmpMessage>>> {
Ok(BTreeMap::new())
}
async fn persisted_validation_data(
&self,
_: PHash,
_: ParaId,
_: OccupiedCoreAssumption,
) -> Result<Option<PersistedValidationData>, sp_api::ApiError> {
) -> RelayChainResult<Option<PersistedValidationData>> {
Ok(Some(PersistedValidationData {
parent_head: HeadData(default_header().encode()),
..Default::default()
}))
}
fn candidate_pending_availability(
async fn candidate_pending_availability(
&self,
_: &cumulus_primitives_core::relay_chain::BlockId,
_: PHash,
_: ParaId,
) -> Result<Option<CommittedCandidateReceipt>, sp_api::ApiError> {
) -> RelayChainResult<Option<CommittedCandidateReceipt>> {
if self.data.lock().has_pending_availability {
Ok(Some(CommittedCandidateReceipt {
descriptor: CandidateDescriptor {
@@ -152,60 +146,55 @@ impl RelayChainInterface for DummyRelayChainInterface {
}
}
fn session_index_for_child(
&self,
_: &cumulus_primitives_core::relay_chain::BlockId,
) -> Result<SessionIndex, sp_api::ApiError> {
async fn session_index_for_child(&self, _: PHash) -> RelayChainResult<SessionIndex> {
Ok(0)
}
fn import_notification_stream(&self) -> sc_client_api::ImportNotifications<PBlock> {
self.relay_client.import_notification_stream()
}
fn finality_notification_stream(&self) -> sc_client_api::FinalityNotifications<PBlock> {
self.relay_client.finality_notification_stream()
}
fn storage_changes_notification_stream(
async fn import_notification_stream(
&self,
filter_keys: Option<&[sc_client_api::StorageKey]>,
child_filter_keys: Option<
&[(sc_client_api::StorageKey, Option<Vec<sc_client_api::StorageKey>>)],
>,
) -> sc_client_api::blockchain::Result<sc_client_api::StorageEventStream<PHash>> {
self.relay_client
.storage_changes_notification_stream(filter_keys, child_filter_keys)
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>> {
Ok(Box::pin(
self.relay_client
.import_notification_stream()
.map(|notification| notification.header),
))
}
fn is_major_syncing(&self) -> bool {
false
async fn finality_notification_stream(
&self,
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>> {
Ok(Box::pin(
self.relay_client
.finality_notification_stream()
.map(|notification| notification.header),
))
}
fn overseer_handle(&self) -> Option<Handle> {
async fn is_major_syncing(&self) -> RelayChainResult<bool> {
Ok(false)
}
fn overseer_handle(&self) -> RelayChainResult<Option<Handle>> {
unimplemented!("Not needed for test")
}
fn get_storage_by_key(
async fn get_storage_by_key(
&self,
_: &polkadot_service::BlockId,
_: PHash,
_: &[u8],
) -> Result<Option<StorageValue>, sp_blockchain::Error> {
) -> RelayChainResult<Option<StorageValue>> {
unimplemented!("Not needed for test")
}
fn prove_read(
async fn prove_read(
&self,
_: &polkadot_service::BlockId,
_: PHash,
_: &Vec<Vec<u8>>,
) -> Result<Option<sc_client_api::StorageProof>, Box<dyn sp_state_machine::Error>> {
) -> RelayChainResult<sc_client_api::StorageProof> {
unimplemented!("Not needed for test")
}
async fn wait_for_block(
&self,
hash: PHash,
) -> Result<(), cumulus_relay_chain_interface::WaitError> {
async fn wait_for_block(&self, hash: PHash) -> RelayChainResult<()> {
let mut listener = match check_block_in_chain(
self.relay_backend.clone(),
self.relay_client.clone(),
@@ -219,16 +208,32 @@ impl RelayChainInterface for DummyRelayChainInterface {
loop {
futures::select! {
_ = timeout => return Err(WaitError::Timeout(hash)),
_ = timeout => return Err(RelayChainError::WaitTimeout(hash)),
evt = listener.next() => match evt {
Some(evt) if evt.hash == hash => return Ok(()),
// Not the event we waited on.
Some(_) => continue,
None => return Err(WaitError::ImportListenerClosed(hash)),
None => return Err(RelayChainError::ImportListenerClosed(hash)),
}
}
}
}
async fn new_best_notification_stream(
&self,
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>> {
let notifications_stream =
self.relay_client
.import_notification_stream()
.filter_map(|notification| async move {
if notification.is_new_best {
Some(notification.header)
} else {
None
}
});
Ok(Box::pin(notifications_stream))
}
}
fn make_validator_and_api(
@@ -272,9 +277,7 @@ async fn make_gossip_message_and_header(
Some(&Sr25519Keyring::Alice.to_seed()),
)
.unwrap();
let session_index = relay_chain_interface
.session_index_for_child(&BlockId::Hash(relay_parent))
.unwrap();
let session_index = relay_chain_interface.session_index_for_child(relay_parent).await.unwrap();
let signing_context = SigningContext { parent_hash: relay_parent, session_index };
let header = default_header();
@@ -442,9 +445,9 @@ fn check_statement_is_correctly_signed() {
assert_eq!(Validation::Failure { disconnect: true }, res.unwrap());
}
#[test]
fn check_statement_seconded() {
let (mut validator, api) = make_validator_and_api();
#[tokio::test]
async fn check_statement_seconded() {
let (mut validator, relay_chain_interface) = make_validator_and_api();
let header = default_header();
let relay_parent = H256::from_low_u64_be(1);
@@ -455,7 +458,7 @@ fn check_statement_seconded() {
Some(&Sr25519Keyring::Alice.to_seed()),
)
.unwrap();
let session_index = api.session_index_for_child(&BlockId::Hash(relay_parent)).unwrap();
let session_index = relay_chain_interface.session_index_for_child(relay_parent).await.unwrap();
let signing_context = SigningContext { parent_hash: relay_parent, session_index };
let statement = Statement::Valid(Default::default());
@@ -16,6 +16,7 @@
use cumulus_primitives_core::ParaId;
use cumulus_test_service::{initial_head_data, run_relay_chain_validator_node, Keyring::*};
use futures::join;
#[substrate_test_utils::test]
#[ignore]
@@ -27,12 +28,24 @@ async fn sync_blocks_from_tip_without_being_connected_to_a_collator() {
let para_id = ParaId::from(100);
let tokio_handle = tokio::runtime::Handle::current();
let ws_port = portpicker::pick_unused_port().expect("No free ports");
// start alice
let alice = run_relay_chain_validator_node(tokio_handle.clone(), Alice, || {}, Vec::new());
let alice = run_relay_chain_validator_node(
tokio_handle.clone(),
Alice,
|| {},
Vec::new(),
Some(ws_port),
);
// start bob
let bob =
run_relay_chain_validator_node(tokio_handle.clone(), Bob, || {}, vec![alice.addr.clone()]);
let bob = run_relay_chain_validator_node(
tokio_handle.clone(),
Bob,
|| {},
vec![alice.addr.clone()],
None,
);
// register parachain
alice
@@ -62,12 +75,21 @@ async fn sync_blocks_from_tip_without_being_connected_to_a_collator() {
.await;
// run eve as parachain full node that is only connected to dave
let eve = cumulus_test_service::TestNodeBuilder::new(para_id, tokio_handle, Eve)
let eve = cumulus_test_service::TestNodeBuilder::new(para_id, tokio_handle.clone(), Eve)
.connect_to_parachain_node(&dave)
.exclusively_connect_to_registered_parachain_nodes()
.connect_to_relay_chain_nodes(vec![&alice, &bob])
.build()
.await;
eve.wait_for_blocks(7).await;
// run eve as parachain full node that is only connected to dave
let ferdie = cumulus_test_service::TestNodeBuilder::new(para_id, tokio_handle, Ferdie)
.connect_to_parachain_node(&dave)
.exclusively_connect_to_registered_parachain_nodes()
.connect_to_relay_chain_nodes(vec![&alice, &bob])
.use_external_relay_chain_node_at_port(ws_port)
.build()
.await;
join!(ferdie.wait_for_blocks(7), eve.wait_for_blocks(7));
}
+20 -21
View File
@@ -6,39 +6,38 @@ description = "Cumulus-specific networking protocol"
edition = "2021"
[dependencies]
# Substrate deps
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-maybe-compressed-blob = { git = "https://github.com/paritytech/substrate", branch = "master" }
codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] }
futures = { version = "0.3.1", features = ["compat"] }
futures-timer = "3.0.2"
rand = "0.8.5"
tracing = "0.1.31"
# Substrate
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-maybe-compressed-blob = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot deps
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Polkadot
polkadot-node-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-overseer = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-subsystem = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-overseer = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus deps
# Cumulus
cumulus-primitives-core = { path = "../../primitives/core" }
cumulus-relay-chain-interface = {path = "../relay-chain-interface"}
# other deps
codec = { package = "parity-scale-codec", version = "2.3.0", features = [ "derive" ] }
futures = { version = "0.3.1", features = ["compat"] }
futures-timer = "3.0.2"
tracing = "0.1.22"
rand = "0.8.3"
[dev-dependencies]
tokio = { version = "1.10", features = ["macros"] }
tokio = { version = "1.17.0", features = ["macros"] }
# Cumulus deps
# Cumulus
cumulus-test-service = { path = "../../test/service" }
# substrate deps
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Substrate
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
+70 -32
View File
@@ -23,8 +23,7 @@
//! several reasons, either a malicious collator that managed to include its own PoV and doesn't want
//! to share it with the rest of the network or maybe a collator went down before it could distribute
//! the block in the network. When something like this happens we can use the PoV recovery algorithm
//! implemented in this crate to recover a PoV and to propagate it with the rest of the network. This
//! protocol is only executed by the collators, to not overwhelm the relay chain validators.
//! implemented in this crate to recover a PoV and to propagate it with the rest of the network.
//!
//! It works in the following way:
//!
@@ -57,7 +56,7 @@ use polkadot_primitives::v1::{
};
use cumulus_primitives_core::ParachainBlockData;
use cumulus_relay_chain_interface::RelayChainInterface;
use cumulus_relay_chain_interface::{RelayChainInterface, RelayChainResult};
use codec::Decode;
use futures::{select, stream::FuturesUnordered, Future, FutureExt, Stream, StreamExt};
@@ -83,6 +82,26 @@ struct PendingCandidate<Block: BlockT> {
block_number: NumberFor<Block>,
}
/// The delay between observing an unknown block and recovering this block.
#[derive(Clone, Copy)]
pub enum RecoveryDelay {
/// Start recovering the block in maximum of the given delay.
WithMax { max: Duration },
/// Start recovering the block after at least `min` delay and in maximum `max` delay.
WithMinAndMax { min: Duration, max: Duration },
}
impl RecoveryDelay {
/// Return as [`Delay`].
fn as_delay(self) -> Delay {
match self {
Self::WithMax { max } => Delay::new(max.mul_f64(thread_rng().gen())),
Self::WithMinAndMax { min, max } =>
Delay::new(min + max.saturating_sub(min).mul_f64(thread_rng().gen())),
}
}
}
/// Encapsulates the logic of the pov recovery.
pub struct PoVRecovery<Block: BlockT, PC, IQ, RC> {
/// All the pending candidates that we are waiting for to be imported or that need to be
@@ -98,7 +117,7 @@ pub struct PoVRecovery<Block: BlockT, PC, IQ, RC> {
///
/// Uses parent -> blocks mapping.
waiting_for_parent: HashMap<Block::Hash, Vec<Block>>,
relay_chain_slot_duration: Duration,
recovery_delay: RecoveryDelay,
parachain_client: Arc<PC>,
parachain_import_queue: IQ,
relay_chain_interface: RC,
@@ -114,7 +133,7 @@ where
/// Create a new instance.
pub fn new(
overseer_handle: OverseerHandle,
relay_chain_slot_duration: Duration,
recovery_delay: RecoveryDelay,
parachain_client: Arc<PC>,
parachain_import_queue: IQ,
relay_chain_interface: RCInterface,
@@ -124,7 +143,7 @@ where
pending_candidates: HashMap::new(),
next_candidate_to_recover: Default::default(),
active_candidate_recovery: ActiveCandidateRecovery::new(overseer_handle),
relay_chain_slot_duration,
recovery_delay,
waiting_for_parent: HashMap::new(),
parachain_client,
parachain_import_queue,
@@ -186,9 +205,8 @@ where
return
}
// Wait some random time, with the maximum being the slot duration of the relay chain
// before we start to recover the candidate.
let delay = Delay::new(self.relay_chain_slot_duration.mul_f64(thread_rng().gen()));
// Delay the recovery by some random time to not spam the relay chain.
let delay = self.recovery_delay.as_delay();
self.next_candidate_to_recover.push(
async move {
delay.await;
@@ -363,7 +381,14 @@ where
let mut imported_blocks = self.parachain_client.import_notification_stream().fuse();
let mut finalized_blocks = self.parachain_client.finality_notification_stream().fuse();
let pending_candidates =
pending_candidates(self.relay_chain_interface.clone(), self.para_id).fuse();
match pending_candidates(self.relay_chain_interface.clone(), self.para_id).await {
Ok(pending_candidate_stream) => pending_candidate_stream.fuse(),
Err(err) => {
tracing::error!(target: LOG_TARGET, error = ?err, "Unable to retrieve pending candidate stream.");
return
},
};
futures::pin_mut!(pending_candidates);
loop {
@@ -417,28 +442,41 @@ where
}
/// Returns a stream over pending candidates for the parachain corresponding to `para_id`.
fn pending_candidates(
relay_chain_client: impl RelayChainInterface,
async fn pending_candidates(
relay_chain_client: impl RelayChainInterface + Clone,
para_id: ParaId,
) -> impl Stream<Item = (CommittedCandidateReceipt, SessionIndex)> {
relay_chain_client.import_notification_stream().filter_map(move |n| {
let res = relay_chain_client
.candidate_pending_availability(&BlockId::hash(n.hash), para_id)
.and_then(|pa| {
relay_chain_client
.session_index_for_child(&BlockId::hash(n.hash))
.map(|v| pa.map(|pa| (pa, v)))
})
.map_err(|e| {
tracing::error!(
target: LOG_TARGET,
error = ?e,
"Failed fetch pending candidates.",
)
})
.ok()
.flatten();
) -> RelayChainResult<impl Stream<Item = (CommittedCandidateReceipt, SessionIndex)>> {
let import_notification_stream = relay_chain_client.import_notification_stream().await?;
async move { res }
})
let filtered_stream = import_notification_stream.filter_map(move |n| {
let client_for_closure = relay_chain_client.clone();
async move {
let hash = n.hash();
let pending_availability_result = client_for_closure
.candidate_pending_availability(hash, para_id)
.await
.map_err(|e| {
tracing::error!(
target: LOG_TARGET,
error = ?e,
"Failed to fetch pending candidates.",
)
});
let session_index_result =
client_for_closure.session_index_for_child(hash).await.map_err(|e| {
tracing::error!(
target: LOG_TARGET,
error = ?e,
"Failed to fetch session index.",
)
});
if let Ok(Some(candidate)) = pending_availability_result {
session_index_result.map(|session_index| (candidate, session_index)).ok()
} else {
None
}
}
});
Ok(filtered_stream)
}
+21 -4
View File
@@ -39,6 +39,7 @@ async fn pov_recovery() {
Alice,
|| {},
Vec::new(),
None,
);
// Start bob
@@ -47,6 +48,7 @@ async fn pov_recovery() {
Bob,
|| {},
vec![alice.addr.clone()],
None,
);
// Register parachain
@@ -73,16 +75,31 @@ async fn pov_recovery() {
.build()
.await;
// Run dave as parachain full node
// Run dave as parachain collator and eve as parachain full node
//
// It will need to recover the pov blocks through availability recovery.
let dave = cumulus_test_service::TestNodeBuilder::new(para_id, tokio_handle, Dave)
// They will need to recover the pov blocks through availability recovery.
let dave = cumulus_test_service::TestNodeBuilder::new(para_id, tokio_handle.clone(), Dave)
.enable_collator()
.use_null_consensus()
.connect_to_parachain_node(&charlie)
.connect_to_relay_chain_nodes(vec![&alice, &bob])
.wrap_announce_block(|_| {
// Never announce any block
Arc::new(|_, _| {})
})
.build()
.await;
dave.wait_for_blocks(7).await;
let eve = cumulus_test_service::TestNodeBuilder::new(para_id, tokio_handle, Eve)
.use_null_consensus()
.connect_to_parachain_node(&charlie)
.connect_to_relay_chain_nodes(vec![&alice, &bob])
.wrap_announce_block(|_| {
// Never announce any block
Arc::new(|_, _| {})
})
.build()
.await;
futures::future::join(dave.wait_for_blocks(7), eve.wait_for_blocks(7)).await;
}
@@ -1,43 +1,46 @@
[package]
authors = ["Parity Technologies <admin@parity.io>"]
name = "cumulus-relay-chain-local"
name = "cumulus-relay-chain-inprocess-interface"
version = "0.1.0"
edition = "2021"
[dependencies]
polkadot-client = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
cumulus-primitives-core = { path = "../../primitives/core" }
cumulus-relay-chain-interface = { path = "../relay-chain-interface" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
async-trait = "0.1.52"
futures = "0.3.21"
futures-timer = "3.0.2"
parking_lot = "0.12.0"
tracing = "0.1.31"
# Substrate
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
parking_lot = "0.11.1"
tracing = "0.1.25"
async-trait = "0.1.52"
futures = { version = "0.3.1", features = ["compat"] }
futures-timer = "3.0.2"
# Polkadot
polkadot-client = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus
cumulus-primitives-core = { path = "../../primitives/core" }
cumulus-relay-chain-interface = { path = "../relay-chain-interface" }
[dev-dependencies]
# Cumulus deps
cumulus-test-service = { path = "../../test/service" }
# Polkadot deps
polkadot-test-client = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# substrate deps
# Substrate
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-test-client = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus
cumulus-test-service = { path = "../../test/service" }
@@ -14,19 +14,19 @@
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
use std::{sync::Arc, time::Duration};
use std::{pin::Pin, sync::Arc, time::Duration};
use async_trait::async_trait;
use cumulus_primitives_core::{
relay_chain::{
v1::{CommittedCandidateReceipt, OccupiedCoreAssumption, SessionIndex, ValidatorId},
v2::ParachainHost,
Block as PBlock, BlockId, Hash as PHash, InboundHrmpMessage,
Block as PBlock, BlockId, Hash as PHash, Header as PHeader, InboundHrmpMessage,
},
InboundDownwardMessage, ParaId, PersistedValidationData,
};
use cumulus_relay_chain_interface::{RelayChainInterface, WaitError};
use futures::{FutureExt, StreamExt};
use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface, RelayChainResult};
use futures::{FutureExt, Stream, StreamExt};
use parking_lot::Mutex;
use polkadot_client::{ClientHandle, ExecuteWithClient, FullBackend};
use polkadot_service::{
@@ -37,25 +37,24 @@ use sc_client_api::{
StorageProof, UsageProvider,
};
use sc_telemetry::TelemetryWorkerHandle;
use sp_api::{ApiError, ProvideRuntimeApi};
use sp_api::ProvideRuntimeApi;
use sp_consensus::SyncOracle;
use sp_core::{sp_std::collections::btree_map::BTreeMap, Pair};
use sp_state_machine::{Backend as StateBackend, StorageValue};
const LOG_TARGET: &str = "relay-chain-local";
/// The timeout in seconds after that the waiting for a block should be aborted.
const TIMEOUT_IN_SECONDS: u64 = 6;
/// Provides an implementation of the [`RelayChainInterface`] using a local in-process relay chain node.
pub struct RelayChainLocal<Client> {
pub struct RelayChainInProcessInterface<Client> {
full_client: Arc<Client>,
backend: Arc<FullBackend>,
sync_oracle: Arc<Mutex<Box<dyn SyncOracle + Send + Sync>>>,
overseer_handle: Option<Handle>,
}
impl<Client> RelayChainLocal<Client> {
/// Create a new instance of [`RelayChainLocal`]
impl<Client> RelayChainInProcessInterface<Client> {
/// Create a new instance of [`RelayChainInProcessInterface`]
pub fn new(
full_client: Arc<Client>,
backend: Arc<FullBackend>,
@@ -66,7 +65,7 @@ impl<Client> RelayChainLocal<Client> {
}
}
impl<T> Clone for RelayChainLocal<T> {
impl<T> Clone for RelayChainInProcessInterface<T> {
fn clone(&self) -> Self {
Self {
full_client: self.full_client.clone(),
@@ -78,7 +77,7 @@ impl<T> Clone for RelayChainLocal<T> {
}
#[async_trait]
impl<Client> RelayChainInterface for RelayChainLocal<Client>
impl<Client> RelayChainInterface for RelayChainInProcessInterface<Client>
where
Client: ProvideRuntimeApi<PBlock>
+ BlockchainEvents<PBlock>
@@ -88,158 +87,115 @@ where
+ Send,
Client::Api: ParachainHost<PBlock> + BabeApi<PBlock>,
{
fn retrieve_dmq_contents(
async fn retrieve_dmq_contents(
&self,
para_id: ParaId,
relay_parent: PHash,
) -> Option<Vec<InboundDownwardMessage>> {
self.full_client
.runtime_api()
.dmq_contents_with_context(
&BlockId::hash(relay_parent),
sp_core::ExecutionContext::Importing,
para_id,
)
.map_err(|e| {
tracing::error!(
target: LOG_TARGET,
relay_parent = ?relay_parent,
error = ?e,
"An error occured during requesting the downward messages.",
);
})
.ok()
) -> RelayChainResult<Vec<InboundDownwardMessage>> {
Ok(self.full_client.runtime_api().dmq_contents_with_context(
&BlockId::hash(relay_parent),
sp_core::ExecutionContext::Importing,
para_id,
)?)
}
fn retrieve_all_inbound_hrmp_channel_contents(
async fn retrieve_all_inbound_hrmp_channel_contents(
&self,
para_id: ParaId,
relay_parent: PHash,
) -> Option<BTreeMap<ParaId, Vec<InboundHrmpMessage>>> {
self.full_client
.runtime_api()
.inbound_hrmp_channels_contents_with_context(
&BlockId::hash(relay_parent),
sp_core::ExecutionContext::Importing,
para_id,
)
.map_err(|e| {
tracing::error!(
target: LOG_TARGET,
relay_parent = ?relay_parent,
error = ?e,
"An error occured during requesting the inbound HRMP messages.",
);
})
.ok()
) -> RelayChainResult<BTreeMap<ParaId, Vec<InboundHrmpMessage>>> {
Ok(self.full_client.runtime_api().inbound_hrmp_channels_contents_with_context(
&BlockId::hash(relay_parent),
sp_core::ExecutionContext::Importing,
para_id,
)?)
}
fn persisted_validation_data(
async fn persisted_validation_data(
&self,
block_id: &BlockId,
hash: PHash,
para_id: ParaId,
occupied_core_assumption: OccupiedCoreAssumption,
) -> Result<Option<PersistedValidationData>, ApiError> {
self.full_client.runtime_api().persisted_validation_data(
block_id,
) -> RelayChainResult<Option<PersistedValidationData>> {
Ok(self.full_client.runtime_api().persisted_validation_data(
&BlockId::Hash(hash),
para_id,
occupied_core_assumption,
)
)?)
}
fn candidate_pending_availability(
async fn candidate_pending_availability(
&self,
block_id: &BlockId,
hash: PHash,
para_id: ParaId,
) -> Result<Option<CommittedCandidateReceipt>, ApiError> {
self.full_client.runtime_api().candidate_pending_availability(block_id, para_id)
) -> RelayChainResult<Option<CommittedCandidateReceipt>> {
Ok(self
.full_client
.runtime_api()
.candidate_pending_availability(&BlockId::Hash(hash), para_id)?)
}
fn session_index_for_child(&self, block_id: &BlockId) -> Result<SessionIndex, ApiError> {
self.full_client.runtime_api().session_index_for_child(block_id)
async fn session_index_for_child(&self, hash: PHash) -> RelayChainResult<SessionIndex> {
Ok(self.full_client.runtime_api().session_index_for_child(&BlockId::Hash(hash))?)
}
fn validators(&self, block_id: &BlockId) -> Result<Vec<ValidatorId>, ApiError> {
self.full_client.runtime_api().validators(block_id)
async fn validators(&self, hash: PHash) -> RelayChainResult<Vec<ValidatorId>> {
Ok(self.full_client.runtime_api().validators(&BlockId::Hash(hash))?)
}
fn import_notification_stream(&self) -> sc_client_api::ImportNotifications<PBlock> {
self.full_client.import_notification_stream()
}
fn finality_notification_stream(&self) -> sc_client_api::FinalityNotifications<PBlock> {
self.full_client.finality_notification_stream()
}
fn storage_changes_notification_stream(
async fn import_notification_stream(
&self,
filter_keys: Option<&[sc_client_api::StorageKey]>,
child_filter_keys: Option<
&[(sc_client_api::StorageKey, Option<Vec<sc_client_api::StorageKey>>)],
>,
) -> sc_client_api::blockchain::Result<sc_client_api::StorageEventStream<PHash>> {
self.full_client
.storage_changes_notification_stream(filter_keys, child_filter_keys)
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>> {
let notification_stream = self
.full_client
.import_notification_stream()
.map(|notification| notification.header);
Ok(Box::pin(notification_stream))
}
fn best_block_hash(&self) -> PHash {
self.backend.blockchain().info().best_hash
async fn finality_notification_stream(
&self,
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>> {
let notification_stream = self
.full_client
.finality_notification_stream()
.map(|notification| notification.header);
Ok(Box::pin(notification_stream))
}
fn block_status(&self, block_id: BlockId) -> Result<BlockStatus, sp_blockchain::Error> {
self.backend.blockchain().status(block_id)
async fn best_block_hash(&self) -> RelayChainResult<PHash> {
Ok(self.backend.blockchain().info().best_hash)
}
fn is_major_syncing(&self) -> bool {
async fn is_major_syncing(&self) -> RelayChainResult<bool> {
let mut network = self.sync_oracle.lock();
network.is_major_syncing()
Ok(network.is_major_syncing())
}
fn overseer_handle(&self) -> Option<Handle> {
self.overseer_handle.clone()
fn overseer_handle(&self) -> RelayChainResult<Option<Handle>> {
Ok(self.overseer_handle.clone())
}
fn get_storage_by_key(
async fn get_storage_by_key(
&self,
block_id: &BlockId,
relay_parent: PHash,
key: &[u8],
) -> Result<Option<StorageValue>, sp_blockchain::Error> {
let state = self.backend.state_at(*block_id)?;
state.storage(key).map_err(sp_blockchain::Error::Storage)
) -> RelayChainResult<Option<StorageValue>> {
let block_id = BlockId::Hash(relay_parent);
let state = self.backend.state_at(block_id)?;
state.storage(key).map_err(RelayChainError::GenericError)
}
fn prove_read(
async fn prove_read(
&self,
block_id: &BlockId,
relay_parent: PHash,
relevant_keys: &Vec<Vec<u8>>,
) -> Result<Option<StorageProof>, Box<dyn sp_state_machine::Error>> {
let state_backend = self
.backend
.state_at(*block_id)
.map_err(|e| {
tracing::error!(
target: LOG_TARGET,
relay_parent = ?block_id,
error = ?e,
"Cannot obtain the state of the relay chain.",
);
})
.ok();
) -> RelayChainResult<StorageProof> {
let block_id = BlockId::Hash(relay_parent);
let state_backend = self.backend.state_at(block_id)?;
match state_backend {
Some(state) => sp_state_machine::prove_read(state, relevant_keys)
.map_err(|e| {
tracing::error!(
target: LOG_TARGET,
relay_parent = ?block_id,
error = ?e,
"Failed to collect required relay chain state storage proof.",
);
e
})
.map(Some),
None => Ok(None),
}
sp_state_machine::prove_read(state_backend, relevant_keys)
.map_err(RelayChainError::StateMachineError)
}
/// Wait for a given relay chain block in an async way.
@@ -259,7 +215,7 @@ where
///
/// The timeout is set to 6 seconds. This should be enough time to import the block in the current
/// round and if not, the new round of the relay chain already started anyway.
async fn wait_for_block(&self, hash: PHash) -> Result<(), WaitError> {
async fn wait_for_block(&self, hash: PHash) -> RelayChainResult<()> {
let mut listener =
match check_block_in_chain(self.backend.clone(), self.full_client.clone(), hash)? {
BlockCheckStatus::InChain => return Ok(()),
@@ -270,16 +226,28 @@ where
loop {
futures::select! {
_ = timeout => return Err(WaitError::Timeout(hash)),
_ = timeout => return Err(RelayChainError::WaitTimeout(hash)),
evt = listener.next() => match evt {
Some(evt) if evt.hash == hash => return Ok(()),
// Not the event we waited on.
Some(_) => continue,
None => return Err(WaitError::ImportListenerClosed(hash)),
None => return Err(RelayChainError::ImportListenerClosed(hash)),
}
}
}
}
async fn new_best_notification_stream(
&self,
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>> {
let notifications_stream =
self.full_client
.import_notification_stream()
.filter_map(|notification| async move {
notification.is_new_best.then(|| notification.header)
});
Ok(Box::pin(notifications_stream))
}
}
pub enum BlockCheckStatus {
@@ -294,17 +262,16 @@ pub fn check_block_in_chain<Client>(
backend: Arc<FullBackend>,
client: Arc<Client>,
hash: PHash,
) -> Result<BlockCheckStatus, WaitError>
) -> RelayChainResult<BlockCheckStatus>
where
Client: BlockchainEvents<PBlock>,
{
let _lock = backend.get_import_lock().read();
let block_id = BlockId::Hash(hash);
match backend.blockchain().status(block_id) {
Ok(BlockStatus::InChain) => return Ok(BlockCheckStatus::InChain),
Err(err) => return Err(WaitError::BlockchainError(hash, err)),
_ => {},
if backend.blockchain().status(block_id)? == BlockStatus::InChain {
return Ok(BlockCheckStatus::InChain)
}
let listener = client.import_notification_stream();
@@ -313,25 +280,25 @@ where
}
/// Builder for a concrete relay chain interface, created from a full node. Builds
/// a [`RelayChainLocal`] to access relay chain data necessary for parachain operation.
/// a [`RelayChainInProcessInterface`] to access relay chain data necessary for parachain operation.
///
/// The builder takes a [`polkadot_client::Client`]
/// that wraps a concrete instance. By using [`polkadot_client::ExecuteWithClient`]
/// the builder gets access to this concrete instance and instantiates a [`RelayChainLocal`] with it.
struct RelayChainLocalBuilder {
/// the builder gets access to this concrete instance and instantiates a [`RelayChainInProcessInterface`] with it.
struct RelayChainInProcessInterfaceBuilder {
polkadot_client: polkadot_client::Client,
backend: Arc<FullBackend>,
sync_oracle: Arc<Mutex<Box<dyn SyncOracle + Send + Sync>>>,
overseer_handle: Option<Handle>,
}
impl RelayChainLocalBuilder {
impl RelayChainInProcessInterfaceBuilder {
pub fn build(self) -> Arc<dyn RelayChainInterface> {
self.polkadot_client.clone().execute_with(self)
}
}
impl ExecuteWithClient for RelayChainLocalBuilder {
impl ExecuteWithClient for RelayChainInProcessInterfaceBuilder {
type Output = Arc<dyn RelayChainInterface>;
fn execute_with_client<Client, Api, Backend>(self, client: Arc<Client>) -> Self::Output
@@ -345,7 +312,12 @@ impl ExecuteWithClient for RelayChainLocalBuilder {
+ Send,
Client::Api: ParachainHost<PBlock> + BabeApi<PBlock>,
{
Arc::new(RelayChainLocal::new(client, self.backend, self.sync_oracle, self.overseer_handle))
Arc::new(RelayChainInProcessInterface::new(
client,
self.backend,
self.sync_oracle,
self.overseer_handle,
))
}
}
@@ -353,50 +325,54 @@ impl ExecuteWithClient for RelayChainLocalBuilder {
#[sc_tracing::logging::prefix_logs_with("Relaychain")]
fn build_polkadot_full_node(
config: Configuration,
parachain_config: &Configuration,
telemetry_worker_handle: Option<TelemetryWorkerHandle>,
) -> Result<(NewFull<polkadot_client::Client>, CollatorPair), polkadot_service::Error> {
) -> Result<(NewFull<polkadot_client::Client>, Option<CollatorPair>), polkadot_service::Error> {
let is_light = matches!(config.role, Role::Light);
if is_light {
Err(polkadot_service::Error::Sub("Light client not supported.".into()))
} else {
let collator_key = CollatorPair::generate().0;
let (is_collator, maybe_collator_key) = if parachain_config.role.is_authority() {
let collator_key = CollatorPair::generate().0;
(polkadot_service::IsCollator::Yes(collator_key.clone()), Some(collator_key))
} else {
(polkadot_service::IsCollator::No, None)
};
let relay_chain_full_node = polkadot_service::build_full(
config,
polkadot_service::IsCollator::Yes(collator_key.clone()),
is_collator,
None,
true,
None,
telemetry_worker_handle,
true,
polkadot_service::RealOverseerGen,
)?;
Ok((relay_chain_full_node, collator_key))
Ok((relay_chain_full_node, maybe_collator_key))
}
}
/// Builds a relay chain interface by constructing a full relay chain node
pub fn build_relay_chain_interface(
pub fn build_inprocess_relay_chain(
polkadot_config: Configuration,
parachain_config: &Configuration,
telemetry_worker_handle: Option<TelemetryWorkerHandle>,
task_manager: &mut TaskManager,
) -> Result<(Arc<(dyn RelayChainInterface + 'static)>, CollatorPair), polkadot_service::Error> {
) -> RelayChainResult<(Arc<(dyn RelayChainInterface + 'static)>, Option<CollatorPair>)> {
let (full_node, collator_key) =
build_polkadot_full_node(polkadot_config, telemetry_worker_handle).map_err(
|e| match e {
polkadot_service::Error::Sub(x) => x,
s => format!("{}", s).into(),
},
)?;
build_polkadot_full_node(polkadot_config, parachain_config, telemetry_worker_handle)?;
let sync_oracle: Box<dyn SyncOracle + Send + Sync> = Box::new(full_node.network.clone());
let sync_oracle = Arc::new(Mutex::new(sync_oracle));
let relay_chain_interface_builder = RelayChainLocalBuilder {
let relay_chain_interface_builder = RelayChainInProcessInterfaceBuilder {
polkadot_client: full_node.client.clone(),
backend: full_node.backend.clone(),
sync_oracle,
overseer_handle: full_node.overseer_handle.clone(),
};
task_manager.add_child(full_node.task_manager);
Ok((relay_chain_interface_builder.build(), collator_key))
@@ -432,7 +408,8 @@ mod tests {
}
}
fn build_client_backend_and_block() -> (Arc<Client>, PBlock, RelayChainLocal<Client>) {
fn build_client_backend_and_block(
) -> (Arc<Client>, PBlock, RelayChainInProcessInterface<Client>) {
let builder =
TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::NativeWhenPossible);
let backend = builder.backend();
@@ -445,7 +422,7 @@ mod tests {
(
client.clone(),
block,
RelayChainLocal::new(
RelayChainInProcessInterface::new(
client,
backend.clone(),
Arc::new(Mutex::new(dummy_network)),
@@ -495,7 +472,7 @@ mod tests {
assert!(matches!(
block_on(relay_chain_interface.wait_for_block(hash)),
Err(WaitError::Timeout(_))
Err(RelayChainError::WaitTimeout(_))
));
}
+7 -1
View File
@@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
polkadot-overseer = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
cumulus-primitives-core = { path = "../../primitives/core" }
@@ -15,7 +16,12 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
parking_lot = "0.11.1"
futures = "0.3.21"
parking_lot = "0.12.0"
derive_more = "0.99.2"
async-trait = "0.1.52"
thiserror = "1.0.30"
jsonrpsee-core = "0.9.0"
parity-scale-codec = "3.0.0"
+117 -102
View File
@@ -14,136 +14,153 @@
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
use std::{collections::BTreeMap, sync::Arc};
use std::{collections::BTreeMap, pin::Pin, sync::Arc};
use cumulus_primitives_core::{
relay_chain::{
v1::{CommittedCandidateReceipt, OccupiedCoreAssumption, SessionIndex, ValidatorId},
Block as PBlock, BlockId, Hash as PHash, InboundHrmpMessage,
Hash as PHash, Header as PHeader, InboundHrmpMessage,
},
InboundDownwardMessage, ParaId, PersistedValidationData,
};
use polkadot_overseer::Handle as OverseerHandle;
use sc_client_api::{blockchain::BlockStatus, StorageProof};
use sc_client_api::StorageProof;
use futures::Stream;
use async_trait::async_trait;
use jsonrpsee_core::Error as JsonRPSeeError;
use parity_scale_codec::Error as CodecError;
use sp_api::ApiError;
use sp_state_machine::StorageValue;
use async_trait::async_trait;
pub type RelayChainResult<T> = Result<T, RelayChainError>;
#[derive(Debug, derive_more::Display)]
pub enum WaitError {
#[display(fmt = "Timeout while waiting for relay-chain block `{}` to be imported.", _0)]
Timeout(PHash),
#[display(
fmt = "Import listener closed while waiting for relay-chain block `{}` to be imported.",
_0
)]
#[derive(thiserror::Error, Debug)]
pub enum RelayChainError {
#[error("Error occured while calling relay chain runtime: {0}")]
ApiError(#[from] ApiError),
#[error("Timeout while waiting for relay-chain block `{0}` to be imported.")]
WaitTimeout(PHash),
#[error("Import listener closed while waiting for relay-chain block `{0}` to be imported.")]
ImportListenerClosed(PHash),
#[display(
fmt = "Blockchain returned an error while waiting for relay-chain block `{}` to be imported: {:?}",
_0,
_1
)]
BlockchainError(PHash, sp_blockchain::Error),
#[error("Blockchain returned an error while waiting for relay-chain block `{0}` to be imported: {1}")]
WaitBlockchainError(PHash, sp_blockchain::Error),
#[error("Blockchain returned an error: {0}")]
BlockchainError(#[from] sp_blockchain::Error),
#[error("State machine error occured: {0}")]
StateMachineError(Box<dyn sp_state_machine::Error>),
#[error("Unable to call RPC method '{0}' due to error: {1}")]
RPCCallError(String, JsonRPSeeError),
#[error("RPC Error: '{0}'")]
JsonRPCError(#[from] JsonRPSeeError),
#[error("Scale codec deserialization error: {0}")]
DeserializationError(CodecError),
#[error("Scale codec deserialization error: {0}")]
ServiceError(#[from] polkadot_service::Error),
#[error("Unspecified error occured: {0}")]
GenericError(String),
}
impl From<CodecError> for RelayChainError {
fn from(e: CodecError) -> Self {
RelayChainError::DeserializationError(e)
}
}
/// Trait that provides all necessary methods for interaction between collator and relay chain.
#[async_trait]
pub trait RelayChainInterface: Send + Sync {
/// Fetch a storage item by key.
fn get_storage_by_key(
async fn get_storage_by_key(
&self,
block_id: &BlockId,
relay_parent: PHash,
key: &[u8],
) -> Result<Option<StorageValue>, sp_blockchain::Error>;
) -> RelayChainResult<Option<StorageValue>>;
/// Fetch a vector of current validators.
fn validators(&self, block_id: &BlockId) -> Result<Vec<ValidatorId>, ApiError>;
/// Get the status of a given block.
fn block_status(&self, block_id: BlockId) -> Result<BlockStatus, sp_blockchain::Error>;
async fn validators(&self, block_id: PHash) -> RelayChainResult<Vec<ValidatorId>>;
/// Get the hash of the current best block.
fn best_block_hash(&self) -> PHash;
async fn best_block_hash(&self) -> RelayChainResult<PHash>;
/// Returns the whole contents of the downward message queue for the parachain we are collating
/// for.
///
/// Returns `None` in case of an error.
fn retrieve_dmq_contents(
async fn retrieve_dmq_contents(
&self,
para_id: ParaId,
relay_parent: PHash,
) -> Option<Vec<InboundDownwardMessage>>;
) -> RelayChainResult<Vec<InboundDownwardMessage>>;
/// Returns channels contents for each inbound HRMP channel addressed to the parachain we are
/// collating for.
///
/// Empty channels are also included.
fn retrieve_all_inbound_hrmp_channel_contents(
async fn retrieve_all_inbound_hrmp_channel_contents(
&self,
para_id: ParaId,
relay_parent: PHash,
) -> Option<BTreeMap<ParaId, Vec<InboundHrmpMessage>>>;
) -> RelayChainResult<BTreeMap<ParaId, Vec<InboundHrmpMessage>>>;
/// Yields the persisted validation data for the given `ParaId` along with an assumption that
/// should be used if the para currently occupies a core.
///
/// Returns `None` if either the para is not registered or the assumption is `Freed`
/// and the para already occupies a core.
fn persisted_validation_data(
async fn persisted_validation_data(
&self,
block_id: &BlockId,
block_id: PHash,
para_id: ParaId,
_: OccupiedCoreAssumption,
) -> Result<Option<PersistedValidationData>, ApiError>;
) -> RelayChainResult<Option<PersistedValidationData>>;
/// Get the receipt of a candidate pending availability. This returns `Some` for any paras
/// assigned to occupied cores in `availability_cores` and `None` otherwise.
fn candidate_pending_availability(
async fn candidate_pending_availability(
&self,
block_id: &BlockId,
block_id: PHash,
para_id: ParaId,
) -> Result<Option<CommittedCandidateReceipt>, ApiError>;
) -> RelayChainResult<Option<CommittedCandidateReceipt>>;
/// Returns the session index expected at a child of the block.
fn session_index_for_child(&self, block_id: &BlockId) -> Result<SessionIndex, ApiError>;
async fn session_index_for_child(&self, block_id: PHash) -> RelayChainResult<SessionIndex>;
/// Get a stream of import block notifications.
fn import_notification_stream(&self) -> sc_client_api::ImportNotifications<PBlock>;
async fn import_notification_stream(
&self,
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>>;
/// Get a stream of new best block notifications.
async fn new_best_notification_stream(
&self,
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>>;
/// Wait for a block with a given hash in the relay chain.
///
/// This method returns immediately on error or if the block is already
/// reported to be in chain. Otherwise, it waits for the block to arrive.
async fn wait_for_block(&self, hash: PHash) -> Result<(), WaitError>;
async fn wait_for_block(&self, hash: PHash) -> RelayChainResult<()>;
/// Get a stream of finality notifications.
fn finality_notification_stream(&self) -> sc_client_api::FinalityNotifications<PBlock>;
/// Get a stream of storage change notifications.
fn storage_changes_notification_stream(
async fn finality_notification_stream(
&self,
filter_keys: Option<&[sc_client_api::StorageKey]>,
child_filter_keys: Option<
&[(sc_client_api::StorageKey, Option<Vec<sc_client_api::StorageKey>>)],
>,
) -> sc_client_api::blockchain::Result<sc_client_api::StorageEventStream<PHash>>;
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>>;
/// Whether the synchronization service is undergoing major sync.
/// Returns true if so.
fn is_major_syncing(&self) -> bool;
async fn is_major_syncing(&self) -> RelayChainResult<bool>;
/// Get a handle to the overseer.
fn overseer_handle(&self) -> Option<OverseerHandle>;
fn overseer_handle(&self) -> RelayChainResult<Option<OverseerHandle>>;
/// Generate a storage read proof.
fn prove_read(
async fn prove_read(
&self,
block_id: &BlockId,
relay_parent: PHash,
relevant_keys: &Vec<Vec<u8>>,
) -> Result<Option<StorageProof>, Box<dyn sp_state_machine::Error>>;
) -> RelayChainResult<StorageProof>;
}
#[async_trait]
@@ -151,98 +168,96 @@ impl<T> RelayChainInterface for Arc<T>
where
T: RelayChainInterface + ?Sized,
{
fn retrieve_dmq_contents(
async fn retrieve_dmq_contents(
&self,
para_id: ParaId,
relay_parent: PHash,
) -> Option<Vec<InboundDownwardMessage>> {
(**self).retrieve_dmq_contents(para_id, relay_parent)
) -> RelayChainResult<Vec<InboundDownwardMessage>> {
(**self).retrieve_dmq_contents(para_id, relay_parent).await
}
fn retrieve_all_inbound_hrmp_channel_contents(
async fn retrieve_all_inbound_hrmp_channel_contents(
&self,
para_id: ParaId,
relay_parent: PHash,
) -> Option<BTreeMap<ParaId, Vec<InboundHrmpMessage>>> {
(**self).retrieve_all_inbound_hrmp_channel_contents(para_id, relay_parent)
) -> RelayChainResult<BTreeMap<ParaId, Vec<InboundHrmpMessage>>> {
(**self).retrieve_all_inbound_hrmp_channel_contents(para_id, relay_parent).await
}
fn persisted_validation_data(
async fn persisted_validation_data(
&self,
block_id: &BlockId,
block_id: PHash,
para_id: ParaId,
occupied_core_assumption: OccupiedCoreAssumption,
) -> Result<Option<PersistedValidationData>, ApiError> {
(**self).persisted_validation_data(block_id, para_id, occupied_core_assumption)
) -> RelayChainResult<Option<PersistedValidationData>> {
(**self)
.persisted_validation_data(block_id, para_id, occupied_core_assumption)
.await
}
fn candidate_pending_availability(
async fn candidate_pending_availability(
&self,
block_id: &BlockId,
block_id: PHash,
para_id: ParaId,
) -> Result<Option<CommittedCandidateReceipt>, ApiError> {
(**self).candidate_pending_availability(block_id, para_id)
) -> RelayChainResult<Option<CommittedCandidateReceipt>> {
(**self).candidate_pending_availability(block_id, para_id).await
}
fn session_index_for_child(&self, block_id: &BlockId) -> Result<SessionIndex, ApiError> {
(**self).session_index_for_child(block_id)
async fn session_index_for_child(&self, block_id: PHash) -> RelayChainResult<SessionIndex> {
(**self).session_index_for_child(block_id).await
}
fn validators(&self, block_id: &BlockId) -> Result<Vec<ValidatorId>, ApiError> {
(**self).validators(block_id)
async fn validators(&self, block_id: PHash) -> RelayChainResult<Vec<ValidatorId>> {
(**self).validators(block_id).await
}
fn import_notification_stream(&self) -> sc_client_api::ImportNotifications<PBlock> {
(**self).import_notification_stream()
}
fn finality_notification_stream(&self) -> sc_client_api::FinalityNotifications<PBlock> {
(**self).finality_notification_stream()
}
fn storage_changes_notification_stream(
async fn import_notification_stream(
&self,
filter_keys: Option<&[sc_client_api::StorageKey]>,
child_filter_keys: Option<
&[(sc_client_api::StorageKey, Option<Vec<sc_client_api::StorageKey>>)],
>,
) -> sc_client_api::blockchain::Result<sc_client_api::StorageEventStream<PHash>> {
(**self).storage_changes_notification_stream(filter_keys, child_filter_keys)
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>> {
(**self).import_notification_stream().await
}
fn best_block_hash(&self) -> PHash {
(**self).best_block_hash()
async fn finality_notification_stream(
&self,
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>> {
(**self).finality_notification_stream().await
}
fn block_status(&self, block_id: BlockId) -> Result<BlockStatus, sp_blockchain::Error> {
(**self).block_status(block_id)
async fn best_block_hash(&self) -> RelayChainResult<PHash> {
(**self).best_block_hash().await
}
fn is_major_syncing(&self) -> bool {
(**self).is_major_syncing()
async fn is_major_syncing(&self) -> RelayChainResult<bool> {
(**self).is_major_syncing().await
}
fn overseer_handle(&self) -> Option<OverseerHandle> {
fn overseer_handle(&self) -> RelayChainResult<Option<OverseerHandle>> {
(**self).overseer_handle()
}
fn get_storage_by_key(
async fn get_storage_by_key(
&self,
block_id: &BlockId,
relay_parent: PHash,
key: &[u8],
) -> Result<Option<StorageValue>, sp_blockchain::Error> {
(**self).get_storage_by_key(block_id, key)
) -> RelayChainResult<Option<StorageValue>> {
(**self).get_storage_by_key(relay_parent, key).await
}
fn prove_read(
async fn prove_read(
&self,
block_id: &BlockId,
relay_parent: PHash,
relevant_keys: &Vec<Vec<u8>>,
) -> Result<Option<StorageProof>, Box<dyn sp_state_machine::Error>> {
(**self).prove_read(block_id, relevant_keys)
) -> RelayChainResult<StorageProof> {
(**self).prove_read(relay_parent, relevant_keys).await
}
async fn wait_for_block(&self, hash: PHash) -> Result<(), WaitError> {
async fn wait_for_block(&self, hash: PHash) -> RelayChainResult<()> {
(**self).wait_for_block(hash).await
}
async fn new_best_notification_stream(
&self,
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>> {
(**self).new_best_notification_stream().await
}
}
@@ -0,0 +1,30 @@
[package]
authors = ["Parity Technologies <admin@parity.io>"]
name = "cumulus-relay-chain-rpc-interface"
version = "0.1.0"
edition = "2021"
[dependencies]
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
cumulus-primitives-core = { path = "../../primitives/core" }
cumulus-relay-chain-interface = { path = "../relay-chain-interface" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
futures = "0.3.21"
futures-timer = "3.0.2"
parity-scale-codec = "3.0.0"
parking_lot = "0.12.0"
jsonrpsee = { version = "0.9.0", features = ["client"] }
tracing = "0.1.25"
async-trait = "0.1.52"
url = "2.2.2"
backoff = { version = "0.4.0", features = ["tokio"] }
+471
View File
@@ -0,0 +1,471 @@
// Copyright 2022 Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use async_trait::async_trait;
use backoff::{future::retry_notify, ExponentialBackoff};
use core::time::Duration;
use cumulus_primitives_core::{
relay_chain::{
v1::{CommittedCandidateReceipt, OccupiedCoreAssumption, SessionIndex, ValidatorId},
Hash as PHash, Header as PHeader, InboundHrmpMessage,
},
InboundDownwardMessage, ParaId, PersistedValidationData,
};
use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface, RelayChainResult};
use futures::{FutureExt, Stream, StreamExt};
use jsonrpsee::{
core::{
client::{Client as JsonRPCClient, ClientT, Subscription, SubscriptionClientT},
Error as JsonRpseeError,
},
rpc_params,
types::ParamsSer,
ws_client::WsClientBuilder,
};
use parity_scale_codec::{Decode, Encode};
use polkadot_service::Handle;
use sc_client_api::{StorageData, StorageProof};
use sc_rpc_api::{state::ReadProof, system::Health};
use sp_core::sp_std::collections::btree_map::BTreeMap;
use sp_runtime::DeserializeOwned;
use sp_state_machine::StorageValue;
use sp_storage::StorageKey;
use std::{pin::Pin, sync::Arc};
pub use url::Url;
const LOG_TARGET: &str = "relay-chain-rpc-interface";
const TIMEOUT_IN_SECONDS: u64 = 6;
/// Client that maps RPC methods and deserializes results
#[derive(Clone)]
struct RelayChainRPCClient {
/// Websocket client to make calls
ws_client: Arc<JsonRPCClient>,
/// Retry strategy that should be used for requests and subscriptions
retry_strategy: ExponentialBackoff,
}
impl RelayChainRPCClient {
pub async fn new(url: Url) -> RelayChainResult<Self> {
tracing::info!(target: LOG_TARGET, url = %url.to_string(), "Initializing RPC Client");
let ws_client = WsClientBuilder::default().build(url.as_str()).await?;
Ok(RelayChainRPCClient {
ws_client: Arc::new(ws_client),
retry_strategy: ExponentialBackoff::default(),
})
}
/// Call a call to `state_call` rpc method.
async fn call_remote_runtime_function<R: Decode>(
&self,
method_name: &str,
hash: PHash,
payload: Option<impl Encode>,
) -> RelayChainResult<R> {
let payload_bytes =
payload.map_or(sp_core::Bytes(Vec::new()), |v| sp_core::Bytes(v.encode()));
let params = rpc_params! {
method_name,
payload_bytes,
hash
};
let res = self
.request_tracing::<sp_core::Bytes, _>("state_call", params, |err| {
tracing::trace!(
target: LOG_TARGET,
%method_name,
%hash,
error = %err,
"Error during call to 'state_call'.",
);
})
.await?;
Decode::decode(&mut &*res.0).map_err(Into::into)
}
/// Subscribe to a notification stream via RPC
async fn subscribe<'a, R>(
&self,
sub_name: &'a str,
unsub_name: &'a str,
params: Option<ParamsSer<'a>>,
) -> RelayChainResult<Subscription<R>>
where
R: DeserializeOwned,
{
self.ws_client
.subscribe::<R>(sub_name, params, unsub_name)
.await
.map_err(|err| RelayChainError::RPCCallError(sub_name.to_string(), err))
}
/// Perform RPC request
async fn request<'a, R>(
&self,
method: &'a str,
params: Option<ParamsSer<'a>>,
) -> Result<R, RelayChainError>
where
R: DeserializeOwned + std::fmt::Debug,
{
self.request_tracing(
method,
params,
|e| tracing::trace!(target:LOG_TARGET, error = %e, %method, "Unable to complete RPC request"),
)
.await
}
/// Perform RPC request
async fn request_tracing<'a, R, OR>(
&self,
method: &'a str,
params: Option<ParamsSer<'a>>,
trace_error: OR,
) -> Result<R, RelayChainError>
where
R: DeserializeOwned + std::fmt::Debug,
OR: Fn(&jsonrpsee::core::Error),
{
retry_notify(
self.retry_strategy.clone(),
|| async {
self.ws_client.request(method, params.clone()).await.map_err(|err| match err {
JsonRpseeError::Transport(_) =>
backoff::Error::Transient { err, retry_after: None },
_ => backoff::Error::Permanent(err),
})
},
|error, dur| tracing::trace!(target: LOG_TARGET, %error, ?dur, "Encountered transport error, retrying."),
)
.await
.map_err(|err| {
trace_error(&err);
RelayChainError::RPCCallError(method.to_string(), err)})
}
async fn system_health(&self) -> Result<Health, RelayChainError> {
self.request("system_health", None).await
}
async fn state_get_read_proof(
&self,
storage_keys: Vec<StorageKey>,
at: Option<PHash>,
) -> Result<ReadProof<PHash>, RelayChainError> {
let params = rpc_params!(storage_keys, at);
self.request("state_getReadProof", params).await
}
async fn state_get_storage(
&self,
storage_key: StorageKey,
at: Option<PHash>,
) -> Result<Option<StorageData>, RelayChainError> {
let params = rpc_params!(storage_key, at);
self.request("state_getStorage", params).await
}
async fn chain_get_head(&self) -> Result<PHash, RelayChainError> {
self.request("chain_getHead", None).await
}
async fn chain_get_header(
&self,
hash: Option<PHash>,
) -> Result<Option<PHeader>, RelayChainError> {
let params = rpc_params!(hash);
self.request("chain_getHeader", params).await
}
async fn parachain_host_candidate_pending_availability(
&self,
at: PHash,
para_id: ParaId,
) -> Result<Option<CommittedCandidateReceipt>, RelayChainError> {
self.call_remote_runtime_function(
"ParachainHost_candidate_pending_availability",
at,
Some(para_id),
)
.await
}
async fn parachain_host_session_index_for_child(
&self,
at: PHash,
) -> Result<SessionIndex, RelayChainError> {
self.call_remote_runtime_function("ParachainHost_session_index_for_child", at, None::<()>)
.await
}
async fn parachain_host_validators(
&self,
at: PHash,
) -> Result<Vec<ValidatorId>, RelayChainError> {
self.call_remote_runtime_function("ParachainHost_validators", at, None::<()>)
.await
}
async fn parachain_host_persisted_validation_data(
&self,
at: PHash,
para_id: ParaId,
occupied_core_assumption: OccupiedCoreAssumption,
) -> Result<Option<PersistedValidationData>, RelayChainError> {
self.call_remote_runtime_function(
"ParachainHost_persisted_validation_data",
at,
Some((para_id, occupied_core_assumption)),
)
.await
}
async fn parachain_host_inbound_hrmp_channels_contents(
&self,
para_id: ParaId,
at: PHash,
) -> Result<BTreeMap<ParaId, Vec<InboundHrmpMessage>>, RelayChainError> {
self.call_remote_runtime_function(
"ParachainHost_inbound_hrmp_channels_contents",
at,
Some(para_id),
)
.await
}
async fn parachain_host_dmq_contents(
&self,
para_id: ParaId,
at: PHash,
) -> Result<Vec<InboundDownwardMessage>, RelayChainError> {
self.call_remote_runtime_function("ParachainHost_dmq_contents", at, Some(para_id))
.await
}
async fn subscribe_all_heads(&self) -> Result<Subscription<PHeader>, RelayChainError> {
self.subscribe::<PHeader>("chain_subscribeAllHeads", "chain_unsubscribeAllHeads", None)
.await
}
async fn subscribe_new_best_heads(&self) -> Result<Subscription<PHeader>, RelayChainError> {
self.subscribe::<PHeader>("chain_subscribeNewHeads", "chain_unsubscribeNewHeads", None)
.await
}
async fn subscribe_finalized_heads(&self) -> Result<Subscription<PHeader>, RelayChainError> {
self.subscribe::<PHeader>(
"chain_subscribeFinalizedHeads",
"chain_unsubscribeFinalizedHeads",
None,
)
.await
}
}
/// RelayChainRPCInterface is used to interact with a full node that is running locally
/// in the same process.
#[derive(Clone)]
pub struct RelayChainRPCInterface {
rpc_client: RelayChainRPCClient,
}
impl RelayChainRPCInterface {
pub async fn new(url: Url) -> RelayChainResult<Self> {
Ok(Self { rpc_client: RelayChainRPCClient::new(url).await? })
}
}
#[async_trait]
impl RelayChainInterface for RelayChainRPCInterface {
async fn retrieve_dmq_contents(
&self,
para_id: ParaId,
relay_parent: PHash,
) -> RelayChainResult<Vec<InboundDownwardMessage>> {
self.rpc_client.parachain_host_dmq_contents(para_id, relay_parent).await
}
async fn retrieve_all_inbound_hrmp_channel_contents(
&self,
para_id: ParaId,
relay_parent: PHash,
) -> RelayChainResult<BTreeMap<ParaId, Vec<InboundHrmpMessage>>> {
self.rpc_client
.parachain_host_inbound_hrmp_channels_contents(para_id, relay_parent)
.await
}
async fn persisted_validation_data(
&self,
hash: PHash,
para_id: ParaId,
occupied_core_assumption: OccupiedCoreAssumption,
) -> RelayChainResult<Option<PersistedValidationData>> {
self.rpc_client
.parachain_host_persisted_validation_data(hash, para_id, occupied_core_assumption)
.await
}
async fn candidate_pending_availability(
&self,
hash: PHash,
para_id: ParaId,
) -> RelayChainResult<Option<CommittedCandidateReceipt>> {
self.rpc_client
.parachain_host_candidate_pending_availability(hash, para_id)
.await
}
async fn session_index_for_child(&self, hash: PHash) -> RelayChainResult<SessionIndex> {
self.rpc_client.parachain_host_session_index_for_child(hash).await
}
async fn validators(&self, block_id: PHash) -> RelayChainResult<Vec<ValidatorId>> {
self.rpc_client.parachain_host_validators(block_id).await
}
async fn import_notification_stream(
&self,
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>> {
let imported_headers_stream =
self.rpc_client.subscribe_all_heads().await?.filter_map(|item| async move {
item.map_err(|err| {
tracing::error!(
target: LOG_TARGET,
"Encountered error in import notification stream: {}",
err
)
})
.ok()
});
Ok(imported_headers_stream.boxed())
}
async fn finality_notification_stream(
&self,
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>> {
let imported_headers_stream = self
.rpc_client
.subscribe_finalized_heads()
.await?
.filter_map(|item| async move {
item.map_err(|err| {
tracing::error!(
target: LOG_TARGET,
"Encountered error in finality notification stream: {}",
err
)
})
.ok()
});
Ok(imported_headers_stream.boxed())
}
async fn best_block_hash(&self) -> RelayChainResult<PHash> {
self.rpc_client.chain_get_head().await
}
async fn is_major_syncing(&self) -> RelayChainResult<bool> {
self.rpc_client.system_health().await.map(|h| h.is_syncing)
}
fn overseer_handle(&self) -> RelayChainResult<Option<Handle>> {
unimplemented!("Overseer handle is not available on relay-chain-rpc-interface");
}
async fn get_storage_by_key(
&self,
relay_parent: PHash,
key: &[u8],
) -> RelayChainResult<Option<StorageValue>> {
let storage_key = StorageKey(key.to_vec());
self.rpc_client
.state_get_storage(storage_key, Some(relay_parent))
.await
.map(|storage_data| storage_data.map(|sv| sv.0))
}
async fn prove_read(
&self,
relay_parent: PHash,
relevant_keys: &Vec<Vec<u8>>,
) -> RelayChainResult<StorageProof> {
let cloned = relevant_keys.clone();
let storage_keys: Vec<StorageKey> = cloned.into_iter().map(StorageKey).collect();
self.rpc_client
.state_get_read_proof(storage_keys, Some(relay_parent))
.await
.map(|read_proof| {
StorageProof::new(read_proof.proof.into_iter().map(|bytes| bytes.to_vec()))
})
}
/// Wait for a given relay chain block
///
/// The hash of the block to wait for is passed. We wait for the block to arrive or return after a timeout.
///
/// Implementation:
/// 1. Register a listener to all new blocks.
/// 2. Check if the block is already in chain. If yes, succeed early.
/// 3. Wait for the block to be imported via subscription.
/// 4. If timeout is reached, we return an error.
async fn wait_for_block(&self, wait_for_hash: PHash) -> RelayChainResult<()> {
let mut head_stream = self.rpc_client.subscribe_all_heads().await?;
if self.rpc_client.chain_get_header(Some(wait_for_hash)).await?.is_some() {
return Ok(())
}
let mut timeout = futures_timer::Delay::new(Duration::from_secs(TIMEOUT_IN_SECONDS)).fuse();
loop {
futures::select! {
_ = timeout => return Err(RelayChainError::WaitTimeout(wait_for_hash)),
evt = head_stream.next().fuse() => match evt {
Some(Ok(evt)) if evt.hash() == wait_for_hash => return Ok(()),
// Not the event we waited on.
Some(_) => continue,
None => return Err(RelayChainError::ImportListenerClosed(wait_for_hash)),
}
}
}
}
async fn new_best_notification_stream(
&self,
) -> RelayChainResult<Pin<Box<dyn Stream<Item = PHeader> + Send>>> {
let imported_headers_stream =
self.rpc_client.subscribe_new_best_heads().await?.filter_map(|item| async move {
item.map_err(|err| {
tracing::error!(
target: LOG_TARGET,
"Error in best block notification stream: {}",
err
)
})
.ok()
});
Ok(imported_headers_stream.boxed())
}
}
+18 -18
View File
@@ -5,32 +5,32 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[dependencies]
# Cumulus dependencies
cumulus-client-consensus-common = { path = "../consensus/common" }
cumulus-client-collator = { path = "../collator" }
cumulus-client-pov-recovery = { path = "../pov-recovery" }
cumulus-relay-chain-interface = { path = "../relay-chain-interface" }
cumulus-primitives-core = { path = "../../primitives/core" }
codec = { package = "parity-scale-codec", version = "3.0.0" }
parking_lot = "0.12.0"
tracing = "0.1.31"
# Substrate dependencies
# Substrate
sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot dependencies
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Polkadot
polkadot-overseer = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Other deps
tracing = "0.1.22"
codec = { package = "parity-scale-codec", version = "2.3.0" }
parking_lot = "0.10.2"
# Cumulus
cumulus-client-cli = { path = "../cli" }
cumulus-client-collator = { path = "../collator" }
cumulus-client-consensus-common = { path = "../consensus/common" }
cumulus-client-pov-recovery = { path = "../pov-recovery" }
cumulus-primitives-core = { path = "../../primitives/core" }
cumulus-relay-chain-interface = { path = "../relay-chain-interface" }
+58 -13
View File
@@ -18,6 +18,7 @@
//!
//! Provides functions for starting a collator node or a normal full node.
use cumulus_client_cli::CollatorOptions;
use cumulus_client_consensus_common::ParachainConsensus;
use cumulus_primitives_core::{CollectCollationInfo, ParaId};
use cumulus_relay_chain_interface::RelayChainInterface;
@@ -54,7 +55,7 @@ pub struct StartCollatorParams<'a, Block: BlockT, BS, Client, RCInterface, Spawn
pub parachain_consensus: Box<dyn ParachainConsensus<Block>>,
pub import_queue: IQ,
pub collator_key: CollatorPair,
pub slot_duration: Duration,
pub relay_chain_slot_duration: Duration,
}
/// Start a collator node for a parachain.
@@ -74,7 +75,7 @@ pub async fn start_collator<'a, Block, BS, Client, Backend, RCInterface, Spawner
parachain_consensus,
import_queue,
collator_key,
slot_duration,
relay_chain_slot_duration,
}: StartCollatorParams<'a, Block, BS, Client, RCInterface, Spawner, IQ>,
) -> sc_service::error::Result<()>
where
@@ -107,11 +108,16 @@ where
.spawn_essential_handle()
.spawn("cumulus-consensus", None, consensus);
let overseer_handle = relay_chain_interface
.overseer_handle()
.map_err(|e| sc_service::Error::Application(Box::new(e)))?
.ok_or_else(|| "Polkadot full node did not provide an `OverseerHandle`!")?;
let pov_recovery = cumulus_client_pov_recovery::PoVRecovery::new(
relay_chain_interface
.overseer_handle()
.ok_or_else(|| "Polkadot full node did not provide an `OverseerHandle`!")?,
slot_duration,
overseer_handle.clone(),
// We want that collators wait at maximum the relay chain slot duration before starting
// to recover blocks.
cumulus_client_pov_recovery::RecoveryDelay::WithMax { max: relay_chain_slot_duration },
client.clone(),
import_queue,
relay_chain_interface.clone(),
@@ -126,9 +132,7 @@ where
runtime_api: client.clone(),
block_status,
announce_block,
overseer_handle: relay_chain_interface
.overseer_handle()
.ok_or_else(|| "Polkadot full node did not provide an `OverseerHandle`!")?,
overseer_handle,
spawner,
para_id,
key: collator_key,
@@ -140,26 +144,32 @@ where
}
/// Parameters given to [`start_full_node`].
pub struct StartFullNodeParams<'a, Block: BlockT, Client, RCInterface> {
pub struct StartFullNodeParams<'a, Block: BlockT, Client, RCInterface, IQ> {
pub para_id: ParaId,
pub client: Arc<Client>,
pub relay_chain_interface: RCInterface,
pub task_manager: &'a mut TaskManager,
pub announce_block: Arc<dyn Fn(Block::Hash, Option<Vec<u8>>) + Send + Sync>,
pub relay_chain_slot_duration: Duration,
pub import_queue: IQ,
pub collator_options: CollatorOptions,
}
/// Start a full node for a parachain.
///
/// A full node will only sync the given parachain and will follow the
/// tip of the chain.
pub fn start_full_node<Block, Client, Backend, RCInterface>(
pub fn start_full_node<Block, Client, Backend, RCInterface, IQ>(
StartFullNodeParams {
client,
announce_block,
task_manager,
relay_chain_interface,
para_id,
}: StartFullNodeParams<Block, Client, RCInterface>,
relay_chain_slot_duration,
import_queue,
collator_options,
}: StartFullNodeParams<Block, Client, RCInterface, IQ>,
) -> sc_service::error::Result<()>
where
Block: BlockT,
@@ -173,6 +183,7 @@ where
for<'a> &'a Client: BlockImport<Block>,
Backend: BackendT<Block> + 'static,
RCInterface: RelayChainInterface + Clone + 'static,
IQ: ImportQueue<Block> + 'static,
{
let consensus = cumulus_client_consensus_common::run_parachain_consensus(
para_id,
@@ -185,10 +196,44 @@ where
.spawn_essential_handle()
.spawn("cumulus-consensus", None, consensus);
// PoV Recovery is currently not supported when we connect to the
// relay chain via RPC, so we return early. The node will work, but not be able to recover PoVs from the
// relay chain if blocks are not announced on parachain. This will be enabled again once
// https://github.com/paritytech/cumulus/issues/545 is finished.
if collator_options.relay_chain_rpc_url.is_some() {
return Ok(())
}
let overseer_handle = relay_chain_interface
.overseer_handle()
.map_err(|e| sc_service::Error::Application(Box::new(e)))?
.ok_or_else(|| "Polkadot full node did not provide an `OverseerHandle`!")?;
let pov_recovery = cumulus_client_pov_recovery::PoVRecovery::new(
overseer_handle,
// Full nodes should at least wait 2.5 minutes (assuming 6 seconds slot duration) and
// in maximum 5 minutes before starting to recover blocks. Collators should already start
// the recovery way before full nodes try to recover a certain block and then share the
// block with the network using "the normal way". Full nodes are just the "last resort"
// for block recovery.
cumulus_client_pov_recovery::RecoveryDelay::WithMinAndMax {
min: relay_chain_slot_duration * 25,
max: relay_chain_slot_duration * 50,
},
client.clone(),
import_queue,
relay_chain_interface.clone(),
para_id,
);
task_manager
.spawn_essential_handle()
.spawn("cumulus-pov-recovery", None, pov_recovery.run());
Ok(())
}
/// Prepare the parachain's node condifugration
/// Prepare the parachain's node configuration
///
/// This function will disable the default announcement of Substrate for the parachain in favor
/// of the one of Cumulus.
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 88 KiB

+19 -18
View File
@@ -6,22 +6,23 @@ edition = "2021"
description = "AURA consensus extension pallet for parachains"
[dependencies]
# Substrate dependencies
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Other Dependencies
codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = ["derive"]}
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.132", optional = true, features = ["derive"] }
# Substrate
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
[dev-dependencies]
# Cumulus
cumulus-pallet-parachain-system = { path = "../parachain-system" }
[features]
@@ -30,12 +31,12 @@ std = [
"codec/std",
"scale-info/std",
"serde",
"frame-executive/std",
"frame-support/std",
"frame-system/std",
"pallet-aura/std",
"sp-application-crypto/std",
"sp-consensus-aura/std",
"sp-runtime/std",
"sp-std/std",
"frame-system/std",
"frame-executive/std",
"pallet-aura/std",
"sp-consensus-aura/std",
"sp-application-crypto/std",
]
+1
View File
@@ -56,6 +56,7 @@ pub mod pallet {
pub trait Config: pallet_aura::Config + frame_system::Config {}
#[pallet::pallet]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);
#[pallet::hooks]
+3 -3
View File
@@ -14,9 +14,9 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
log = { version = "0.4.0", default-features = false }
codec = { default-features = false, features = ["derive"], package = "parity-scale-codec", version = "2.3.0" }
rand = { version = "0.7.2", default-features = false }
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
codec = { default-features = false, features = ["derive"], package = "parity-scale-codec", version = "3.0.0" }
rand = { version = "0.8.5", features = ["std_rng"], default-features = false }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.132", default-features = false }
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -84,12 +84,14 @@ fn validator<T: Config + session::Config>(c: u32) -> (T::AccountId, <T as sessio
(create_funded_user::<T>("candidate", c, 1000), keys::<T>(c))
}
fn register_validators<T: Config + session::Config>(count: u32) {
fn register_validators<T: Config + session::Config>(count: u32) -> Vec<T::AccountId> {
let validators = (0..count).map(|c| validator::<T>(c)).collect::<Vec<_>>();
for (who, keys) in validators {
for (who, keys) in validators.clone() {
<session::Pallet<T>>::set_keys(RawOrigin::Signed(who).into(), keys, Vec::new()).unwrap();
}
validators.into_iter().map(|(who, _)| who).collect()
}
fn register_candidates<T: Config>(count: u32) {
@@ -107,7 +109,7 @@ benchmarks! {
set_invulnerables {
let b in 1 .. T::MaxInvulnerables::get();
let new_invulnerables = (0..b).map(|c| account("candidate", c, SEED)).collect::<Vec<_>>();
let new_invulnerables = register_validators::<T>(b);
let origin = T::UpdateOrigin::successful_origin();
}: {
assert_ok!(
+31 -2
View File
@@ -31,7 +31,7 @@
//!
//! ## Implementation
//!
//! The final [`Collators`] are aggregated from two individual lists:
//! The final `Collators` are aggregated from two individual lists:
//!
//! 1. [`Invulnerables`]: a set of collators appointed by governance. These accounts will always be
//! collators.
@@ -168,6 +168,7 @@ pub mod pallet {
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);
/// The invulnerable, fixed collators.
@@ -194,7 +195,9 @@ pub mod pallet {
#[pallet::getter(fn desired_candidates)]
pub type DesiredCandidates<T> = StorageValue<_, u32, ValueQuery>;
/// Fixed deposit bond for each candidate.
/// Fixed amount to deposit to become a collator.
///
/// When a collator calls `leave_intent` they immediately receive the deposit back.
#[pallet::storage]
#[pallet::getter(fn candidacy_bond)]
pub type CandidacyBond<T> = StorageValue<_, BalanceOf<T>, ValueQuery>;
@@ -280,6 +283,7 @@ pub mod pallet {
#[pallet::call]
impl<T: Config> Pallet<T> {
/// Set the list of invulnerable (fixed) collators.
#[pallet::weight(T::WeightInfo::set_invulnerables(new.len() as u32))]
pub fn set_invulnerables(
origin: OriginFor<T>,
@@ -292,11 +296,25 @@ pub mod pallet {
"invulnerables > T::MaxInvulnerables; you might need to run benchmarks again"
);
}
// check if the invulnerables have associated validator keys before they are set
for account_id in &new {
let validator_key = T::ValidatorIdOf::convert(account_id.clone())
.ok_or(Error::<T>::NoAssociatedValidatorId)?;
ensure!(
T::ValidatorRegistration::is_registered(&validator_key),
Error::<T>::ValidatorNotRegistered
);
}
<Invulnerables<T>>::put(&new);
Self::deposit_event(Event::NewInvulnerables(new));
Ok(().into())
}
/// Set the ideal number of collators (not including the invulnerables).
/// If lowering this number, then the number of running collators could be higher than this figure.
/// Aside from that edge case, there should be no other way to have more collators than the desired number.
#[pallet::weight(T::WeightInfo::set_desired_candidates())]
pub fn set_desired_candidates(
origin: OriginFor<T>,
@@ -312,6 +330,7 @@ pub mod pallet {
Ok(().into())
}
/// Set the candidacy bond amount.
#[pallet::weight(T::WeightInfo::set_candidacy_bond())]
pub fn set_candidacy_bond(
origin: OriginFor<T>,
@@ -323,6 +342,10 @@ pub mod pallet {
Ok(().into())
}
/// Register this account as a collator candidate. The account must (a) already have
/// registered session keys and (b) be able to reserve the `CandidacyBond`.
///
/// This call is not available to `Invulnerable` collators.
#[pallet::weight(T::WeightInfo::register_as_candidate(T::MaxCandidates::get()))]
pub fn register_as_candidate(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
@@ -362,6 +385,12 @@ pub mod pallet {
Ok(Some(T::WeightInfo::register_as_candidate(current_count as u32)).into())
}
/// Deregister `origin` as a collator candidate. Note that the collator can only leave on
/// session change. The `CandidacyBond` will be unreserved immediately.
///
/// This call will fail if the total number of candidates would drop below `MinCandidates`.
///
/// This call is not available to `Invulnerable` collators.
#[pallet::weight(T::WeightInfo::leave_intent(T::MaxCandidates::get()))]
pub fn leave_intent(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
+10
View File
@@ -48,6 +48,16 @@ fn it_should_set_invulnerables() {
CollatorSelection::set_invulnerables(Origin::signed(1), new_set.clone()),
BadOrigin
);
// cannot set invulnerables without associated validator keys
let invulnerables = vec![7];
assert_noop!(
CollatorSelection::set_invulnerables(
Origin::signed(RootAccount::get()),
invulnerables.clone()
),
Error::<Test>::ValidatorNotRegistered
);
});
}
+14 -15
View File
@@ -5,23 +5,22 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[dependencies]
# Other dependencies
codec = { package = "parity-scale-codec", version = "2.3.0", features = [ "derive" ], default-features = false }
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ], default-features = false }
log = { version = "0.4.14", default-features = false }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
# Substrate Dependencies
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Substrate
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Polkadot Dependencies
# Polkadot
xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
# Cumulus Dependencies
# Cumulus
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
[dev-dependencies]
@@ -32,14 +31,14 @@ sp-version = { git = "https://github.com/paritytech/substrate", default-features
default = [ "std" ]
std = [
"codec/std",
"log/std",
"scale-info/std",
"sp-std/std",
"sp-io/std",
"sp-runtime/std",
"frame-support/std",
"frame-system/std",
"cumulus-primitives-core/std",
"xcm/std",
"log/std",
"sp-io/std",
"sp-runtime/std",
"sp-std/std",
"xcm-executor/std",
"xcm/std",
"cumulus-primitives-core/std",
]
+4 -3
View File
@@ -77,6 +77,7 @@ pub mod pallet {
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);
/// The module configuration trait.
@@ -222,12 +223,12 @@ pub mod pallet {
pub(crate) fn try_service_message(
limit: Weight,
_sent_at: RelayBlockNumber,
data: &[u8],
mut data: &[u8],
) -> Result<Weight, (MessageId, Weight)> {
let id = sp_io::hashing::blake2_256(&data[..]);
let id = sp_io::hashing::blake2_256(data);
let maybe_msg = VersionedXcm::<T::Call>::decode_all_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut &data[..],
&mut data,
)
.map(Xcm::<T::Call>::try_from);
match maybe_msg {
+43 -44
View File
@@ -6,71 +6,70 @@ edition = "2021"
description = "Base pallet for cumulus-based parachains"
[dependencies]
# Cumulus dependencies
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
cumulus-primitives-parachain-inherent = { path = "../../primitives/parachain-inherent", default-features = false }
cumulus-pallet-parachain-system-proc-macro = { path = "proc-macro", default-features = false }
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
environmental = { version = "1.1.2", default-features = false }
impl-trait-for-tuples = "0.2.1"
log = { version = "0.4.14", default-features = false }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.132", optional = true, features = ["derive"] }
# Polkadot dependencies
# Substrate
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-externalities = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Polkadot
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, features = [ "wasm-api" ], branch = "master" }
xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
# Substrate dependencies
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-externalities = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Other Dependencies
codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = ["derive"]}
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.132", optional = true, features = ["derive"] }
log = { version = "0.4.14", default-features = false }
environmental = { version = "1.1.2", default-features = false }
# Cumulus
cumulus-pallet-parachain-system-proc-macro = { path = "proc-macro", default-features = false }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
cumulus-primitives-parachain-inherent = { path = "../../primitives/parachain-inherent", default-features = false }
[dev-dependencies]
# Other Dependencies
hex-literal = "0.2.1"
hex-literal = "0.3.4"
lazy_static = "1.4"
# Substrate dependencies
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Substrate
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Cumulus dependencies
# Cumulus
cumulus-test-client = { path = "../../test/client" }
cumulus-test-relay-sproof-builder = { path = "../../test/relay-sproof-builder" }
[features]
default = [ "std" ]
std = [
"serde",
"codec/std",
"scale-info/std",
"frame-support/std",
"pallet-balances/std",
"sp-core/std",
"sp-runtime/std",
"sp-io/std",
"sp-std/std",
"environmental/std",
"log/std",
"sp-state-machine/std",
"sp-trie/std",
"sp-externalities/std",
"frame-system/std",
"scale-info/std",
"serde",
"cumulus-pallet-parachain-system-proc-macro/std",
"cumulus-primitives-core/std",
"cumulus-primitives-parachain-inherent/std",
"cumulus-pallet-parachain-system-proc-macro/std",
"environmental/std",
"frame-support/std",
"frame-system/std",
"pallet-balances/std",
"sp-core/std",
"sp-externalities/std",
"sp-io/std",
"sp-runtime/std",
"sp-state-machine/std",
"sp-std/std",
"sp-trie/std",
"xcm/std"
]
@@ -12,7 +12,7 @@ proc-macro = true
syn = "1.0.81"
proc-macro2 = "1.0.36"
quote = "1.0.9"
proc-macro-crate = "1.0.0"
proc-macro-crate = "1.1.3"
[features]
default = [ "std" ]
+34 -10
View File
@@ -27,9 +27,10 @@
//!
//! Users must ensure that they register this pallet as an inherent provider.
use codec::Encode;
use cumulus_primitives_core::{
relay_chain, AbridgedHostConfiguration, ChannelStatus, CollationInfo, DmpMessageHandler,
GetChannelInfo, InboundDownwardMessage, InboundHrmpMessage, MessageSendError, OnValidationData,
GetChannelInfo, InboundDownwardMessage, InboundHrmpMessage, MessageSendError,
OutboundHrmpMessage, ParaId, PersistedValidationData, UpwardMessage, UpwardMessageSender,
XcmpMessageHandler, XcmpMessageSource,
};
@@ -44,7 +45,6 @@ use frame_support::{
};
use frame_system::{ensure_none, ensure_root};
use polkadot_parachain::primitives::RelayChainBlockNumber;
use relay_state_snapshot::MessagingStateSnapshot;
use sp_runtime::{
traits::{Block as BlockT, BlockNumberProvider, Hash},
transaction_validity::{
@@ -84,7 +84,7 @@ mod tests;
/// # fn main() {}
/// ```
pub use cumulus_pallet_parachain_system_proc_macro::register_validate_block;
pub use relay_state_snapshot::RelayChainStateProof;
pub use relay_state_snapshot::{MessagingStateSnapshot, RelayChainStateProof};
pub use pallet::*;
@@ -96,6 +96,7 @@ pub mod pallet {
#[pallet::pallet]
#[pallet::storage_version(migration::STORAGE_VERSION)]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);
#[pallet::config]
@@ -104,7 +105,7 @@ pub mod pallet {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
/// Something which can be notified when the validation data is set.
type OnValidationData: OnValidationData;
type OnSystemEvent: OnSystemEvent;
/// Returns the parachain ID we are running with.
type SelfParaId: Get<ParaId>;
@@ -328,6 +329,7 @@ pub mod pallet {
let validation_code = <PendingValidationCode<T>>::take();
Self::put_parachain_code(&validation_code);
<T::OnSystemEvent as OnSystemEvent>::on_validation_code_applied();
Self::deposit_event(Event::ValidationFunctionApplied(vfp.relay_parent_number));
},
Some(relay_chain::v1::UpgradeGoAhead::Abort) => {
@@ -353,7 +355,7 @@ pub mod pallet {
<RelevantMessagingState<T>>::put(relevant_messaging_state.clone());
<HostConfiguration<T>>::put(host_config);
<T::OnValidationData as OnValidationData>::on_validation_data(&vfp);
<T::OnSystemEvent as OnSystemEvent>::on_validation_data(&vfp);
// TODO: This is more than zero, but will need benchmarking to figure out what.
let mut total_weight = 0;
@@ -396,7 +398,7 @@ pub mod pallet {
code: Vec<u8>,
) -> DispatchResultWithPostInfo {
Self::validate_authorized_upgrade(&code[..])?;
Self::set_code_impl(code)?;
Self::schedule_code_upgrade(code)?;
AuthorizedUpgrade::<T>::kill();
Ok(Pays::No.into())
}
@@ -602,7 +604,7 @@ pub mod pallet {
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig {
fn build(&self) {
//TODO: Remove after https://github.com/paritytech/cumulus/issues/479
// TODO: Remove after https://github.com/paritytech/cumulus/issues/479
sp_io::storage::set(b":c", &[]);
}
}
@@ -882,7 +884,7 @@ impl<T: Config> Pallet<T> {
}
/// The implementation of the runtime upgrade functionality for parachains.
fn set_code_impl(validation_function: Vec<u8>) -> DispatchResult {
pub fn schedule_code_upgrade(validation_function: Vec<u8>) -> DispatchResult {
// Ensure that `ValidationData` exists. We do not care about the validation data per se,
// but we do care about the [`UpgradeRestrictionSignal`] which arrives with the same inherent.
ensure!(<ValidationData<T>>::exists(), Error::<T>::ValidationDataNotAvailable,);
@@ -908,15 +910,22 @@ impl<T: Config> Pallet<T> {
/// Returns the [`CollationInfo`] of the current active block.
///
/// The given `header` is the header of the built block we are collecting the collation info for.
///
/// This is expected to be used by the
/// [`CollectCollationInfo`](cumulus_primitives_core::CollectCollationInfo) runtime api.
pub fn collect_collation_info() -> CollationInfo {
pub fn collect_collation_info(header: &T::Header) -> CollationInfo {
CollationInfo {
hrmp_watermark: HrmpWatermark::<T>::get(),
horizontal_messages: HrmpOutboundMessages::<T>::get(),
upward_messages: UpwardMessages::<T>::get(),
processed_downward_messages: ProcessedDownwardMessages::<T>::get(),
new_validation_code: NewValidationCode::<T>::get().map(Into::into),
// Check if there is a custom header that will also be returned by the validation phase.
// If so, we need to also return it here.
head_data: CustomValidationHeadData::<T>::get()
.map_or_else(|| header.encode(), |v| v)
.into(),
}
}
@@ -941,7 +950,7 @@ pub struct ParachainSetCode<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> frame_system::SetCode<T> for ParachainSetCode<T> {
fn set_code(code: Vec<u8>) -> DispatchResult {
Pallet::<T>::set_code_impl(code)
Pallet::<T>::schedule_code_upgrade(code)
}
}
@@ -999,6 +1008,21 @@ pub trait CheckInherents<Block: BlockT> {
) -> frame_support::inherent::CheckInherentsResult;
}
/// Something that should be informed about system related events.
///
/// This includes events like [`on_validation_data`](Self::on_validation_data) that is being
/// called when the parachain inherent is executed that contains the validation data.
/// Or like [`on_validation_code_applied`](Self::on_validation_code_applied) that is called
/// when the new validation is written to the state. This means that
/// from the next block the runtime is being using this new code.
#[impl_trait_for_tuples::impl_for_tuples(30)]
pub trait OnSystemEvent {
/// Called in each blocks once when the validation data is set by the inherent.
fn on_validation_data(data: &PersistedValidationData);
/// Called when the validation code is being applied, aka from the next block on this is the new runtime.
fn on_validation_code_applied();
}
/// Implements [`BlockNumberProvider`] that returns relay chain block number fetched from
/// validation data.
/// NTOE: When validation data is not available (e.g. within on_initialize), 0 will be returned.
+69 -5
View File
@@ -29,7 +29,7 @@ use frame_support::{
traits::{OnFinalize, OnInitialize},
weights::Weight,
};
use frame_system::{InitKind, RawOrigin};
use frame_system::RawOrigin;
use hex_literal::hex;
use relay_chain::v1::HrmpChannelId;
use sp_core::H256;
@@ -100,7 +100,7 @@ impl frame_system::Config for Test {
}
impl Config for Test {
type Event = Event;
type OnValidationData = ();
type OnSystemEvent = ();
type SelfParaId = ParachainId;
type OutboundXcmpMessageSource = FromThreadLocal;
type DmpMessageHandler = SaveIntoThreadLocal;
@@ -303,7 +303,8 @@ impl BlockTests {
}
// begin initialization
System::initialize(&n, &Default::default(), &Default::default(), InitKind::Full);
System::reset_events();
System::initialize(&n, &Default::default(), &Default::default());
// now mess with the storage the way validate_block does
let mut sproof_builder = RelayStateSproofBuilder::default();
@@ -719,6 +720,69 @@ fn receive_dmp() {
});
}
#[test]
fn receive_dmp_after_pause() {
lazy_static::lazy_static! {
static ref MSG_1: InboundDownwardMessage = InboundDownwardMessage {
sent_at: 1,
msg: b"down1".to_vec(),
};
static ref MSG_2: InboundDownwardMessage = InboundDownwardMessage {
sent_at: 3,
msg: b"down2".to_vec(),
};
}
BlockTests::new()
.with_relay_sproof_builder(|_, relay_block_num, sproof| match relay_block_num {
1 => {
sproof.dmq_mqc_head =
Some(MessageQueueChain::default().extend_downward(&MSG_1).head());
},
2 => {
// no new messages, mqc stayed the same.
sproof.dmq_mqc_head =
Some(MessageQueueChain::default().extend_downward(&MSG_1).head());
},
3 => {
sproof.dmq_mqc_head = Some(
MessageQueueChain::default()
.extend_downward(&MSG_1)
.extend_downward(&MSG_2)
.head(),
);
},
_ => unreachable!(),
})
.with_inherent_data(|_, relay_block_num, data| match relay_block_num {
1 => {
data.downward_messages.push(MSG_1.clone());
},
2 => {
// no new messages
},
3 => {
data.downward_messages.push(MSG_2.clone());
},
_ => unreachable!(),
})
.add(1, || {
HANDLED_DMP_MESSAGES.with(|m| {
let mut m = m.borrow_mut();
assert_eq!(&*m, &[(MSG_1.sent_at, MSG_1.msg.clone())]);
m.clear();
});
})
.add(2, || {})
.add(3, || {
HANDLED_DMP_MESSAGES.with(|m| {
let mut m = m.borrow_mut();
assert_eq!(&*m, &[(MSG_2.sent_at, MSG_2.msg.clone())]);
m.clear();
});
});
}
#[test]
fn receive_hrmp() {
lazy_static::lazy_static! {
@@ -752,8 +816,8 @@ fn receive_hrmp() {
Some(MessageQueueChain::default().extend_hrmp(&MSG_1).head());
},
2 => {
// 200 - two new messages
// 300 - now present with one message.
// 200 - now present with one message
// 300 - two new messages
sproof.upsert_inbound_channel(ParaId::from(200)).mqc_head =
Some(MessageQueueChain::default().extend_hrmp(&MSG_4).head());
sproof.upsert_inbound_channel(ParaId::from(300)).mqc_head = Some(
+1 -1
View File
@@ -13,7 +13,7 @@ readme = "README.md"
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
parity-scale-codec = { version = "2.3.1", default-features = false }
parity-scale-codec = { version = "3.0.0", default-features = false }
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
+39
View File
@@ -0,0 +1,39 @@
[package]
name = "cumulus-pallet-solo-to-para"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
description = "Adds functionality to migrate from a Solo to a Parachain"
[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
# Substrate
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Polkadot
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
# Cumulus
cumulus-pallet-parachain-system = { default-features = false, path = "../parachain-system" }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
[features]
default = [ "std" ]
std = [
"codec/std",
"scale-info/std",
"cumulus-pallet-parachain-system/std",
"cumulus-primitives-core/std",
"frame-support/std",
"frame-system/std",
"pallet-sudo/std",
"polkadot-primitives/std",
"sp-runtime/std",
"sp-std/std",
]
+182
View File
@@ -0,0 +1,182 @@
// Copyright 2022 Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
#![cfg_attr(not(feature = "std"), no_std)]
use codec::{Decode, Encode};
use cumulus_pallet_parachain_system as parachain_system;
use frame_support::{dispatch::DispatchResult, pallet_prelude::*, weights::DispatchInfo};
use frame_system::pallet_prelude::*;
pub use pallet::*;
use polkadot_primitives::v1::PersistedValidationData;
use scale_info::TypeInfo;
use sp_runtime::{
traits::{DispatchInfoOf, Dispatchable, SignedExtension},
transaction_validity::{
InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionValidity,
TransactionValidityError, ValidTransaction,
},
};
use sp_std::{prelude::*, vec::Vec};
#[frame_support::pallet]
pub mod pallet {
use super::*;
#[pallet::config]
pub trait Config:
frame_system::Config + parachain_system::Config + pallet_sudo::Config
{
type Event: From<Event> + IsType<<Self as frame_system::Config>::Event>;
}
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);
/// In case of a scheduled migration, this storage field contains the custom head data to be applied.
#[pallet::storage]
pub(super) type PendingCustomValidationHeadData<T: Config> =
StorageValue<_, Vec<u8>, OptionQuery>;
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event {
/// The custom validation head data has been scheduled to apply.
CustomValidationHeadDataStored,
/// The custom validation head data was applied as of the contained relay chain block number.
CustomValidationHeadDataApplied,
}
#[pallet::error]
pub enum Error<T> {
/// CustomHeadData is not stored in storage.
NoCustomHeadData,
}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(0)]
pub fn schedule_migration(
origin: OriginFor<T>,
code: Vec<u8>,
head_data: Vec<u8>,
) -> DispatchResult {
ensure_root(origin)?;
parachain_system::Pallet::<T>::schedule_code_upgrade(code)?;
Self::store_pending_custom_validation_head_data(head_data);
Ok(())
}
}
impl<T: Config> Pallet<T> {
/// Set a custom head data that should only be applied when upgradeGoAheadSignal from
/// the Relay Chain is GoAhead
fn store_pending_custom_validation_head_data(head_data: Vec<u8>) {
PendingCustomValidationHeadData::<T>::put(head_data);
Self::deposit_event(Event::CustomValidationHeadDataStored);
}
/// Set pending custom head data as head data that will be returned by `validate_block`. on the relay chain.
fn set_pending_custom_validation_head_data() {
if let Some(head_data) = <PendingCustomValidationHeadData<T>>::take() {
parachain_system::Pallet::<T>::set_custom_validation_head_data(head_data);
Self::deposit_event(Event::CustomValidationHeadDataApplied);
}
}
}
impl<T: Config> parachain_system::OnSystemEvent for Pallet<T> {
fn on_validation_data(_data: &PersistedValidationData) {}
fn on_validation_code_applied() {
crate::Pallet::<T>::set_pending_custom_validation_head_data();
}
}
/// Ensure that signed transactions are only valid if they are signed by root.
#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo, Default)]
#[scale_info(skip_type_params(T))]
pub struct CheckSudo<T: Config + Send + Sync>(sp_std::marker::PhantomData<T>);
impl<T: Config + Send + Sync> CheckSudo<T> {
pub fn new() -> Self {
Self(Default::default())
}
}
impl<T: Config + Send + Sync> sp_std::fmt::Debug for CheckSudo<T> {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "CheckSudo")
}
#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
Ok(())
}
}
impl<T: Config + Send + Sync> SignedExtension for CheckSudo<T>
where
<T as frame_system::Config>::Call: Dispatchable<Info = DispatchInfo>,
{
type AccountId = T::AccountId;
type Call = <T as frame_system::Config>::Call;
type AdditionalSigned = ();
type Pre = ();
const IDENTIFIER: &'static str = "CheckSudo";
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {
Ok(())
}
fn pre_dispatch(
self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
Ok(self.validate(who, call, info, len).map(|_| ())?)
}
fn validate(
&self,
who: &Self::AccountId,
_call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
_len: usize,
) -> TransactionValidity {
let root_account = match pallet_sudo::Pallet::<T>::key() {
Some(account) => account,
None => return Err(InvalidTransaction::BadSigner.into()),
};
if *who == root_account {
Ok(ValidTransaction {
priority: info.weight as TransactionPriority,
longevity: TransactionLongevity::max_value(),
propagate: true,
..Default::default()
})
} else {
Err(InvalidTransaction::BadSigner.into())
}
}
}
}
+2 -2
View File
@@ -5,8 +5,8 @@ name = "cumulus-pallet-xcm"
version = "0.1.0"
[dependencies]
codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = ["derive"] }
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.132", optional = true, features = ["derive"] }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
+2 -2
View File
@@ -117,7 +117,7 @@ impl<T: Config> DmpMessageHandler for UnlimitedDmpExecution<T> {
let id = sp_io::hashing::twox_64(&data[..]);
let msg = VersionedXcm::<T::Call>::decode_all_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut &data[..],
&mut data.as_slice(),
)
.map(Xcm::<T::Call>::try_from);
match msg {
@@ -150,7 +150,7 @@ impl<T: Config> DmpMessageHandler for LimitAndDropDmpExecution<T> {
let id = sp_io::hashing::twox_64(&data[..]);
let msg = VersionedXcm::<T::Call>::decode_all_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut &data[..],
&mut data.as_slice(),
)
.map(Xcm::<T::Call>::try_from);
match msg {
+30 -16
View File
@@ -5,43 +5,57 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[dependencies]
# Other dependencies
codec = { package = "parity-scale-codec", version = "2.3.0", features = [ "derive" ], default-features = false }
rand_chacha = { version = "0.3.0", default-features = false }
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ], default-features = false }
log = { version = "0.4.14", default-features = false }
rand_chacha = { version = "0.3.0", default-features = false }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
# Substrate Dependencies
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Substrate
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Polkadot Dependencies
# Polkadot
xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
# Cumulus Dependencies
# Cumulus
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
# Optional import for benchmarking
frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "master" }
[dev-dependencies]
# Substrate
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" }
cumulus-pallet-parachain-system = { path = "../parachain-system" }
xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot
xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus
cumulus-pallet-parachain-system = { path = "../parachain-system" }
[features]
default = [ "std" ]
std = [
"codec/std",
"log/std",
"scale-info/std",
"sp-std/std",
"sp-runtime/std",
"cumulus-primitives-core/std",
"frame-support/std",
"frame-system/std",
"cumulus-primitives-core/std",
"xcm/std",
"log/std",
"sp-runtime/std",
"sp-std/std",
"xcm-executor/std",
"xcm/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
]
+28
View File
@@ -0,0 +1,28 @@
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Benchmarking setup for cumulus-pallet-xcmp-queue
use crate::*;
use frame_benchmarking::{benchmarks, impl_benchmark_test_suite};
use frame_system::RawOrigin;
benchmarks! {
set_config_with_u32 {}: update_resume_threshold(RawOrigin::Root, 100)
set_config_with_weight {}: update_weight_restrict_decay(RawOrigin::Root, 3_000_000 as Weight)
}
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
+173 -32
View File
@@ -33,12 +33,20 @@ mod mock;
#[cfg(test)]
mod tests;
use codec::{Decode, DecodeAll, DecodeLimit, Encode};
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
pub mod weights;
pub use weights::WeightInfo;
use codec::{Decode, DecodeLimit, Encode};
use cumulus_primitives_core::{
relay_chain::BlockNumber as RelayBlockNumber, ChannelStatus, GetChannelInfo, MessageSendError,
ParaId, XcmpMessageFormat, XcmpMessageHandler, XcmpMessageSource,
};
use frame_support::weights::{constants::WEIGHT_PER_MILLIS, Weight};
use frame_support::{
traits::EnsureOrigin,
weights::{constants::WEIGHT_PER_MILLIS, Weight},
};
use rand_chacha::{
rand_core::{RngCore, SeedableRng},
ChaChaRng,
@@ -47,6 +55,7 @@ use scale_info::TypeInfo;
use sp_runtime::{traits::Hash, RuntimeDebug};
use sp_std::{convert::TryFrom, prelude::*};
use xcm::{latest::prelude::*, VersionedXcm, WrapVersion, MAX_XCM_DECODE_DEPTH};
use xcm_executor::traits::ConvertOrigin;
pub use pallet::*;
@@ -64,6 +73,7 @@ pub mod pallet {
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
#[pallet::storage_version(migration::STORAGE_VERSION)]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);
#[pallet::config]
@@ -81,6 +91,16 @@ pub mod pallet {
/// The origin that is allowed to execute overweight messages.
type ExecuteOverweightOrigin: EnsureOrigin<Self::Origin>;
/// The origin that is allowed to resume or suspend the XCMP queue.
type ControllerOrigin: EnsureOrigin<Self::Origin>;
/// The conversion function used to attempt to convert an XCM `MultiLocation` origin to a
/// superuser origin.
type ControllerOriginConverter: ConvertOrigin<Self::Origin>;
/// The weight information of this pallet.
type WeightInfo: WeightInfo;
}
#[pallet::hooks]
@@ -110,7 +130,7 @@ pub mod pallet {
///
/// Events:
/// - `OverweightServiced`: On success.
#[pallet::weight(weight_limit.saturating_add(1_000_000))]
#[pallet::weight((weight_limit.saturating_add(1_000_000), DispatchClass::Operational,))]
pub fn service_overweight(
origin: OriginFor<T>,
index: OverweightIndex,
@@ -120,15 +140,123 @@ pub mod pallet {
let (sender, sent_at, data) =
Overweight::<T>::get(index).ok_or(Error::<T>::BadOverweightIndex)?;
let xcm =
VersionedXcm::<T::Call>::decode_all_with_depth_limit(MAX_XCM_DECODE_DEPTH, &data)
.map_err(|_| Error::<T>::BadXcm)?;
let xcm = VersionedXcm::<T::Call>::decode_all_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut data.as_slice(),
)
.map_err(|_| Error::<T>::BadXcm)?;
let used = Self::handle_xcm_message(sender, sent_at, xcm, weight_limit)
.map_err(|_| Error::<T>::WeightOverLimit)?;
Overweight::<T>::remove(index);
Self::deposit_event(Event::OverweightServiced(index, used));
Ok(Some(used.saturating_add(1_000_000)).into())
}
/// Suspends all XCM executions for the XCMP queue, regardless of the sender's origin.
///
/// - `origin`: Must pass `ControllerOrigin`.
#[pallet::weight((T::DbWeight::get().writes(1), DispatchClass::Operational,))]
pub fn suspend_xcm_execution(origin: OriginFor<T>) -> DispatchResult {
T::ControllerOrigin::ensure_origin(origin)?;
QueueSuspended::<T>::put(true);
Ok(())
}
/// Resumes all XCM executions for the XCMP queue.
///
/// Note that this function doesn't change the status of the in/out bound channels.
///
/// - `origin`: Must pass `ControllerOrigin`.
#[pallet::weight((T::DbWeight::get().writes(1), DispatchClass::Operational,))]
pub fn resume_xcm_execution(origin: OriginFor<T>) -> DispatchResult {
T::ControllerOrigin::ensure_origin(origin)?;
QueueSuspended::<T>::put(false);
Ok(())
}
/// Overwrites the number of pages of messages which must be in the queue for the other side to be told to
/// suspend their sending.
///
/// - `origin`: Must pass `Root`.
/// - `new`: Desired value for `QueueConfigData.suspend_value`
#[pallet::weight((T::WeightInfo::set_config_with_u32(), DispatchClass::Operational,))]
pub fn update_suspend_threshold(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
QueueConfig::<T>::mutate(|data| data.suspend_threshold = new);
Ok(())
}
/// Overwrites the number of pages of messages which must be in the queue after which we drop any further
/// messages from the channel.
///
/// - `origin`: Must pass `Root`.
/// - `new`: Desired value for `QueueConfigData.drop_threshold`
#[pallet::weight((T::WeightInfo::set_config_with_u32(),DispatchClass::Operational,))]
pub fn update_drop_threshold(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
QueueConfig::<T>::mutate(|data| data.drop_threshold = new);
Ok(())
}
/// Overwrites the number of pages of messages which the queue must be reduced to before it signals that
/// message sending may recommence after it has been suspended.
///
/// - `origin`: Must pass `Root`.
/// - `new`: Desired value for `QueueConfigData.resume_threshold`
#[pallet::weight((T::WeightInfo::set_config_with_u32(), DispatchClass::Operational,))]
pub fn update_resume_threshold(origin: OriginFor<T>, new: u32) -> DispatchResult {
ensure_root(origin)?;
QueueConfig::<T>::mutate(|data| data.resume_threshold = new);
Ok(())
}
/// Overwrites the amount of remaining weight under which we stop processing messages.
///
/// - `origin`: Must pass `Root`.
/// - `new`: Desired value for `QueueConfigData.threshold_weight`
#[pallet::weight((T::WeightInfo::set_config_with_weight(), DispatchClass::Operational,))]
pub fn update_threshold_weight(origin: OriginFor<T>, new: Weight) -> DispatchResult {
ensure_root(origin)?;
QueueConfig::<T>::mutate(|data| data.threshold_weight = new);
Ok(())
}
/// Overwrites the speed to which the available weight approaches the maximum weight.
/// A lower number results in a faster progression. A value of 1 makes the entire weight available initially.
///
/// - `origin`: Must pass `Root`.
/// - `new`: Desired value for `QueueConfigData.weight_restrict_decay`.
#[pallet::weight((T::WeightInfo::set_config_with_weight(), DispatchClass::Operational,))]
pub fn update_weight_restrict_decay(origin: OriginFor<T>, new: Weight) -> DispatchResult {
ensure_root(origin)?;
QueueConfig::<T>::mutate(|data| data.weight_restrict_decay = new);
Ok(())
}
/// Overwrite the maximum amount of weight any individual message may consume.
/// Messages above this weight go into the overweight queue and may only be serviced explicitly.
///
/// - `origin`: Must pass `Root`.
/// - `new`: Desired value for `QueueConfigData.xcmp_max_individual_weight`.
#[pallet::weight((T::WeightInfo::set_config_with_weight(), DispatchClass::Operational,))]
pub fn update_xcmp_max_individual_weight(
origin: OriginFor<T>,
new: Weight,
) -> DispatchResult {
ensure_root(origin)?;
QueueConfig::<T>::mutate(|data| data.xcmp_max_individual_weight = new);
Ok(())
}
}
#[pallet::event]
@@ -220,6 +348,10 @@ pub mod pallet {
/// available free overweight index.
#[pallet::storage]
pub(super) type OverweightCount<T: Config> = StorageValue<_, OverweightIndex, ValueQuery>;
/// Whether or not the XCMP queue is suspended from executing incoming XCMs or not.
#[pallet::storage]
pub(super) type QueueSuspended<T: Config> = StorageValue<_, bool, ValueQuery>;
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, TypeInfo)]
@@ -370,10 +502,8 @@ impl<T: Config> Pallet<T> {
let have_active = s[index].last_index > s[index].first_index;
let appended = have_active &&
<OutboundXcmpMessages<T>>::mutate(recipient, s[index].last_index - 1, |s| {
if XcmpMessageFormat::decode_and_advance_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut &s[..],
) != Ok(format)
if XcmpMessageFormat::decode_with_depth_limit(MAX_XCM_DECODE_DEPTH, &mut &s[..]) !=
Ok(format)
{
return false
}
@@ -497,7 +627,7 @@ impl<T: Config> Pallet<T> {
XcmpMessageFormat::ConcatenatedVersionedXcm => {
while !remaining_fragments.is_empty() {
last_remaining_fragments = remaining_fragments;
if let Ok(xcm) = VersionedXcm::<T::Call>::decode_and_advance_with_depth_limit(
if let Ok(xcm) = VersionedXcm::<T::Call>::decode_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut remaining_fragments,
) {
@@ -538,26 +668,24 @@ impl<T: Config> Pallet<T> {
XcmpMessageFormat::ConcatenatedEncodedBlob => {
while !remaining_fragments.is_empty() {
last_remaining_fragments = remaining_fragments;
match <Vec<u8>>::decode_all(&mut remaining_fragments) {
Ok(blob) if remaining_fragments.len() < last_remaining_fragments.len() => {
let weight = max_weight - weight_used;
match Self::handle_blob_message(sender, sent_at, blob, weight) {
Ok(used) => weight_used = weight_used.saturating_add(used),
Err(true) => {
// That message didn't get processed this time because of being
// too heavy. We leave it around for next time and bail.
remaining_fragments = last_remaining_fragments;
break
},
Err(false) => {
// Message invalid; don't attempt to retry
},
}
},
_ => {
debug_assert!(false, "Invalid incoming blob message data");
remaining_fragments = &b""[..];
},
if let Ok(blob) = <Vec<u8>>::decode(&mut remaining_fragments) {
let weight = max_weight - weight_used;
match Self::handle_blob_message(sender, sent_at, blob, weight) {
Ok(used) => weight_used = weight_used.saturating_add(used),
Err(true) => {
// That message didn't get processed this time because of being
// too heavy. We leave it around for next time and bail.
remaining_fragments = last_remaining_fragments;
break
},
Err(false) => {
// Message invalid; don't attempt to retry
},
}
} else {
debug_assert!(false, "Invalid incoming blob message data");
remaining_fragments = &b""[..];
}
}
},
@@ -619,6 +747,8 @@ impl<T: Config> Pallet<T> {
/// for the second &c. though empirical and or practical factors may give rise to adjusting it
/// further.
fn service_xcmp_queue(max_weight: Weight) -> Weight {
let suspended = QueueSuspended::<T>::get();
let mut status = <InboundXcmpStatus<T>>::get(); // <- sorted.
if status.len() == 0 {
return 0
@@ -650,6 +780,17 @@ impl<T: Config> Pallet<T> {
{
let index = shuffled[shuffle_index];
let sender = status[index].sender;
let sender_origin = T::ControllerOriginConverter::convert_origin(
(1, Parachain(sender.into())),
OriginKind::Superuser,
);
let is_controller = sender_origin
.map_or(false, |origin| T::ControllerOrigin::try_origin(origin).is_ok());
if suspended && !is_controller {
shuffle_index += 1;
continue
}
if weight_available != max_weight {
// Get incrementally closer to freeing up max_weight for message execution over the
@@ -760,7 +901,7 @@ impl<T: Config> XcmpMessageHandler for Pallet<T> {
for (sender, sent_at, data) in iter {
// Figure out the message format.
let mut data_ref = data;
let format = match XcmpMessageFormat::decode_and_advance_with_depth_limit(
let format = match XcmpMessageFormat::decode_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut data_ref,
) {
+33 -4
View File
@@ -15,16 +15,20 @@
use super::*;
use crate as xcmp_queue;
use frame_support::parameter_types;
use core::marker::PhantomData;
use cumulus_primitives_core::{IsSystem, ParaId};
use frame_support::{parameter_types, traits::OriginTrait};
use frame_system::EnsureRoot;
use sp_core::H256;
use sp_runtime::{
testing::Header,
traits::{BlakeTwo256, IdentityLookup},
};
use xcm::prelude::*;
use xcm_builder::{
CurrencyAdapter, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, ParentIsDefault,
CurrencyAdapter, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, ParentIsPreset,
};
use xcm_executor::traits::ConvertOrigin;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
@@ -98,7 +102,7 @@ impl pallet_balances::Config for Test {
impl cumulus_pallet_parachain_system::Config for Test {
type Event = Event;
type OnValidationData = ();
type OnSystemEvent = ();
type SelfParaId = ();
type OutboundXcmpMessageSource = XcmpQueue;
type DmpMessageHandler = ();
@@ -129,7 +133,7 @@ pub type LocalAssetTransactor = CurrencyAdapter<
(),
>;
pub type LocationToAccountId = (ParentIsDefault<AccountId>,);
pub type LocationToAccountId = (ParentIsPreset<AccountId>,);
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
@@ -157,12 +161,37 @@ pub type XcmRouter = (
XcmpQueue,
);
pub struct SystemParachainAsSuperuser<Origin>(PhantomData<Origin>);
impl<Origin: OriginTrait> ConvertOrigin<Origin> for SystemParachainAsSuperuser<Origin> {
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<Origin, MultiLocation> {
let origin = origin.into();
if kind == OriginKind::Superuser &&
matches!(
origin,
MultiLocation {
parents: 1,
interior: X1(Parachain(id)),
} if ParaId::from(id).is_system(),
) {
Ok(Origin::root())
} else {
Err(origin)
}
}
}
impl Config for Test {
type Event = Event;
type XcmExecutor = xcm_executor::XcmExecutor<XcmConfig>;
type ChannelInfo = ParachainSystem;
type VersionWrapper = ();
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
type ControllerOrigin = EnsureRoot<AccountId>;
type ControllerOriginConverter = SystemParachainAsSuperuser<Origin>;
type WeightInfo = ();
}
pub fn new_test_ext() -> sp_io::TestExternalities {
+117 -5
View File
@@ -15,8 +15,9 @@
use super::*;
use cumulus_primitives_core::XcmpMessageHandler;
use frame_support::assert_noop;
use mock::{new_test_ext, Origin, Test, XcmpQueue};
use frame_support::{assert_noop, assert_ok};
use mock::{new_test_ext, Call, Origin, Test, XcmpQueue};
use sp_runtime::traits::BadOrigin;
#[test]
fn one_message_does_not_panic() {
@@ -46,10 +47,12 @@ fn bad_message_is_handled() {
});
}
/// Tests that a blob message is handled. Currently this isn't implemented and panics when debug assertions
/// are enabled. When this feature is enabled, this test should be rewritten properly.
#[test]
#[should_panic = "Invalid incoming blob message data"]
#[should_panic = "Blob messages not handled."]
#[cfg(debug_assertions)]
fn other_bad_message_is_handled() {
fn handle_blob_message() {
new_test_ext().execute_with(|| {
let bad_data = vec![
1, 1, 1, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 64, 239,
@@ -58,7 +61,6 @@ fn other_bad_message_is_handled() {
];
InboundXcmpMessages::<Test>::insert(ParaId::from(1000), 1, bad_data);
let format = XcmpMessageFormat::ConcatenatedEncodedBlob;
// This should exit with an error.
XcmpQueue::process_xcmp_message(1000.into(), (1, format), 10_000_000_000, 10_000_000_000);
});
}
@@ -82,3 +84,113 @@ fn service_overweight_bad_xcm_format() {
assert_noop!(XcmpQueue::service_overweight(Origin::root(), 0, 1000), Error::<Test>::BadXcm);
});
}
#[test]
fn suspend_xcm_execution_works() {
new_test_ext().execute_with(|| {
QueueSuspended::<Test>::put(true);
let xcm = VersionedXcm::from(Xcm::<Call>(vec![Instruction::<Call>::ClearOrigin])).encode();
let mut message_format = XcmpMessageFormat::ConcatenatedVersionedXcm.encode();
message_format.extend(xcm.clone());
let messages = vec![(ParaId::from(999), 1u32.into(), message_format.as_slice())];
// This should have executed the incoming XCM, because it came from a system parachain
XcmpQueue::handle_xcmp_messages(messages.into_iter(), Weight::max_value());
let queued_xcm = InboundXcmpMessages::<Test>::get(ParaId::from(999), 1u32);
assert!(queued_xcm.is_empty());
let messages = vec![(ParaId::from(2000), 1u32.into(), message_format.as_slice())];
// This shouldn't have executed the incoming XCM
XcmpQueue::handle_xcmp_messages(messages.into_iter(), Weight::max_value());
let queued_xcm = InboundXcmpMessages::<Test>::get(ParaId::from(2000), 1u32);
assert_eq!(queued_xcm, xcm);
});
}
#[test]
fn update_suspend_threshold_works() {
new_test_ext().execute_with(|| {
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.suspend_threshold, 2);
assert_ok!(XcmpQueue::update_suspend_threshold(Origin::root(), 3));
assert_noop!(XcmpQueue::update_suspend_threshold(Origin::signed(2), 5), BadOrigin);
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.suspend_threshold, 3);
});
}
#[test]
fn update_drop_threshold_works() {
new_test_ext().execute_with(|| {
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.drop_threshold, 5);
assert_ok!(XcmpQueue::update_drop_threshold(Origin::root(), 6));
assert_noop!(XcmpQueue::update_drop_threshold(Origin::signed(2), 7), BadOrigin);
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.drop_threshold, 6);
});
}
#[test]
fn update_resume_threshold_works() {
new_test_ext().execute_with(|| {
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.resume_threshold, 1);
assert_ok!(XcmpQueue::update_resume_threshold(Origin::root(), 2));
assert_noop!(XcmpQueue::update_resume_threshold(Origin::signed(7), 3), BadOrigin);
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.resume_threshold, 2);
});
}
#[test]
fn update_threshold_weight_works() {
new_test_ext().execute_with(|| {
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.threshold_weight, 100_000);
assert_ok!(XcmpQueue::update_threshold_weight(Origin::root(), 10_000));
assert_noop!(XcmpQueue::update_threshold_weight(Origin::signed(5), 10_000_000), BadOrigin);
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.threshold_weight, 10_000);
});
}
#[test]
fn update_weight_restrict_decay_works() {
new_test_ext().execute_with(|| {
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.weight_restrict_decay, 2);
assert_ok!(XcmpQueue::update_weight_restrict_decay(Origin::root(), 5));
assert_noop!(XcmpQueue::update_weight_restrict_decay(Origin::signed(6), 4), BadOrigin);
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.weight_restrict_decay, 5);
});
}
#[test]
fn update_xcmp_max_individual_weight() {
new_test_ext().execute_with(|| {
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.xcmp_max_individual_weight, 20 * WEIGHT_PER_MILLIS);
assert_ok!(XcmpQueue::update_xcmp_max_individual_weight(
Origin::root(),
30 * WEIGHT_PER_MILLIS
));
assert_noop!(
XcmpQueue::update_xcmp_max_individual_weight(Origin::signed(3), 10 * WEIGHT_PER_MILLIS),
BadOrigin
);
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.xcmp_max_individual_weight, 30 * WEIGHT_PER_MILLIS);
});
}
+48
View File
@@ -0,0 +1,48 @@
#![allow(unused_parens)]
#![allow(unused_imports)]
use frame_support::{
traits::Get,
weights::{constants::RocksDbWeight, Weight},
};
use sp_std::marker::PhantomData;
// Implemented by autogenerated benchmarking code.
pub trait WeightInfo {
fn set_config_with_u32() -> Weight;
fn set_config_with_weight() -> Weight;
}
pub struct SubstrateWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
// Storage: XcmpQueue QueueConfig (r:1 w:1)
fn set_config_with_u32() -> Weight {
(2_717_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: XcmpQueue QueueConfig (r:1 w:1)
fn set_config_with_weight() -> Weight {
(2_717_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
}
impl WeightInfo for () {
// Storage: XcmpQueue QueueConfig (r:1 w:1)
fn set_config_with_u32() -> Weight {
(2_717_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: XcmpQueue QueueConfig (r:1 w:1)
fn set_config_with_weight() -> Weight {
(2_717_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
}
+32 -38
View File
@@ -9,62 +9,41 @@ repository = "https://github.com/paritytech/cumulus/"
edition = "2021"
build = "build.rs"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[build-dependencies]
substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
[[bin]]
name = "parachain-collator"
path = "src/main.rs"
[features]
runtime-benchmarks = ["parachain-template-runtime/runtime-benchmarks"]
try-runtime = [ "parachain-template-runtime/try-runtime" ]
[dependencies]
clap = { version = "3.1", features = ["derive"] }
derive_more = "0.99.2"
log = "0.4.14"
codec = { package = "parity-scale-codec", version = "2.0.0" }
structopt = "0.3.8"
codec = { package = "parity-scale-codec", version = "3.0.0" }
serde = { version = "1.0.132", features = ["derive"] }
hex-literal = "0.3.1"
# RPC related Dependencies
hex-literal = "0.3.4"
jsonrpc-core = "18.0.0"
# Local Dependencies
# Local
parachain-template-runtime = { path = "../runtime" }
# Substrate Dependencies
# Substrate
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
try-runtime-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" }
## Substrate Client Dependencies
sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] }
sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", features = ["wasmtime"] , branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] }
sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
## Substrate Primitive Dependencies
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -78,8 +57,18 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master
sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" }
try-runtime-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Cumulus dependencies
# Polkadot
polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
# Cumulus
cumulus-client-cli = { path = "../../client/cli" }
cumulus-client-collator = { path = "../../client/collator" }
cumulus-client-consensus-aura = { path = "../../client/consensus/aura" }
@@ -88,12 +77,17 @@ cumulus-client-network = { path = "../../client/network" }
cumulus-client-service = { path = "../../client/service" }
cumulus-primitives-core = { path = "../../primitives/core" }
cumulus-primitives-parachain-inherent = { path = "../../primitives/parachain-inherent" }
cumulus-relay-chain-inprocess-interface = { path = "../../client/relay-chain-inprocess-interface" }
cumulus-relay-chain-interface = { path = "../../client/relay-chain-interface" }
cumulus-relay-chain-local = { path = "../../client/relay-chain-local" }
cumulus-relay-chain-rpc-interface = { path = "../../client/relay-chain-rpc-interface" }
# Polkadot dependencies
polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
[build-dependencies]
substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
[features]
default = []
runtime-benchmarks = [
"parachain-template-runtime/runtime-benchmarks",
"polkadot-cli/runtime-benchmarks",
]
try-runtime = ["parachain-template-runtime/try-runtime"]
@@ -10,6 +10,9 @@ use sp_runtime::traits::{IdentifyAccount, Verify};
pub type ChainSpec =
sc_service::GenericChainSpec<parachain_template_runtime::GenesisConfig, Extensions>;
/// The default XCM version to set in genesis config.
const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION;
/// Helper function to generate a crypto pair from seed
pub fn get_public_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
TPublic::Pair::from_string(&format!("//{}", seed), None)
@@ -105,6 +108,7 @@ pub fn development_config() -> ChainSpec {
None,
None,
None,
None,
Extensions {
relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
para_id: 1000,
@@ -161,6 +165,8 @@ pub fn local_testnet_config() -> ChainSpec {
None,
// Protocol ID
Some("template-local"),
// Fork ID
None,
// Properties
Some(properties),
// Extensions
@@ -208,5 +214,8 @@ fn testnet_genesis(
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: parachain_template_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
}
}
+23 -23
View File
@@ -1,16 +1,16 @@
use crate::chain_spec;
use clap::Parser;
use std::path::PathBuf;
use structopt::StructOpt;
/// Sub-commands supported by the collator.
#[derive(Debug, StructOpt)]
#[derive(Debug, clap::Subcommand)]
pub enum Subcommand {
/// Export the genesis state of the parachain.
#[structopt(name = "export-genesis-state")]
#[clap(name = "export-genesis-state")]
ExportGenesisState(ExportGenesisStateCommand),
/// Export the genesis wasm of the parachain.
#[structopt(name = "export-genesis-wasm")]
#[clap(name = "export-genesis-wasm")]
ExportGenesisWasm(ExportGenesisWasmCommand),
/// Build a chain specification.
@@ -35,7 +35,7 @@ pub enum Subcommand {
Revert(sc_cli::RevertCmd),
/// The custom benchmark subcommmand benchmarking runtime pallets.
#[structopt(name = "benchmark", about = "Benchmark runtime pallets.")]
#[clap(name = "benchmark", about = "Benchmark runtime pallets.")]
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
/// Try some testing command against a specified runtime state.
@@ -43,52 +43,52 @@ pub enum Subcommand {
}
/// Command for exporting the genesis state of the parachain
#[derive(Debug, StructOpt)]
#[derive(Debug, Parser)]
pub struct ExportGenesisStateCommand {
/// Output file name or stdout if unspecified.
#[structopt(parse(from_os_str))]
#[clap(parse(from_os_str))]
pub output: Option<PathBuf>,
/// Write output in binary. Default is to write in hex.
#[structopt(short, long)]
#[clap(short, long)]
pub raw: bool,
/// The name of the chain for that the genesis state should be exported.
#[structopt(long)]
#[clap(long)]
pub chain: Option<String>,
}
/// Command for exporting the genesis wasm file.
#[derive(Debug, StructOpt)]
#[derive(Debug, Parser)]
pub struct ExportGenesisWasmCommand {
/// Output file name or stdout if unspecified.
#[structopt(parse(from_os_str))]
#[clap(parse(from_os_str))]
pub output: Option<PathBuf>,
/// Write output in binary. Default is to write in hex.
#[structopt(short, long)]
#[clap(short, long)]
pub raw: bool,
/// The name of the chain for that the genesis wasm file should be exported.
#[structopt(long)]
#[clap(long)]
pub chain: Option<String>,
}
#[derive(Debug, StructOpt)]
#[structopt(settings = &[
structopt::clap::AppSettings::GlobalVersion,
structopt::clap::AppSettings::ArgsNegateSubcommands,
structopt::clap::AppSettings::SubcommandsNegateReqs,
])]
#[derive(Debug, Parser)]
#[clap(
propagate_version = true,
args_conflicts_with_subcommands = true,
subcommand_negates_reqs = true
)]
pub struct Cli {
#[structopt(subcommand)]
#[clap(subcommand)]
pub subcommand: Option<Subcommand>,
#[structopt(flatten)]
#[clap(flatten)]
pub run: cumulus_client_cli::RunCmd,
/// Relay chain arguments
#[structopt(raw = true)]
#[clap(raw = true)]
pub relay_chain_args: Vec<String>,
}
@@ -113,6 +113,6 @@ impl RelayChainCli {
let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec);
let chain_id = extension.map(|e| e.relay_chain.clone());
let base_path = para_config.base_path.as_ref().map(|x| x.path().join("polkadot"));
Self { base_path, chain_id, base: polkadot_cli::RunCmd::from_iter(relay_chain_args) }
Self { base_path, chain_id, base: polkadot_cli::RunCmd::parse_from(relay_chain_args) }
}
}
+9 -3
View File
@@ -241,7 +241,7 @@ pub fn run() -> Result<()> {
You can enable it with `--features runtime-benchmarks`."
.into())
},
Some(Subcommand::TryRuntime(cmd)) =>
Some(Subcommand::TryRuntime(cmd)) => {
if cfg!(feature = "try-runtime") {
let runner = cli.create_runner(cmd)?;
@@ -256,9 +256,11 @@ pub fn run() -> Result<()> {
})
} else {
Err("Try-runtime must be enabled by `--features try-runtime`.".into())
},
}
},
None => {
let runner = cli.create_runner(&cli.run.normalize())?;
let collator_options = cli.run.collator_options();
runner.run_node_until_exit(|config| async move {
let para_id = chain_spec::Extensions::try_get(&*config.chain_spec)
@@ -291,7 +293,7 @@ pub fn run() -> Result<()> {
info!("Parachain genesis state: {}", genesis_state);
info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" });
crate::service::start_parachain_node(config, polkadot_config, id)
crate::service::start_parachain_node(config, polkadot_config, collator_options, id)
.await
.map(|r| r.0)
.map_err(Into::into)
@@ -431,4 +433,8 @@ impl CliConfiguration<Self> for RelayChainCli {
) -> Result<Option<sc_telemetry::TelemetryEndpoints>> {
self.base.base.telemetry_endpoints(chain_spec)
}
fn node_name(&self) -> Result<String> {
self.base.base.node_name()
}
}
+55 -18
View File
@@ -3,6 +3,7 @@
// std
use std::{sync::Arc, time::Duration};
use cumulus_client_cli::CollatorOptions;
// Local Runtime Types
use parachain_template_runtime::{
opaque::Block, AccountId, Balance, Hash, Index as Nonce, RuntimeApi,
@@ -16,8 +17,9 @@ use cumulus_client_service::{
prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams,
};
use cumulus_primitives_core::ParaId;
use cumulus_relay_chain_interface::RelayChainInterface;
use cumulus_relay_chain_local::build_relay_chain_interface;
use cumulus_relay_chain_inprocess_interface::build_inprocess_relay_chain;
use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface, RelayChainResult};
use cumulus_relay_chain_rpc_interface::RelayChainRPCInterface;
// Substrate Imports
use sc_client_api::ExecutorProvider;
@@ -26,11 +28,12 @@ use sc_network::NetworkService;
use sc_service::{Configuration, PartialComponents, Role, TFullBackend, TFullClient, TaskManager};
use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};
use sp_api::ConstructRuntimeApi;
use sp_consensus::SlotData;
use sp_keystore::SyncCryptoStorePtr;
use sp_runtime::traits::BlakeTwo256;
use substrate_prometheus_endpoint::Registry;
use polkadot_service::CollatorPair;
/// Native executor instance.
pub struct TemplateRuntimeExecutor;
@@ -161,6 +164,25 @@ where
Ok(params)
}
async fn build_relay_chain_interface(
polkadot_config: Configuration,
parachain_config: &Configuration,
telemetry_worker_handle: Option<TelemetryWorkerHandle>,
task_manager: &mut TaskManager,
collator_options: CollatorOptions,
) -> RelayChainResult<(Arc<(dyn RelayChainInterface + 'static)>, Option<CollatorPair>)> {
match collator_options.relay_chain_rpc_url {
Some(relay_chain_url) =>
Ok((Arc::new(RelayChainRPCInterface::new(relay_chain_url).await?) as Arc<_>, None)),
None => build_inprocess_relay_chain(
polkadot_config,
parachain_config,
telemetry_worker_handle,
task_manager,
),
}
}
/// Start a node with the given parachain `Configuration` and relay chain `Configuration`.
///
/// This is the actual implementation that is abstract over the executor and the runtime api.
@@ -168,6 +190,7 @@ where
async fn start_node_impl<RuntimeApi, Executor, RB, BIQ, BIC>(
parachain_config: Configuration,
polkadot_config: Configuration,
collator_options: CollatorOptions,
id: ParaId,
_rpc_ext_builder: RB,
build_import_queue: BIQ,
@@ -241,12 +264,18 @@ where
let backend = params.backend.clone();
let mut task_manager = params.task_manager;
let (relay_chain_interface, collator_key) =
build_relay_chain_interface(polkadot_config, telemetry_worker_handle, &mut task_manager)
.map_err(|e| match e {
polkadot_service::Error::Sub(x) => x,
s => format!("{}", s).into(),
})?;
let (relay_chain_interface, collator_key) = build_relay_chain_interface(
polkadot_config,
&parachain_config,
telemetry_worker_handle,
&mut task_manager,
collator_options.clone(),
)
.await
.map_err(|e| match e {
RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x,
s => s.to_string().into(),
})?;
let block_announce_validator = BlockAnnounceValidator::new(relay_chain_interface.clone(), id);
@@ -301,6 +330,8 @@ where
Arc::new(move |hash, data| network.announce_block(hash, data))
};
let relay_chain_slot_duration = Duration::from_secs(6);
if validator {
let parachain_consensus = build_consensus(
client.clone(),
@@ -326,8 +357,8 @@ where
spawner,
parachain_consensus,
import_queue,
collator_key,
slot_duration: Duration::from_secs(6),
collator_key: collator_key.expect("Command line arguments do not allow this. qed"),
relay_chain_slot_duration,
};
start_collator(params).await?;
@@ -338,6 +369,9 @@ where
task_manager: &mut task_manager,
para_id: id,
relay_chain_interface,
relay_chain_slot_duration,
import_queue,
collator_options,
};
start_full_node(params)?;
@@ -379,9 +413,9 @@ pub fn parachain_build_import_queue(
let time = sp_timestamp::InherentDataProvider::from_system_time();
let slot =
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(
*time,
slot_duration.slot_duration(),
slot_duration,
);
Ok((time, slot))
@@ -398,6 +432,7 @@ pub fn parachain_build_import_queue(
pub async fn start_parachain_node(
parachain_config: Configuration,
polkadot_config: Configuration,
collator_options: CollatorOptions,
id: ParaId,
) -> sc_service::error::Result<(
TaskManager,
@@ -406,6 +441,7 @@ pub async fn start_parachain_node(
start_node_impl::<RuntimeApi, TemplateRuntimeExecutor, _, _, _>(
parachain_config,
polkadot_config,
collator_options,
id,
|_| Ok(Default::default()),
parachain_build_import_queue,
@@ -432,20 +468,21 @@ pub async fn start_parachain_node(
BuildAuraConsensusParams {
proposer_factory,
create_inherent_data_providers: move |_, (relay_parent, validation_data)| {
let parachain_inherent =
let relay_chain_interface = relay_chain_interface.clone();
async move {
let parachain_inherent =
cumulus_primitives_parachain_inherent::ParachainInherentData::create_at(
relay_parent,
&relay_chain_interface,
&validation_data,
id,
);
async move {
).await;
let time = sp_timestamp::InherentDataProvider::from_system_time();
let slot =
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(
*time,
slot_duration.slot_duration(),
slot_duration,
);
let parachain_inherent = parachain_inherent.ok_or_else(|| {
+12 -9
View File
@@ -12,18 +12,21 @@ edition = "2021"
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"], default-features = false }
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"], default-features = false }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "master" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
# Substrate
frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "master" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
[dev-dependencies]
serde = { version = "1.0.132" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
# Substrate
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
[features]
default = ["std"]
@@ -31,8 +34,8 @@ runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"]
std = [
"codec/std",
"scale-info/std",
"frame-benchmarking/std",
"frame-support/std",
"frame-system/std",
"frame-benchmarking/std",
]
try-runtime = [ "frame-support/try-runtime" ]
+73 -75
View File
@@ -15,54 +15,58 @@ targets = ["x86_64-unknown-linux-gnu"]
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
[dependencies]
hex-literal = { version = "0.3.1", optional = true }
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"]}
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
hex-literal = { version = "0.3.4", optional = true }
log = { version = "0.4.14", default-features = false }
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.132", optional = true, features = ["derive"] }
smallvec = "1.6.1"
# Local Dependencies
# Local
pallet-template = { path = "../pallets/template", default-features = false }
# Substrate Dependencies
## Substrate Primitive Dependencies
sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
## Substrate FRAME Dependencies
frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "master" }
frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "master" }
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
# Substrate
frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "master" }
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "master" }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "master" }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "master" }
pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
## Substrate Pallet Dependencies
pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
# Polkadot
pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
# Cumulus dependencies
# Cumulus
cumulus-pallet-aura-ext = { path = "../../pallets/aura-ext", default-features = false }
cumulus-pallet-dmp-queue = { path = "../../pallets/dmp-queue", default-features = false }
cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false }
cumulus-pallet-session-benchmarking = {path = "../../pallets/session-benchmarking", default-features = false, version = "3.0.0"}
cumulus-pallet-xcm = { path = "../../pallets/xcm", default-features = false }
cumulus-pallet-xcmp-queue = { path = "../../pallets/xcmp-queue", default-features = false }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
@@ -70,15 +74,6 @@ cumulus-primitives-timestamp = { path = "../../primitives/timestamp", default-fe
cumulus-primitives-utility = { path = "../../primitives/utility", default-features = false }
pallet-collator-selection = { path = "../../pallets/collator-selection", default-features = false }
parachain-info = { path = "../../polkadot-parachains/pallets/parachain-info", default-features = false }
cumulus-pallet-session-benchmarking = {path = "../../pallets/session-benchmarking", default-features = false, version = "3.0.0"}
# Polkadot Dependencies
pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" }
polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" }
xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" }
[features]
default = [
@@ -86,9 +81,35 @@ default = [
]
std = [
"codec/std",
"serde",
"scale-info/std",
"log/std",
"scale-info/std",
"serde",
"cumulus-pallet-aura-ext/std",
"cumulus-pallet-dmp-queue/std",
"cumulus-pallet-parachain-system/std",
"cumulus-pallet-xcm/std",
"cumulus-pallet-xcmp-queue/std",
"cumulus-primitives-core/std",
"cumulus-primitives-timestamp/std",
"cumulus-primitives-utility/std",
"frame-executive/std",
"frame-support/std",
"frame-system-rpc-runtime-api/std",
"frame-system/std",
"pallet-aura/std",
"pallet-authorship/std",
"pallet-balances/std",
"pallet-collator-selection/std",
"pallet-session/std",
"pallet-sudo/std",
"pallet-template/std",
"pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std",
"pallet-xcm/std",
"parachain-info/std",
"polkadot-parachain/std",
"polkadot-runtime-common/std",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-aura/std",
@@ -101,30 +122,6 @@ std = [
"sp-std/std",
"sp-transaction-pool/std",
"sp-version/std",
"frame-executive/std",
"frame-support/std",
"frame-system/std",
"pallet-aura/std",
"pallet-authorship/std",
"pallet-balances/std",
"pallet-collator-selection/std",
"pallet-session/std",
"pallet-sudo/std",
"pallet-template/std",
"pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std",
"cumulus-pallet-aura-ext/std",
"cumulus-pallet-parachain-system/std",
"cumulus-pallet-xcm/std",
"cumulus-pallet-xcmp-queue/std",
"cumulus-primitives-core/std",
"cumulus-primitives-timestamp/std",
"cumulus-primitives-utility/std",
"cumulus-pallet-dmp-queue/std",
"parachain-info/std",
"polkadot-parachain/std",
"polkadot-runtime-common/std",
"xcm-builder/std",
"xcm-executor/std",
"xcm/std",
@@ -132,21 +129,22 @@ std = [
runtime-benchmarks = [
"hex-literal",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"frame-benchmarking/runtime-benchmarks",
"frame-system-benchmarking",
"frame-support/runtime-benchmarks",
"frame-system-benchmarking",
"frame-system/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-collator-selection/runtime-benchmarks",
"pallet-template/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-xcm/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"cumulus-pallet-session-benchmarking/runtime-benchmarks",
"cumulus-pallet-xcmp-queue/runtime-benchmarks",
]
try-runtime = [
"frame-try-runtime",
"frame-executive/try-runtime",
"frame-try-runtime",
]
+35 -171
View File
@@ -6,6 +6,8 @@
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
pub mod xcm_config;
use smallvec::smallvec;
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
@@ -22,11 +24,11 @@ use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use frame_support::{
construct_runtime, match_type, parameter_types,
traits::{Everything, Nothing},
construct_runtime, parameter_types,
traits::Everything,
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND},
DispatchClass, IdentityFee, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients,
DispatchClass, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients,
WeightToFeePolynomial,
},
PalletId,
@@ -37,25 +39,17 @@ use frame_system::{
};
pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
pub use sp_runtime::{MultiAddress, Perbill, Permill};
use xcm_config::{XcmConfig, XcmOriginToTransactDispatchOrigin};
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
// Polkadot Imports
use pallet_xcm::XcmPassthrough;
use polkadot_parachain::primitives::Sibling;
use polkadot_runtime_common::{BlockHashCount, RocksDbWeight, SlowAdjustingFeeUpdate};
// XCM Imports
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, ParentIsDefault,
RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
UsingComponents,
};
use xcm_executor::{Config, XcmExecutor};
use xcm::latest::prelude::BodyId;
use xcm_executor::XcmExecutor;
/// Import the template pallet.
pub use pallet_template;
@@ -371,7 +365,7 @@ parameter_types! {
impl cumulus_pallet_parachain_system::Config for Runtime {
type Event = Event;
type OnValidationData = ();
type OnSystemEvent = ();
type SelfParaId = parachain_info::Pallet<Runtime>;
type DmpMessageHandler = DmpQueue;
type ReservedDmpWeight = ReservedDmpWeight;
@@ -384,150 +378,15 @@ impl parachain_info::Config for Runtime {}
impl cumulus_pallet_aura_ext::Config for Runtime {}
parameter_types! {
pub const RelayLocation: MultiLocation = MultiLocation::parent();
pub const RelayNetwork: NetworkId = NetworkId::Any;
pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
}
/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
/// `Transact` in order to determine the dispatch Origin.
pub type LocationToAccountId = (
// The parent (Relay-chain) origin converts to the default `AccountId`.
ParentIsDefault<AccountId>,
// Sibling parachain origins convert to AccountId via the `ParaId::into`.
SiblingParachainConvertsVia<Sibling, AccountId>,
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
AccountId32Aliases<RelayNetwork, AccountId>,
);
/// Means for transacting assets on this chain.
pub type LocalAssetTransactor = CurrencyAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
IsConcrete<RelayLocation>,
// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We don't track any teleports.
(),
>;
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
/// biases the kind of local `Origin` it will become.
pub type XcmOriginToTransactDispatchOrigin = (
// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
// foreign chains who want to have a local sovereign account on this chain which they control.
SovereignSignedViaLocation<LocationToAccountId, Origin>,
// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
// recognized.
RelayChainAsNative<RelayChainOrigin, Origin>,
// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
// recognized.
SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,
// Native signed account converter; this just converts an `AccountId32` origin into a normal
// `Origin::Signed` origin of the same 32-byte value.
SignedAccountId32AsNative<RelayNetwork, Origin>,
// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
XcmPassthrough<Origin>,
);
parameter_types! {
// One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate.
pub UnitWeightCost: Weight = 1_000_000_000;
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64;
}
match_type! {
pub type ParentOrParentsExecutivePlurality: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) }
};
}
pub type Barrier = (
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom<Everything>,
AllowUnpaidExecutionFrom<ParentOrParentsExecutivePlurality>,
// ^^^ Parent and its exec plurality get free execution
);
pub struct XcmConfig;
impl Config for XcmConfig {
type Call = Call;
type XcmSender = XcmRouter;
// How to withdraw and deposit an asset.
type AssetTransactor = LocalAssetTransactor;
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = NativeAsset;
type IsTeleporter = (); // Teleporting is disabled.
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
type Trader = UsingComponents<IdentityFee<Balance>, RelayLocation, AccountId, Balances, ()>;
type ResponseHandler = PolkadotXcm;
type AssetTrap = PolkadotXcm;
type AssetClaims = PolkadotXcm;
type SubscriptionService = PolkadotXcm;
type PalletInstancesInfo = ();
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
}
parameter_types! {
pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;
}
/// No local origins on this chain are allowed to dispatch XCM sends/executions.
pub type LocalOriginToLocation = SignedToAccountId32<Origin, AccountId, RelayNetwork>;
/// The means for routing XCM messages which are not for local execution into the right message
/// queues.
pub type XcmRouter = (
// Two routers - use UMP to communicate with the relay chain:
cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,
// ..and XCMP to communicate with the sibling chains.
XcmpQueue,
);
impl pallet_xcm::Config for Runtime {
type Event = Event;
type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
type XcmRouter = XcmRouter;
type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
type XcmExecuteFilter = Nothing;
// ^ Disable dispatchable execute on the XCM pallet.
// Needs to be `Everything` for local testing.
type XcmExecutor = XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Nothing;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
type LocationInverter = LocationInverter<Ancestry>;
type Origin = Origin;
type Call = Call;
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
// ^ Override for AdvertisedXcmVersion default
type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
}
impl cumulus_pallet_xcm::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
}
impl cumulus_pallet_xcmp_queue::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
type ChannelInfo = ParachainSystem;
type VersionWrapper = ();
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
type ControllerOrigin = EnsureRoot<AccountId>;
type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
type WeightInfo = ();
}
impl cumulus_pallet_dmp_queue::Config for Runtime {
@@ -623,7 +482,7 @@ construct_runtime!(
// XCM helpers.
XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 30,
PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 31,
PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin, Config} = 31,
CumulusXcm: cumulus_pallet_xcm::{Pallet, Event<T>, Origin} = 32,
DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 33,
@@ -632,6 +491,22 @@ construct_runtime!(
}
);
#[cfg(feature = "runtime-benchmarks")]
#[macro_use]
extern crate frame_benchmarking;
#[cfg(feature = "runtime-benchmarks")]
mod benches {
define_benchmarks!(
[frame_system, SystemBench::<Runtime>]
[pallet_balances, Balances]
[pallet_session, SessionBench::<Runtime>]
[pallet_timestamp, Timestamp]
[pallet_collator_selection, CollatorSelection]
[cumulus_pallet_xcmp_queue, XcmpQueue]
);
}
impl_runtime_apis! {
impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
fn slot_duration() -> sp_consensus_aura::SlotDuration {
@@ -734,8 +609,8 @@ impl_runtime_apis! {
}
impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
fn collect_collation_info() -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info()
fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info(header)
}
}
@@ -758,28 +633,22 @@ impl_runtime_apis! {
Vec<frame_benchmarking::BenchmarkList>,
Vec<frame_support::traits::StorageInfo>,
) {
use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};
use frame_benchmarking::{Benchmarking, BenchmarkList};
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
let mut list = Vec::<BenchmarkList>::new();
list_benchmark!(list, extra, frame_system, SystemBench::<Runtime>);
list_benchmark!(list, extra, pallet_balances, Balances);
list_benchmark!(list, extra, pallet_session, SessionBench::<Runtime>);
list_benchmark!(list, extra, pallet_timestamp, Timestamp);
list_benchmark!(list, extra, pallet_collator_selection, CollatorSelection);
list_benchmarks!(list, extra);
let storage_info = AllPalletsWithSystem::storage_info();
return (list, storage_info)
}
fn dispatch_benchmark(
config: frame_benchmarking::BenchmarkConfig
) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {
use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};
use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey};
use frame_system_benchmarking::Pallet as SystemBench;
impl frame_system_benchmarking::Config for Runtime {}
@@ -802,12 +671,7 @@ impl_runtime_apis! {
let mut batches = Vec::<BenchmarkBatch>::new();
let params = (&config, &whitelist);
add_benchmark!(params, batches, frame_system, SystemBench::<Runtime>);
add_benchmark!(params, batches, pallet_balances, Balances);
add_benchmark!(params, batches, pallet_session, SessionBench::<Runtime>);
add_benchmark!(params, batches, pallet_timestamp, Timestamp);
add_benchmark!(params, batches, pallet_collator_selection, CollatorSelection);
add_benchmarks!(params, batches);
if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
Ok(batches)
@@ -0,0 +1,156 @@
use super::{
AccountId, Balances, Call, Event, Origin, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime,
WeightToFee, XcmpQueue,
};
use frame_support::{
match_types, parameter_types,
traits::{Everything, Nothing},
weights::Weight,
};
use pallet_xcm::XcmPassthrough;
use polkadot_parachain::primitives::Sibling;
use polkadot_runtime_common::impls::ToAuthor;
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, ParentIsPreset,
RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
UsingComponents,
};
use xcm_executor::XcmExecutor;
parameter_types! {
pub const RelayLocation: MultiLocation = MultiLocation::parent();
pub const RelayNetwork: NetworkId = NetworkId::Any;
pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
}
/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
/// `Transact` in order to determine the dispatch Origin.
pub type LocationToAccountId = (
// The parent (Relay-chain) origin converts to the parent `AccountId`.
ParentIsPreset<AccountId>,
// Sibling parachain origins convert to AccountId via the `ParaId::into`.
SiblingParachainConvertsVia<Sibling, AccountId>,
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
AccountId32Aliases<RelayNetwork, AccountId>,
);
/// Means for transacting assets on this chain.
pub type LocalAssetTransactor = CurrencyAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
IsConcrete<RelayLocation>,
// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We don't track any teleports.
(),
>;
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
/// biases the kind of local `Origin` it will become.
pub type XcmOriginToTransactDispatchOrigin = (
// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
// foreign chains who want to have a local sovereign account on this chain which they control.
SovereignSignedViaLocation<LocationToAccountId, Origin>,
// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
// recognized.
RelayChainAsNative<RelayChainOrigin, Origin>,
// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
// recognized.
SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,
// Native signed account converter; this just converts an `AccountId32` origin into a normal
// `Origin::Signed` origin of the same 32-byte value.
SignedAccountId32AsNative<RelayNetwork, Origin>,
// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
XcmPassthrough<Origin>,
);
parameter_types! {
// One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate.
pub UnitWeightCost: Weight = 1_000_000_000;
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64;
}
match_types! {
pub type ParentOrParentsExecutivePlurality: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) }
};
}
pub type Barrier = (
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom<Everything>,
AllowUnpaidExecutionFrom<ParentOrParentsExecutivePlurality>,
// ^^^ Parent and its exec plurality get free execution
);
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type Call = Call;
type XcmSender = XcmRouter;
// How to withdraw and deposit an asset.
type AssetTransactor = LocalAssetTransactor;
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = NativeAsset;
type IsTeleporter = (); // Teleporting is disabled.
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
type Trader =
UsingComponents<WeightToFee, RelayLocation, AccountId, Balances, ToAuthor<Runtime>>;
type ResponseHandler = PolkadotXcm;
type AssetTrap = PolkadotXcm;
type AssetClaims = PolkadotXcm;
type SubscriptionService = PolkadotXcm;
type PalletInstanceInfo = ();
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
}
/// No local origins on this chain are allowed to dispatch XCM sends/executions.
pub type LocalOriginToLocation = SignedToAccountId32<Origin, AccountId, RelayNetwork>;
/// The means for routing XCM messages which are not for local execution into the right message
/// queues.
pub type XcmRouter = (
// Two routers - use UMP to communicate with the relay chain:
cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,
// ..and XCMP to communicate with the sibling chains.
XcmpQueue,
);
impl pallet_xcm::Config for Runtime {
type Event = Event;
type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
type XcmRouter = XcmRouter;
type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
type XcmExecuteFilter = Nothing;
// ^ Disable dispatchable execute on the XCM pallet.
// Needs to be `Everything` for local testing.
type XcmExecutor = XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Nothing;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
type LocationInverter = LocationInverter<Ancestry>;
type Origin = Origin;
type Call = Call;
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
// ^ Override for AdvertisedXcmVersion default
type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
}
impl cumulus_pallet_xcm::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
}
+31 -31
View File
@@ -1,6 +1,6 @@
[package]
name = "polkadot-collator"
version = "5.0.0"
version = "5.2.0"
authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs"
edition = "2021"
@@ -10,24 +10,26 @@ name = "polkadot-collator"
path = "src/main.rs"
[dependencies]
futures = { version = "0.3.1", features = ["compat"] }
log = "0.4.8"
codec = { package = "parity-scale-codec", version = "2.3.0" }
structopt = "0.3.3"
serde = { version = "1.0.132", features = ["derive"] }
hex-literal = "0.2.1"
async-trait = "0.1.42"
clap = { version = "3.1", features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0" }
futures = { version = "0.3.1", features = ["compat"] }
hex-literal = "0.3.4"
log = "0.4.8"
serde = { version = "1.0.132", features = ["derive"] }
# Parachain runtimes
# Local
rococo-parachain-runtime = { path = "rococo-parachain" }
shell-runtime = { path = "shell" }
seedling-runtime = { path = "seedling" }
statemint-runtime = { path = "statemint" }
statemine-runtime = { path = "statemine" }
westmint-runtime = { path = "westmint" }
canvas-kusama-runtime = { path = "canvas-kusama" }
jsonrpc-core = "18.0.0"
parachains-common = { path = "parachains-common" }
# Substrate dependencies
# Substrate
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
@@ -37,10 +39,10 @@ sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "mast
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] }
sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -57,17 +59,20 @@ sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "maste
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" }
# try-runtime stuff.
try-runtime-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
# RPC related dependencies
jsonrpc-core = "18.0.0"
sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-rpc-system = { package = "substrate-frame-rpc-system", git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-contracts-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Cumulus dependencies
# Polkadot
polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
xcm = { git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus
cumulus-client-cli = { path = "../client/cli" }
cumulus-client-consensus-aura = { path = "../client/consensus/aura" }
cumulus-client-consensus-relay-chain = { path = "../client/consensus/relay-chain" }
@@ -77,20 +82,15 @@ cumulus-client-network = { path = "../client/network" }
cumulus-primitives-core = { path = "../primitives/core" }
cumulus-primitives-parachain-inherent = { path = "../primitives/parachain-inherent" }
cumulus-relay-chain-interface = { path = "../client/relay-chain-interface" }
cumulus-relay-chain-local = { path = "../client/relay-chain-local" }
# Polkadot dependencies
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" }
cumulus-relay-chain-inprocess-interface = { path = "../client/relay-chain-inprocess-interface" }
cumulus-relay-chain-rpc-interface = { path = "../client/relay-chain-rpc-interface" }
[build-dependencies]
substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
[dev-dependencies]
assert_cmd = "0.12"
nix = "0.17"
assert_cmd = "2.0"
nix = "0.23"
tempfile = "3.2.0"
[features]
@@ -102,8 +102,8 @@ runtime-benchmarks = [
"westmint-runtime/runtime-benchmarks",
]
try-runtime = [
'statemint-runtime/try-runtime',
'statemine-runtime/try-runtime',
'westmint-runtime/try-runtime',
'shell-runtime/try-runtime',
"statemint-runtime/try-runtime",
"statemine-runtime/try-runtime",
"westmint-runtime/try-runtime",
"shell-runtime/try-runtime",
]
@@ -0,0 +1,167 @@
[package]
name = "canvas-kusama-runtime"
version = "0.2.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[build-dependencies]
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
hex-literal = { version = "0.3.4", optional = true }
log = { version = "0.4.14", default-features = false }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.119", optional = true, features = ["derive"] }
smallvec = "1.6.1"
# Substrate
sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "master" }
frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "master" }
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "master" }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-contracts = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-contracts-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-contracts-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Polkadot
kusama-runtime-constants = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
# Cumulus
cumulus-pallet-aura-ext = { path = "../../pallets/aura-ext", default-features = false }
cumulus-pallet-dmp-queue = { path = "../../pallets/dmp-queue", default-features = false }
cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false }
cumulus-pallet-session-benchmarking = { path = "../../pallets/session-benchmarking", default-features = false }
cumulus-pallet-xcm = { path = "../../pallets/xcm", default-features = false }
cumulus-pallet-xcmp-queue = { path = "../../pallets/xcmp-queue", default-features = false }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
cumulus-primitives-timestamp = { path = "../../primitives/timestamp", default-features = false }
cumulus-primitives-utility = { path = "../../primitives/utility", default-features = false }
pallet-collator-selection = { path = "../../pallets/collator-selection", default-features = false }
parachain-info = { path = "../pallets/parachain-info", default-features = false }
parachains-common = { path = "../parachains-common", default-features = false }
[features]
default = [
"std",
]
std = [
"codec/std",
"log/std",
"scale-info/std",
"serde",
"frame-executive/std",
"frame-support/std",
"frame-system-rpc-runtime-api/std",
"frame-system/std",
"kusama-runtime-constants/std",
"pallet-aura/std",
"pallet-authorship/std",
"pallet-balances/std",
"pallet-collator-selection/std",
"pallet-contracts-primitives/std",
"pallet-contracts-rpc-runtime-api/std",
"pallet-contracts/std",
"pallet-multisig/std",
"pallet-randomness-collective-flip/std",
"pallet-session/std",
"pallet-sudo/std",
"pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std",
"pallet-utility/std",
"pallet-xcm/std",
"parachain-info/std",
"parachains-common/std",
"polkadot-core-primitives/std",
"polkadot-parachain/std",
"polkadot-runtime-common/std",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-aura/std",
"sp-core/std",
"sp-inherents/std",
"sp-io/std",
"sp-offchain/std",
"sp-runtime/std",
"sp-session/std",
"sp-std/std",
"sp-transaction-pool/std",
"sp-version/std",
"xcm-builder/std",
"xcm-executor/std",
"xcm/std",
"cumulus-pallet-aura-ext/std",
"cumulus-pallet-dmp-queue/std",
"cumulus-pallet-parachain-system/std",
"cumulus-pallet-xcm/std",
"cumulus-pallet-xcmp-queue/std",
"cumulus-primitives-core/std",
"cumulus-primitives-timestamp/std",
"cumulus-primitives-utility/std",
]
# Make contract callable functions marked as __unstable__ available. Do not enable
# on live chains as those are subject to change.
contracts-unstable-interface = [
"pallet-contracts/unstable-interface"
]
runtime-benchmarks = [
"hex-literal",
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system-benchmarking",
"frame-system/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-collator-selection/runtime-benchmarks",
"pallet-contracts/runtime-benchmarks",
"pallet-multisig/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-utility/runtime-benchmarks",
"pallet-xcm/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"cumulus-pallet-session-benchmarking/runtime-benchmarks",
]
try-runtime = [
"frame-executive/try-runtime",
"frame-try-runtime",
]
@@ -0,0 +1,9 @@
use substrate_wasm_builder::WasmBuilder;
fn main() {
WasmBuilder::new()
.with_current_project()
.export_heap_base()
.import_memory()
.build()
}
@@ -0,0 +1,73 @@
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub mod currency {
use kusama_runtime_constants as constants;
use polkadot_core_primitives::Balance;
/// The existential deposit. Set to 1/10 of its parent Relay Chain.
pub const EXISTENTIAL_DEPOSIT: Balance = constants::currency::EXISTENTIAL_DEPOSIT / 10;
pub const UNITS: Balance = constants::currency::UNITS;
pub const CENTS: Balance = constants::currency::CENTS;
pub const GRAND: Balance = constants::currency::GRAND;
pub const MILLICENTS: Balance = constants::currency::MILLICENTS;
pub const fn deposit(items: u32, bytes: u32) -> Balance {
// map to 1/10 of what the kusama relay chain charges (v9020)
constants::currency::deposit(items, bytes) / 10
}
}
/// Fee-related.
pub mod fee {
use frame_support::weights::{
constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients,
WeightToFeePolynomial,
};
use polkadot_core_primitives::Balance;
use smallvec::smallvec;
pub use sp_runtime::Perbill;
/// The block saturation level. Fees will be updates based on this value.
pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25);
/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the
/// node's balance type.
///
/// This should typically create a mapping between the following ranges:
/// - [0, MAXIMUM_BLOCK_WEIGHT]
/// - [Balance::min, Balance::max]
///
/// Yet, it can be used for any other sort of change to weight-fee. Some examples being:
/// - Setting it to `0` will essentially disable the weight fee.
/// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged.
pub struct WeightToFee;
impl WeightToFeePolynomial for WeightToFee {
type Balance = Balance;
fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
// in Kusama, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT:
// in Statemine, we map to 1/10 of that, or 1/100 CENT
let p = super::currency::CENTS;
let q = 100 * Balance::from(ExtrinsicBaseWeight::get());
smallvec![WeightToFeeCoefficient {
degree: 1,
negative: false,
coeff_frac: Perbill::from_rational(p % q, q),
coeff_integer: p / q,
}]
}
}
}
@@ -0,0 +1,65 @@
use crate::{
constants::currency::deposit, Balance, Balances, Call, Event, RandomnessCollectiveFlip,
Runtime, RuntimeBlockWeights, Timestamp,
};
use frame_support::{
parameter_types,
traits::{Nothing, OnRuntimeUpgrade},
weights::Weight,
};
use pallet_contracts::{
weights::{SubstrateWeight, WeightInfo},
Config, DefaultAddressGenerator, Frame, Schedule,
};
pub use parachains_common::AVERAGE_ON_INITIALIZE_RATIO;
// Prints debug output of the `contracts` pallet to stdout if the node is
// started with `-lruntime::contracts=debug`.
pub const CONTRACTS_DEBUG_OUTPUT: bool = true;
parameter_types! {
pub const DepositPerItem: Balance = deposit(1, 0);
pub const DepositPerByte: Balance = deposit(0, 1);
// The lazy deletion runs inside on_initialize.
pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *
RuntimeBlockWeights::get().max_block;
// The weight needed for decoding the queue should be less or equal than a fifth
// of the overall weight dedicated to the lazy deletion.
pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (
<Runtime as Config>::WeightInfo::on_initialize_per_queue_item(1) -
<Runtime as Config>::WeightInfo::on_initialize_per_queue_item(0)
)) / 5) as u32;
pub MySchedule: Schedule<Runtime> = Default::default();
}
impl Config for Runtime {
type Time = Timestamp;
type Randomness = RandomnessCollectiveFlip;
type Currency = Balances;
type Event = Event;
type Call = Call;
/// The safest default is to allow no calls at all.
///
/// Runtimes should whitelist dispatchables that are allowed to be called from contracts
/// and make sure they are stable. Dispatchables exposed to contracts are not allowed to
/// change because that would break already deployed contracts. The `Call` structure itself
/// is not allowed to change the indices of existing pallets, too.
type CallFilter = Nothing;
type DepositPerItem = DepositPerItem;
type DepositPerByte = DepositPerByte;
type WeightPrice = pallet_transaction_payment::Pallet<Self>;
type WeightInfo = SubstrateWeight<Self>;
type ChainExtension = ();
type DeletionQueueDepth = DeletionQueueDepth;
type DeletionWeightLimit = DeletionWeightLimit;
type Schedule = MySchedule;
type CallStack = [Frame<Self>; 31];
type AddressGenerator = DefaultAddressGenerator;
}
pub struct Migrations;
impl OnRuntimeUpgrade for Migrations {
fn on_runtime_upgrade() -> Weight {
pallet_contracts::migration::migrate::<Runtime>()
}
}
@@ -0,0 +1,630 @@
// Copyright (C) 2018-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 <https://www.gnu.org/licenses/>.
#![cfg_attr(not(feature = "std"), no_std)]
#![recursion_limit = "256"]
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
pub mod constants;
mod contracts;
mod xcm_config;
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{AccountIdLookup, BlakeTwo256, Block as BlockT},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use constants::{currency::*, fee::WeightToFee};
use frame_support::{
construct_runtime, parameter_types,
traits::{ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, Everything},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight},
DispatchClass,
},
PalletId,
};
use frame_system::limits::{BlockLength, BlockWeights};
pub use parachains_common as common;
use parachains_common::{
impls::DealWithFees, opaque, AccountId, BlockNumber, Hash, Header, Index, Signature,
AVERAGE_ON_INITIALIZE_RATIO, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION,
};
pub use parachains_common::{AuraId, Balance};
use xcm_config::CollatorSelectionUpdateOrigin;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
#[cfg(feature = "try-runtime")]
use frame_support::weights::Weight;
// Polkadot imports
use polkadot_runtime_common::{BlockHashCount, RocksDbWeight, SlowAdjustingFeeUpdate};
/// The address format for describing accounts.
pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
/// Block type as expected by this runtime.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// A Block signed with a Justification
pub type SignedBlock = generic::SignedBlock<Block>;
/// BlockId type as expected by this runtime.
pub type BlockId = generic::BlockId<Block>;
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (
frame_system::CheckNonZeroSender<Runtime>,
frame_system::CheckSpecVersion<Runtime>,
frame_system::CheckTxVersion<Runtime>,
frame_system::CheckGenesis<Runtime>,
frame_system::CheckEra<Runtime>,
frame_system::CheckNonce<Runtime>,
frame_system::CheckWeight<Runtime>,
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
/// Extrinsic type that has already been checked.
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
/// Executive: handles dispatch to the various modules.
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
contracts::Migrations,
>;
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: Aura,
}
}
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("canvas-kusama"),
impl_name: create_runtime_str!("canvas-kusama"),
authoring_version: 1,
spec_version: 16,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
state_version: 1,
};
/// The version information used to identify this runtime when compiled natively.
#[cfg(feature = "std")]
pub fn native_version() -> NativeVersion {
NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
}
parameter_types! {
pub const Version: RuntimeVersion = VERSION;
pub RuntimeBlockLength: BlockLength =
BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
.base_block(BlockExecutionWeight::get())
.for_class(DispatchClass::all(), |weights| {
weights.base_extrinsic = ExtrinsicBaseWeight::get();
})
.for_class(DispatchClass::Normal, |weights| {
weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
})
.for_class(DispatchClass::Operational, |weights| {
weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
// Operational transactions have some extra reserved space, so that they
// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
weights.reserved = Some(
MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
);
})
.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
.build_or_panic();
}
// Configure FRAME pallets to include in runtime.
impl frame_system::Config for Runtime {
type BaseCallFilter = Everything;
type BlockWeights = RuntimeBlockWeights;
type BlockLength = RuntimeBlockLength;
type AccountId = AccountId;
type Call = Call;
type Lookup = AccountIdLookup<AccountId, ()>;
type Index = Index;
type BlockNumber = BlockNumber;
type Hash = Hash;
type Hashing = BlakeTwo256;
type Header = Header;
type Event = Event;
type Origin = Origin;
type BlockHashCount = BlockHashCount;
type DbWeight = RocksDbWeight;
type Version = Version;
type PalletInfo = PalletInfo;
type OnNewAccount = ();
type OnKilledAccount = ();
type AccountData = pallet_balances::AccountData<Balance>;
type SystemWeightInfo = frame_system::weights::SubstrateWeight<Runtime>;
type SS58Prefix = ConstU16<42>;
type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
type MaxConsumers = ConstU32<16>;
}
impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the unix epoch.
type Moment = u64;
type OnTimestampSet = ();
type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
type WeightInfo = pallet_timestamp::weights::SubstrateWeight<Runtime>;
}
impl pallet_authorship::Config for Runtime {
type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Aura>;
type UncleGenerations = ConstU32<0>;
type FilterUncle = ();
type EventHandler = (CollatorSelection,);
}
impl pallet_balances::Config for Runtime {
type MaxLocks = ConstU32<50>;
/// The type for recording an account's balance.
type Balance = Balance;
/// The ubiquitous event type.
type Event = Event;
type DustRemoval = ();
type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
type AccountStore = System;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
type MaxReserves = ConstU32<50>;
type ReserveIdentifier = [u8; 8];
}
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction =
pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees<Runtime>>;
/// Relay Chain `TransactionByteFee` / 10
type TransactionByteFee = ConstU128<MILLICENTS>;
type WeightToFee = WeightToFee;
type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
type OperationalFeeMultiplier = ConstU8<5>;
}
parameter_types! {
// One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes.
pub const DepositBase: Balance = deposit(1, 88);
// Additional storage item size of 32 bytes.
pub const DepositFactor: Balance = deposit(0, 32);
}
impl pallet_multisig::Config for Runtime {
type Event = Event;
type Call = Call;
type Currency = Balances;
type DepositBase = DepositBase;
type DepositFactor = DepositFactor;
type MaxSignatories = ConstU16<100>;
type WeightInfo = pallet_multisig::weights::SubstrateWeight<Runtime>;
}
impl pallet_utility::Config for Runtime {
type Event = Event;
type Call = Call;
type PalletsOrigin = OriginCaller;
type WeightInfo = pallet_utility::weights::SubstrateWeight<Runtime>;
}
impl cumulus_pallet_parachain_system::Config for Runtime {
type Event = Event;
type OnSystemEvent = ();
type SelfParaId = parachain_info::Pallet<Runtime>;
type DmpMessageHandler = DmpQueue;
type ReservedDmpWeight = ConstU64<{ MAXIMUM_BLOCK_WEIGHT / 4 }>;
type OutboundXcmpMessageSource = XcmpQueue;
type XcmpMessageHandler = XcmpQueue;
type ReservedXcmpWeight = ConstU64<{ MAXIMUM_BLOCK_WEIGHT / 4 }>;
}
impl pallet_randomness_collective_flip::Config for Runtime {}
impl parachain_info::Config for Runtime {}
impl cumulus_pallet_aura_ext::Config for Runtime {}
parameter_types! {
pub const Period: u32 = 6 * HOURS;
pub const Offset: u32 = 0;
}
impl pallet_session::Config for Runtime {
type Event = Event;
type ValidatorId = <Self as frame_system::Config>::AccountId;
// we don't have stash and controller, thus we don't need the convert as well.
type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
type ShouldEndSession = pallet_session::PeriodicSessions<Period, Offset>;
type NextSessionRotation = pallet_session::PeriodicSessions<Period, Offset>;
type SessionManager = CollatorSelection;
// Essentially just Aura, but lets be pedantic.
type SessionHandler = <SessionKeys as sp_runtime::traits::OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys;
type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
}
impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
type DisabledValidators = ();
type MaxAuthorities = ConstU32<100_000>;
}
parameter_types! {
pub const PotId: PalletId = PalletId(*b"PotStake");
}
impl pallet_collator_selection::Config for Runtime {
type Event = Event;
type Currency = Balances;
type UpdateOrigin = CollatorSelectionUpdateOrigin;
type PotId = PotId;
type MaxCandidates = ConstU32<1000>;
type MinCandidates = ConstU32<5>;
type MaxInvulnerables = ConstU32<100>;
// should be a multiple of session or things will get inconsistent
type KickThreshold = Period;
type ValidatorId = <Self as frame_system::Config>::AccountId;
type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
type ValidatorRegistration = Session;
type WeightInfo = pallet_collator_selection::weights::SubstrateWeight<Runtime>;
}
impl pallet_sudo::Config for Runtime {
type Call = Call;
type Event = Event;
}
// Create the runtime by composing the FRAME pallets that were previously configured.
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
// System support stuff.
System: frame_system::{Pallet, Call, Config, Storage, Event<T>} = 0,
ParachainSystem: cumulus_pallet_parachain_system::{
Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned,
} = 1,
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 2,
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 3,
ParachainInfo: parachain_info::{Pallet, Storage, Config} = 4,
// Monetary stuff.
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 10,
TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 11,
// Collator support. The order of these 5 are important and shall not change.
Authorship: pallet_authorship::{Pallet, Call, Storage} = 20,
CollatorSelection: pallet_collator_selection::{Pallet, Call, Storage, Event<T>, Config<T>} = 21,
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>} = 22,
Aura: pallet_aura::{Pallet, Storage, Config<T>} = 23,
AuraExt: cumulus_pallet_aura_ext::{Pallet, Storage, Config} = 24,
// XCM helpers.
XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 30,
PolkadotXcm: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin, Config} = 31,
CumulusXcm: cumulus_pallet_xcm::{Pallet, Event<T>, Origin} = 32,
DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 33,
// Smart Contracts.
Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 40,
// Handy utilities.
Utility: pallet_utility::{Pallet, Call, Event} = 50,
Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 51,
// Sudo
Sudo: pallet_sudo::{Pallet, Call, Config<T>, Event<T>, Storage} = 100,
}
);
#[cfg(feature = "runtime-benchmarks")]
#[macro_use]
extern crate frame_benchmarking;
#[cfg(feature = "runtime-benchmarks")]
mod benches {
define_benchmarks!(
[frame_system, SystemBench::<Runtime>]
[pallet_balances, Balances]
[pallet_multisig, Multisig]
[pallet_session, SessionBench::<Runtime>]
[pallet_utility, Utility]
[pallet_timestamp, Timestamp]
[pallet_collator_selection, CollatorSelection]
[pallet_contracts, Contracts]
);
}
impl_runtime_apis! {
impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
fn slot_duration() -> sp_consensus_aura::SlotDuration {
sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
}
fn authorities() -> Vec<AuraId> {
Aura::authorities().into_inner()
}
}
impl sp_api::Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn execute_block(block: Block) {
Executive::execute_block(block)
}
fn initialize_block(header: &<Block as BlockT>::Header) {
Executive::initialize_block(header)
}
}
impl sp_api::Metadata<Block> for Runtime {
fn metadata() -> OpaqueMetadata {
OpaqueMetadata::new(Runtime::metadata().into())
}
}
impl sp_block_builder::BlockBuilder<Block> for Runtime {
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
Executive::apply_extrinsic(extrinsic)
}
fn finalize_block() -> <Block as BlockT>::Header {
Executive::finalize_block()
}
fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
data.create_extrinsics()
}
fn check_inherents(
block: Block,
data: sp_inherents::InherentData,
) -> sp_inherents::CheckInherentsResult {
data.check_extrinsics(&block)
}
}
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(
source: TransactionSource,
tx: <Block as BlockT>::Extrinsic,
block_hash: <Block as BlockT>::Hash,
) -> TransactionValidity {
Executive::validate_transaction(source, tx, block_hash)
}
}
impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
fn offchain_worker(header: &<Block as BlockT>::Header) {
Executive::offchain_worker(header)
}
}
impl sp_session::SessionKeys<Block> for Runtime {
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
SessionKeys::generate(seed)
}
fn decode_session_keys(
encoded: Vec<u8>,
) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
SessionKeys::decode_into_raw_public_keys(&encoded)
}
}
impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
fn account_nonce(account: AccountId) -> Index {
System::account_nonce(account)
}
}
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
fn query_info(
uxt: <Block as BlockT>::Extrinsic,
len: u32,
) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
TransactionPayment::query_info(uxt, len)
}
fn query_fee_details(
uxt: <Block as BlockT>::Extrinsic,
len: u32,
) -> pallet_transaction_payment::FeeDetails<Balance> {
TransactionPayment::query_fee_details(uxt, len)
}
}
impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info(header)
}
}
impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>
for Runtime
{
fn call(
origin: AccountId,
dest: AccountId,
value: Balance,
gas_limit: u64,
storage_deposit_limit: Option<Balance>,
input_data: Vec<u8>,
) -> pallet_contracts_primitives::ContractExecResult<Balance> {
Contracts::bare_call(
origin,
dest,
value,
gas_limit,
storage_deposit_limit,
input_data,
contracts::CONTRACTS_DEBUG_OUTPUT,
)
}
fn instantiate(
origin: AccountId,
value: Balance,
gas_limit: u64,
storage_deposit_limit: Option<Balance>,
code: pallet_contracts_primitives::Code<Hash>,
data: Vec<u8>,
salt: Vec<u8>,
) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, Balance> {
Contracts::bare_instantiate(
origin,
value,
gas_limit,
storage_deposit_limit,
code,
data,
salt,
contracts::CONTRACTS_DEBUG_OUTPUT,
)
}
fn upload_code(
origin: AccountId,
code: Vec<u8>,
storage_deposit_limit: Option<Balance>,
) -> pallet_contracts_primitives::CodeUploadResult<Hash, Balance> {
Contracts::bare_upload_code(origin, code, storage_deposit_limit)
}
fn get_storage(
address: AccountId,
key: [u8; 32],
) -> pallet_contracts_primitives::GetStorageResult {
Contracts::get_storage(address, key)
}
}
#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime<Block> for Runtime {
fn on_runtime_upgrade() -> (Weight, Weight) {
log::info!("try-runtime::on_runtime_upgrade canvas");
let weight = Executive::try_runtime_upgrade().unwrap();
(weight, RuntimeBlockWeights::get().max_block)
}
fn execute_block_no_check(block: Block) -> Weight {
Executive::execute_block_no_check(block)
}
}
#[cfg(feature = "runtime-benchmarks")]
impl frame_benchmarking::Benchmark<Block> for Runtime {
fn benchmark_metadata(extra: bool) -> (
Vec<frame_benchmarking::BenchmarkList>,
Vec<frame_support::traits::StorageInfo>,
) {
use frame_benchmarking::{Benchmarking, BenchmarkList};
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
let mut list = Vec::<BenchmarkList>::new();
list_benchmarks!(list, extra);
let storage_info = AllPalletsWithSystem::storage_info();
return (list, storage_info)
}
fn dispatch_benchmark(
config: frame_benchmarking::BenchmarkConfig
) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {
use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey};
use frame_system_benchmarking::Pallet as SystemBench;
impl frame_system_benchmarking::Config for Runtime {}
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
let whitelist: Vec<TrackedStorageKey> = vec![
// Block Number
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),
// Total Issuance
hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),
// Execution Phase
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),
// Event Count
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),
// System Events
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),
];
let mut batches = Vec::<BenchmarkBatch>::new();
let params = (&config, &whitelist);
add_benchmarks!(params, batches);
if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
Ok(batches)
}
}
}
struct CheckInherents;
impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
fn check_inherents(
block: &Block,
relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
) -> sp_inherents::CheckInherentsResult {
let relay_chain_slot = relay_state_proof
.read_slot()
.expect("Could not read the relay chain slot from the proof");
let inherent_data =
cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
relay_chain_slot,
sp_std::time::Duration::from_secs(6),
)
.create_inherent_data()
.expect("Could not create the timestamp inherent data");
inherent_data.check_extrinsics(&block)
}
}
cumulus_pallet_parachain_system::register_validate_block! {
Runtime = Runtime,
BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
CheckInherents = CheckInherents,
}
@@ -0,0 +1,205 @@
// Copyright (C) 2022 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::{
AccountId, Balances, Call, Event, Origin, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime,
WeightToFee, XcmpQueue,
};
use frame_support::{
match_types, parameter_types,
traits::{EnsureOneOf, Everything, Nothing},
weights::Weight,
};
use frame_system::EnsureRoot;
use pallet_xcm::{EnsureXcm, IsMajorityOfBody, XcmPassthrough};
use polkadot_parachain::primitives::Sibling;
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin,
FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, ParentAsSuperuser,
ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
UsingComponents,
};
use xcm_executor::XcmExecutor;
parameter_types! {
pub const RelayLocation: MultiLocation = MultiLocation::parent();
pub const RelayNetwork: NetworkId = NetworkId::Any;
pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
pub const Local: MultiLocation = Here.into();
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
pub const ExecutiveBody: BodyId = BodyId::Executive;
}
/// We allow root and the Relay Chain council to execute privileged collator selection operations.
pub type CollatorSelectionUpdateOrigin =
EnsureOneOf<EnsureRoot<AccountId>, EnsureXcm<IsMajorityOfBody<RelayLocation, ExecutiveBody>>>;
/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
/// `Transact` in order to determine the dispatch Origin.
pub type LocationToAccountId = (
// The parent (Relay-chain) origin converts to the parent `AccountId`.
ParentIsPreset<AccountId>,
// Sibling parachain origins convert to AccountId via the `ParaId::into`.
SiblingParachainConvertsVia<Sibling, AccountId>,
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
AccountId32Aliases<RelayNetwork, AccountId>,
);
/// Means for transacting the native currency on this chain.
pub type CurrencyTransactor = CurrencyAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
IsConcrete<RelayLocation>,
// Convert an XCM MultiLocation into a local account id:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We don't track any teleports of `Balances`.
(),
>;
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
/// biases the kind of local `Origin` it will become.
pub type XcmOriginToTransactDispatchOrigin = (
// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
// foreign chains who want to have a local sovereign account on this chain which they control.
SovereignSignedViaLocation<LocationToAccountId, Origin>,
// Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when
// recognised.
RelayChainAsNative<RelayChainOrigin, Origin>,
// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
// recognised.
SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,
// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
// transaction from the Root origin.
ParentAsSuperuser<Origin>,
// Native signed account converter; this just converts an `AccountId32` origin into a normal
// `Origin::Signed` origin of the same 32-byte value.
SignedAccountId32AsNative<RelayNetwork, Origin>,
// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
XcmPassthrough<Origin>,
);
parameter_types! {
// One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate.
pub UnitWeightCost: Weight = 1_000_000_000;
pub const MaxInstructions: u32 = 100;
}
match_types! {
pub type ParentOrParentsExecutivePlurality: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) }
};
pub type ParentOrSiblings: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(_) }
};
}
pub type Barrier = (
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom<Everything>,
// Parent and its exec plurality get free execution
AllowUnpaidExecutionFrom<ParentOrParentsExecutivePlurality>,
// Expected responses are OK.
AllowKnownQueryResponses<PolkadotXcm>,
// Subscriptions for version tracking are OK.
AllowSubscriptionsFrom<ParentOrSiblings>,
);
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type Call = Call;
type XcmSender = XcmRouter;
type AssetTransactor = CurrencyTransactor;
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = NativeAsset;
type IsTeleporter = NativeAsset;
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
type Trader = UsingComponents<WeightToFee, RelayLocation, AccountId, Balances, ()>;
type ResponseHandler = PolkadotXcm;
type AssetTrap = PolkadotXcm;
type AssetClaims = PolkadotXcm;
type SubscriptionService = PolkadotXcm;
}
/// Converts a local signed origin into an XCM multilocation.
/// Forms the basis for local origins sending/executing XCMs.
pub type LocalOriginToLocation = SignedToAccountId32<Origin, AccountId, RelayNetwork>;
/// The means for routing XCM messages which are not for local execution into the right message
/// queues.
pub type XcmRouter = (
// Two routers - use UMP to communicate with the relay chain:
cumulus_primitives_utility::ParentAsUmp<ParachainSystem, PolkadotXcm>,
// ..and XCMP to communicate with the sibling chains.
XcmpQueue,
);
impl pallet_xcm::Config for Runtime {
type Event = Event;
// We want to disallow users sending (arbitrary) XCMs from this chain.
type SendXcmOrigin = EnsureXcmOrigin<Origin, ()>;
type XcmRouter = XcmRouter;
// We support local origins dispatching XCM executions in principle...
type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
// ... but disallow generic XCM execution. As a result only teleports and reserve transfers are allowed.
type XcmExecuteFilter = Nothing;
type XcmExecutor = XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Everything;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
type LocationInverter = LocationInverter<Ancestry>;
type Origin = Origin;
type Call = Call;
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
}
impl cumulus_pallet_xcm::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
}
impl cumulus_pallet_xcmp_queue::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
type ChannelInfo = ParachainSystem;
type VersionWrapper = PolkadotXcm;
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
type ControllerOrigin = EnsureOneOf<
EnsureRoot<AccountId>,
EnsureXcm<IsMajorityOfBody<RelayLocation, ExecutiveBody>>,
>;
type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
type WeightInfo = cumulus_pallet_xcmp_queue::weights::SubstrateWeight<Runtime>;
}
impl cumulus_pallet_dmp_queue::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
}
@@ -5,8 +5,8 @@ name = "parachain-info"
version = "0.1.0"
[dependencies]
codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = ["derive"] }
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.132", optional = true, features = ["derive"] }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
+2 -2
View File
@@ -5,8 +5,8 @@ name = "cumulus-ping"
version = "0.1.0"
[dependencies]
codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = ["derive"] }
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.132", optional = true, features = ["derive"] }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
@@ -35,6 +35,7 @@ pub mod pallet {
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);
/// The module configuration trait.
@@ -9,14 +9,10 @@ description = "Logic which is common to all parachain runtimes"
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
# External dependencies
codec = { package = "parity-scale-codec", version = "2.3.0", features = ["derive"], default-features = false }
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"], default-features = false }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
# Substrate dependencies
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
# Substrate
frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
@@ -24,21 +20,24 @@ pallet-asset-tx-payment = { git = "https://github.com/paritytech/substrate", bra
pallet-assets = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
# Polkadot dependencies
polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" }
xcm = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" }
# Polkadot
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
# Local dependencies
# Cumulus
pallet-collator-selection = { path = "../../pallets/collator-selection", default-features = false }
[dev-dependencies]
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
[build-dependencies]
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -48,17 +47,17 @@ default = ["std"]
std = [
"codec/std",
"scale-info/std",
"sp-consensus-aura/std",
"sp-std/std",
"sp-io/std",
"frame-support/std",
"frame-executive/std",
"frame-support/std",
"frame-system/std",
"pallet-asset-tx-payment/std",
"pallet-collator-selection/std",
"pallet-assets/std",
"pallet-authorship/std",
"pallet-balances/std",
"polkadot-runtime-common/std",
"polkadot-primitives/std",
"polkadot-runtime-common/std",
"sp-consensus-aura/std",
"sp-io/std",
"sp-std/std",
"pallet-collator-selection/std",
]
@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Auxillary struct/enums for parachain runtimes.
//! Auxiliary struct/enums for parachain runtimes.
//! Taken from polkadot/runtime/common (at a21cd64) and adapted for parachains.
use frame_support::traits::{
@@ -44,13 +44,8 @@ where
<R as frame_system::Config>::Event: From<pallet_balances::Event<R>>,
{
fn on_nonzero_unbalanced(amount: NegativeImbalance<R>) {
let numeric_amount = amount.peek();
let staking_pot = <pallet_collator_selection::Pallet<R>>::account_id();
<pallet_balances::Pallet<R>>::resolve_creating(&staking_pot, amount);
<frame_system::Pallet<R>>::deposit_event(pallet_balances::Event::Deposit {
who: staking_pot,
amount: numeric_amount,
});
}
}
@@ -135,6 +130,7 @@ mod tests {
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
const TEST_ACCOUNT: AccountId = AccountId::new([1; 32]);
frame_support::construct_runtime!(
pub enum Test where
@@ -200,7 +196,7 @@ mod tests {
where
I: 'a,
{
Some(Default::default())
Some(TEST_ACCOUNT)
}
}
@@ -255,7 +251,7 @@ mod tests {
let fee = Balances::issue(10);
let tip = Balances::issue(20);
assert_eq!(Balances::free_balance(AccountId::default()), 0);
assert_eq!(Balances::free_balance(TEST_ACCOUNT), 0);
DealWithFees::on_unbalanceds(vec![fee, tip].into_iter());
@@ -52,6 +52,13 @@ mod types {
// Aura consensus authority.
pub type AuraId = sp_consensus_aura::sr25519::AuthorityId;
// Aura consensus authority used by Statemint.
//
// Because of registering the authorities with an ed25519 key before switching from Shell
// to Statemint, we were required to deploy a hotfix that changed Statemint to ed22519.
// In the future that may change again.
pub type StatemintAuraId = sp_consensus_aura::ed25519::AuthorityId;
// Id used for identifying assets.
pub type AssetId = u32;
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+61 -60
View File
@@ -6,57 +6,55 @@ edition = "2021"
description = "Simple runtime used by the rococo parachain(s)"
[dependencies]
codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
log = { version = "0.4.14", default-features = false }
parachain-info = { path = "../pallets/parachain-info", default-features = false }
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.132", optional = true, features = ["derive"] }
# Substrate dependencies
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Substrate
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
parachains-common = { path = "../parachains-common", default-features = false }
# Cumulus dependencies
cumulus-pallet-aura-ext = { path = "../../pallets/aura-ext", default-features = false }
cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
cumulus-primitives-timestamp = { path = "../../primitives/timestamp", default-features = false }
cumulus-primitives-utility = { path = "../../primitives/utility", default-features = false }
cumulus-pallet-dmp-queue = { path = "../../pallets/dmp-queue", default-features = false }
cumulus-pallet-xcmp-queue = { path = "../../pallets/xcmp-queue", default-features = false }
cumulus-pallet-xcm = { path = "../../pallets/xcm", default-features = false }
cumulus-ping = { path = "../pallets/ping", default-features = false }
# Polkadot dependencies
# Polkadot
pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
# Cumulus
cumulus-pallet-aura-ext = { path = "../../pallets/aura-ext", default-features = false }
cumulus-pallet-dmp-queue = { path = "../../pallets/dmp-queue", default-features = false }
cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false }
cumulus-pallet-xcm = { path = "../../pallets/xcm", default-features = false }
cumulus-pallet-xcmp-queue = { path = "../../pallets/xcmp-queue", default-features = false }
cumulus-ping = { path = "../pallets/ping", default-features = false }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
cumulus-primitives-timestamp = { path = "../../primitives/timestamp", default-features = false }
cumulus-primitives-utility = { path = "../../primitives/utility", default-features = false }
parachains-common = { path = "../parachains-common", default-features = false }
parachain-info = { path = "../pallets/parachain-info", default-features = false }
[build-dependencies]
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -65,42 +63,45 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran
default = [ "std" ]
std = [
"codec/std",
"log/std",
"scale-info/std",
"serde",
"log/std",
"sp-api/std",
"sp-std/std",
"sp-io/std",
"sp-core/std",
"sp-runtime/std",
"sp-version/std",
"sp-offchain/std",
"sp-session/std",
"sp-block-builder/std",
"sp-transaction-pool/std",
"sp-inherents/std",
"frame-support/std",
"frame-executive/std",
"frame-support/std",
"frame-system-rpc-runtime-api/std",
"frame-system/std",
"pallet-assets/std",
"pallet-aura/std",
"pallet-balances/std",
"pallet-timestamp/std",
"pallet-sudo/std",
"pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std",
"parachain-info/std",
"parachains-common/std",
"pallet-xcm/std",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-aura/std",
"sp-core/std",
"sp-inherents/std",
"sp-io/std",
"sp-offchain/std",
"sp-runtime/std",
"sp-session/std",
"sp-std/std",
"sp-transaction-pool/std",
"sp-version/std",
"xcm-builder/std",
"xcm-executor/std",
"xcm/std",
"cumulus-pallet-aura-ext/std",
"cumulus-pallet-dmp-queue/std",
"cumulus-pallet-parachain-system/std",
"cumulus-pallet-xcmp-queue/std",
"cumulus-pallet-xcm/std",
"cumulus-pallet-xcmp-queue/std",
"cumulus-ping/std",
"cumulus-primitives-core/std",
"cumulus-primitives-timestamp/std",
"cumulus-primitives-utility/std",
"cumulus-ping/std",
"xcm/std",
"xcm-builder/std",
"xcm-executor/std",
"pallet-aura/std",
"sp-consensus-aura/std",
"parachain-info/std",
"parachains-common/std",
]
+12 -11
View File
@@ -37,7 +37,7 @@ use sp_version::RuntimeVersion;
// A few exports that help ease life for downstream crates.
pub use frame_support::{
construct_runtime, match_type, parameter_types,
construct_runtime, match_types, parameter_types,
traits::{EnsureOneOf, Everything, IsInVec, Randomness},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
@@ -73,7 +73,7 @@ use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset,
ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative,
ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, UsingComponents,
};
@@ -258,7 +258,7 @@ parameter_types! {
impl cumulus_pallet_parachain_system::Config for Runtime {
type Event = Event;
type OnValidationData = ();
type OnSystemEvent = ();
type SelfParaId = parachain_info::Pallet<Runtime>;
type OutboundXcmpMessageSource = XcmpQueue;
type DmpMessageHandler = DmpQueue;
@@ -283,8 +283,8 @@ parameter_types! {
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
/// `Transact` in order to determine the dispatch Origin.
pub type LocationToAccountId = (
// The parent (Relay-chain) origin converts to the default `AccountId`.
ParentIsDefault<AccountId>,
// The parent (Relay-chain) origin converts to the parent `AccountId`.
ParentIsPreset<AccountId>,
// Sibling parachain origins convert to AccountId via the `ParaId::into`.
SiblingParachainConvertsVia<Sibling, AccountId>,
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
@@ -361,13 +361,11 @@ parameter_types! {
pub const MaxInstructions: u32 = 100;
}
match_type! {
match_types! {
pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }
};
}
match_type! {
pub type Statemint: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: X1(Parachain(1000)) }
};
@@ -457,6 +455,9 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime {
type ChannelInfo = ParachainSystem;
type VersionWrapper = ();
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
type ControllerOrigin = EnsureRoot<AccountId>;
type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
type WeightInfo = cumulus_pallet_xcmp_queue::weights::SubstrateWeight<Runtime>;
}
impl cumulus_pallet_dmp_queue::Config for Runtime {
@@ -534,7 +535,7 @@ construct_runtime! {
// XCM helpers.
XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin, Config} = 51,
CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,
DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
@@ -700,8 +701,8 @@ impl_runtime_apis! {
}
impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
fn collect_collation_info() -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info()
fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info(header)
}
}
}
+37 -36
View File
@@ -1,37 +1,37 @@
[package]
name = 'seedling-runtime'
version = '0.1.0'
name = "seedling-runtime"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[dependencies]
codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
log = { version = "0.4.14", default-features = false }
parachain-info = { path = "../pallets/parachain-info", default-features = false }
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.132", optional = true, features = ["derive"] }
# Substrate dependencies
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Substrate
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Cumulus dependencies
# Cumulus
cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false }
cumulus-pallet-solo-to-para = { path = "../../pallets/solo-to-para", default-features = false }
parachain-info = { path = "../pallets/parachain-info", default-features = false }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
[build-dependencies]
@@ -41,26 +41,27 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran
default = [ "std" ]
std = [
"codec/std",
"log/std",
"scale-info/std",
"serde",
"log/std",
"sp-api/std",
"sp-std/std",
"sp-io/std",
"sp-core/std",
"sp-runtime/std",
"sp-version/std",
"sp-offchain/std",
"sp-session/std",
"sp-block-builder/std",
"sp-transaction-pool/std",
"sp-inherents/std",
"frame-support/std",
"frame-executive/std",
"frame-support/std",
"frame-system/std",
"pallet-sudo/std",
"pallet-balances/std",
"parachain-info/std",
"pallet-sudo/std",
"sp-api/std",
"sp-block-builder/std",
"sp-core/std",
"sp-inherents/std",
"sp-io/std",
"sp-offchain/std",
"sp-runtime/std",
"sp-session/std",
"sp-std/std",
"sp-transaction-pool/std",
"sp-version/std",
"cumulus-pallet-parachain-system/std",
"cumulus-pallet-solo-to-para/std",
"cumulus-primitives-core/std",
"parachain-info/std",
]
+13 -23
View File
@@ -37,8 +37,8 @@ use sp_version::RuntimeVersion;
// A few exports that help ease life for downstream crates.
pub use frame_support::{
construct_runtime, match_type, parameter_types,
traits::{Contains, IsInVec, Randomness},
construct_runtime, parameter_types,
traits::{IsInVec, Randomness},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
DispatchClass, IdentityFee, Weight,
@@ -103,23 +103,6 @@ parameter_types! {
.build_or_panic();
pub const SS58Prefix: u8 = 42;
}
pub struct BaseFilter;
impl Contains<Call> for BaseFilter {
fn contains(c: &Call) -> bool {
// Disallow everything that is not set_validation_data or set_code
match c {
Call::ParachainSystem(cumulus_pallet_parachain_system::Call::set_validation_data {
..
}) => true,
Call::Sudo(pallet_sudo::Call::sudo_unchecked_weight { call: ref x, .. }) => {
matches!(x.as_ref(), &Call::System(frame_system::Call::set_code { .. }))
},
_ => false,
}
}
}
impl frame_system::Config for Runtime {
/// The identifier used to distinguish between accounts.
type AccountId = AccountId;
@@ -151,7 +134,7 @@ impl frame_system::Config for Runtime {
type OnNewAccount = ();
type OnKilledAccount = ();
type DbWeight = ();
type BaseCallFilter = BaseFilter;
type BaseCallFilter = frame_support::traits::Everything;
type SystemWeightInfo = ();
type BlockWeights = RuntimeBlockWeights;
type BlockLength = RuntimeBlockLength;
@@ -165,9 +148,13 @@ impl pallet_sudo::Config for Runtime {
type Event = Event;
}
impl cumulus_pallet_solo_to_para::Config for Runtime {
type Event = Event;
}
impl cumulus_pallet_parachain_system::Config for Runtime {
type Event = Event;
type OnValidationData = ();
type OnSystemEvent = cumulus_pallet_solo_to_para::Pallet<Runtime>;
type SelfParaId = parachain_info::Pallet<Runtime>;
type OutboundXcmpMessageSource = ();
type DmpMessageHandler = ();
@@ -186,10 +173,12 @@ construct_runtime! {
{
System: frame_system::{Pallet, Call, Storage, Config, Event<T>},
Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>},
ParachainSystem: cumulus_pallet_parachain_system::{
Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned,
},
ParachainInfo: parachain_info::{Pallet, Storage, Config},
SoloToPara: cumulus_pallet_solo_to_para::{Pallet, Call, Storage, Event},
}
}
@@ -221,6 +210,7 @@ pub type SignedExtra = (
frame_system::CheckGenesis<Runtime>,
frame_system::CheckEra<Runtime>,
frame_system::CheckNonce<Runtime>,
cumulus_pallet_solo_to_para::CheckSudo<Runtime>,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
@@ -303,8 +293,8 @@ impl_runtime_apis! {
}
impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
fn collect_collation_info() -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info()
fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info(header)
}
}
}
+43 -44
View File
@@ -5,42 +5,41 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[dependencies]
codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
log = { version = "0.4.14", default-features = false }
parachain-info = { path = "../pallets/parachain-info", default-features = false }
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.132", optional = true, features = ["derive"] }
# Substrate dependencies
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Substrate
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# try-runtime stuff.
frame-try-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Cumulus dependencies
cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
cumulus-primitives-utility = { path = "../../primitives/utility", default-features = false }
cumulus-pallet-dmp-queue = { path = "../../pallets/dmp-queue", default-features = false }
cumulus-pallet-xcm = { path = "../../pallets/xcm", default-features = false }
# Polkadot
xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
# Cumulus
cumulus-pallet-dmp-queue = { path = "../../pallets/dmp-queue", default-features = false }
cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false }
cumulus-pallet-xcm = { path = "../../pallets/xcm", default-features = false }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
cumulus-primitives-utility = { path = "../../primitives/utility", default-features = false }
parachain-info = { path = "../pallets/parachain-info", default-features = false }
[build-dependencies]
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -48,34 +47,34 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran
default = [ "std" ]
std = [
"codec/std",
"log/std",
"scale-info/std",
"serde",
"log/std",
"sp-api/std",
"sp-std/std",
"sp-io/std",
"sp-core/std",
"sp-runtime/std",
"sp-version/std",
"sp-offchain/std",
"sp-session/std",
"sp-block-builder/std",
"sp-transaction-pool/std",
"sp-inherents/std",
"frame-support/std",
"frame-executive/std",
"frame-support/std",
"frame-system/std",
"parachain-info/std",
"cumulus-pallet-parachain-system/std",
"sp-api/std",
"sp-block-builder/std",
"sp-core/std",
"sp-inherents/std",
"sp-io/std",
"sp-offchain/std",
"sp-runtime/std",
"sp-session/std",
"sp-std/std",
"sp-transaction-pool/std",
"sp-version/std",
"xcm-builder/std",
"xcm-executor/std",
"xcm/std",
"cumulus-pallet-dmp-queue/std",
"cumulus-pallet-parachain-system/std",
"cumulus-pallet-xcm/std",
"cumulus-primitives-core/std",
"cumulus-primitives-utility/std",
"xcm/std",
"xcm-builder/std",
"xcm-executor/std",
"parachain-info/std",
]
try-runtime = [
"frame-try-runtime",
"frame-executive/try-runtime",
"frame-try-runtime",
]
+6 -67
View File
@@ -22,6 +22,8 @@
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
pub mod xcm_config;
use codec::{Decode, Encode};
use frame_support::unsigned::TransactionValidityError;
use scale_info::TypeInfo;
@@ -40,7 +42,7 @@ use sp_version::RuntimeVersion;
// A few exports that help ease life for downstream crates.
pub use frame_support::{
construct_runtime, match_type, parameter_types,
construct_runtime, parameter_types,
traits::{Everything, IsInVec, Randomness},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
@@ -53,14 +55,6 @@ use frame_system::limits::{BlockLength, BlockWeights};
pub use sp_runtime::BuildStorage;
pub use sp_runtime::{Perbill, Permill};
// XCM imports
use xcm::latest::prelude::*;
use xcm_builder::{
AllowUnpaidExecutionFrom, FixedWeightBounds, LocationInverter, ParentAsSuperuser,
ParentIsDefault, SovereignSignedViaLocation,
};
use xcm_executor::{Config, XcmExecutor};
/// This runtime version.
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
@@ -162,7 +156,7 @@ parameter_types! {
impl cumulus_pallet_parachain_system::Config for Runtime {
type Event = Event;
type OnValidationData = ();
type OnSystemEvent = ();
type SelfParaId = parachain_info::Pallet<Runtime>;
type OutboundXcmpMessageSource = ();
type DmpMessageHandler = cumulus_pallet_xcm::UnlimitedDmpExecution<Runtime>;
@@ -173,61 +167,6 @@ impl cumulus_pallet_parachain_system::Config for Runtime {
impl parachain_info::Config for Runtime {}
parameter_types! {
pub const RococoLocation: MultiLocation = MultiLocation::parent();
pub const RococoNetwork: NetworkId = NetworkId::Polkadot;
pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
}
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
/// bias the kind of local `Origin` it will become.
pub type XcmOriginToTransactDispatchOrigin = (
// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
// foreign chains who want to have a local sovereign account on this chain which they control.
SovereignSignedViaLocation<ParentIsDefault<AccountId>, Origin>,
// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
// transaction from the Root origin.
ParentAsSuperuser<Origin>,
);
match_type! {
pub type JustTheParent: impl Contains<MultiLocation> = { MultiLocation { parents:1, interior: Here } };
}
parameter_types! {
// One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate.
pub UnitWeightCost: Weight = 1_000_000_000;
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64;
}
pub struct XcmConfig;
impl Config for XcmConfig {
type Call = Call;
type XcmSender = (); // sending XCM not supported
type AssetTransactor = (); // balances not supported
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = (); // balances not supported
type IsTeleporter = (); // balances not supported
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = AllowUnpaidExecutionFrom<JustTheParent>;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>; // balances not supported
type Trader = (); // balances not supported
type ResponseHandler = (); // Don't handle responses for now.
type AssetTrap = (); // don't trap for now
type AssetClaims = (); // don't claim for now
type SubscriptionService = (); // don't handle subscriptions for now
type PalletInstancesInfo = ();
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
}
impl cumulus_pallet_xcm::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
}
construct_runtime! {
pub enum Runtime where
Block = Block,
@@ -384,8 +323,8 @@ impl_runtime_apis! {
}
impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
fn collect_collation_info() -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info()
fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info(header)
}
}
}
@@ -0,0 +1,77 @@
// Copyright (C) 2022 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::{AccountId, Call, Event, Origin, ParachainInfo, Runtime};
use frame_support::{match_types, parameter_types, weights::Weight};
use xcm::latest::prelude::*;
use xcm_builder::{
AllowUnpaidExecutionFrom, FixedWeightBounds, LocationInverter, ParentAsSuperuser,
ParentIsPreset, SovereignSignedViaLocation,
};
parameter_types! {
pub const RococoLocation: MultiLocation = MultiLocation::parent();
pub const RococoNetwork: NetworkId = NetworkId::Polkadot;
pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
}
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
/// bias the kind of local `Origin` it will become.
pub type XcmOriginToTransactDispatchOrigin = (
// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
// foreign chains who want to have a local sovereign account on this chain which they control.
SovereignSignedViaLocation<ParentIsPreset<AccountId>, Origin>,
// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
// transaction from the Root origin.
ParentAsSuperuser<Origin>,
);
match_types! {
pub type JustTheParent: impl Contains<MultiLocation> = { MultiLocation { parents:1, interior: Here } };
}
parameter_types! {
// One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate.
pub UnitWeightCost: Weight = 1_000_000_000;
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64;
}
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type Call = Call;
type XcmSender = (); // sending XCM not supported
type AssetTransactor = (); // balances not supported
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = (); // balances not supported
type IsTeleporter = (); // balances not supported
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = AllowUnpaidExecutionFrom<JustTheParent>;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>; // balances not supported
type Trader = (); // balances not supported
type ResponseHandler = (); // Don't handle responses for now.
type AssetTrap = (); // don't trap for now
type AssetClaims = (); // don't claim for now
type SubscriptionService = (); // don't handle subscriptions for now
type PalletInstanceInfo = ();
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
}
impl cumulus_pallet_xcm::Config for Runtime {
type Event = Event;
type XcmExecutor = xcm_executor::XcmExecutor<XcmConfig>;
}
+358 -19
View File
@@ -34,6 +34,9 @@ pub type ShellChainSpec = sc_service::GenericChainSpec<shell_runtime::GenesisCon
pub type SeedlingChainSpec =
sc_service::GenericChainSpec<seedling_runtime::GenesisConfig, Extensions>;
/// The default XCM version to set in genesis config.
const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION;
/// Helper function to generate a crypto pair from seed
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
TPublic::Pair::from_string(&format!("//{}", seed), None)
@@ -98,6 +101,7 @@ pub fn get_chain_spec() -> ChainSpec {
None,
None,
None,
None,
Extensions { relay_chain: "westend".into(), para_id: 1000 },
)
}
@@ -112,6 +116,7 @@ pub fn get_shell_chain_spec() -> ShellChainSpec {
None,
None,
None,
None,
Extensions { relay_chain: "westend".into(), para_id: 1000 },
)
}
@@ -131,6 +136,7 @@ pub fn get_seedling_chain_spec() -> SeedlingChainSpec {
None,
None,
None,
None,
Extensions { relay_chain: "westend".into(), para_id: 2000 },
)
}
@@ -161,6 +167,7 @@ pub fn staging_test_net() -> ChainSpec {
None,
None,
None,
None,
Extensions { relay_chain: "westend".into(), para_id: 1000 },
)
}
@@ -185,6 +192,9 @@ fn testnet_genesis(
aura: rococo_parachain_runtime::AuraConfig { authorities: initial_authorities },
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: rococo_parachain_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
}
}
@@ -216,7 +226,7 @@ fn seedling_testnet_genesis(
}
}
use parachains_common::Balance as StatemintBalance;
use parachains_common::{Balance as StatemintBalance, StatemintAuraId};
/// Specialized `ChainSpec` for the normal parachain runtime.
pub type StatemintChainSpec =
@@ -240,14 +250,14 @@ pub fn get_public_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pa
/// Generate collator keys from seed.
///
/// This function's return type must always match the session keys of the chain in tuple format.
pub fn get_collator_keys_from_seed(seed: &str) -> AuraId {
pub fn get_collator_keys_from_seed<AuraId: Public>(seed: &str) -> <AuraId::Pair as Pair>::Public {
get_public_from_seed::<AuraId>(seed)
}
/// Generate the session keys from individual elements.
///
/// The input must be a tuple of individual keys (a single arg for now since we have just one key).
pub fn statemint_session_keys(keys: AuraId) -> statemint_runtime::SessionKeys {
pub fn statemint_session_keys(keys: StatemintAuraId) -> statemint_runtime::SessionKeys {
statemint_runtime::SessionKeys { aura: keys }
}
@@ -267,6 +277,7 @@ pub fn westmint_session_keys(keys: AuraId) -> westmint_runtime::SessionKeys {
pub fn statemint_development_config() -> StatemintChainSpec {
let mut properties = sc_chain_spec::Properties::new();
properties.insert("ss58Format".into(), 0.into());
properties.insert("tokenSymbol".into(), "DOT".into());
properties.insert("tokenDecimals".into(), 10.into());
@@ -281,7 +292,7 @@ pub fn statemint_development_config() -> StatemintChainSpec {
// initial collators.
vec![(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed("Alice"),
get_collator_keys_from_seed::<StatemintAuraId>("Alice"),
)],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
@@ -295,6 +306,7 @@ pub fn statemint_development_config() -> StatemintChainSpec {
Vec::new(),
None,
None,
None,
Some(properties),
Extensions { relay_chain: "polkadot-dev".into(), para_id: 1000 },
)
@@ -302,6 +314,7 @@ pub fn statemint_development_config() -> StatemintChainSpec {
pub fn statemint_local_config() -> StatemintChainSpec {
let mut properties = sc_chain_spec::Properties::new();
properties.insert("ss58Format".into(), 0.into());
properties.insert("tokenSymbol".into(), "DOT".into());
properties.insert("tokenDecimals".into(), 10.into());
@@ -317,11 +330,11 @@ pub fn statemint_local_config() -> StatemintChainSpec {
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed("Alice"),
get_collator_keys_from_seed::<StatemintAuraId>("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed("Bob"),
get_collator_keys_from_seed::<StatemintAuraId>("Bob"),
),
],
vec![
@@ -344,13 +357,74 @@ pub fn statemint_local_config() -> StatemintChainSpec {
Vec::new(),
None,
None,
None,
Some(properties),
Extensions { relay_chain: "polkadot-local".into(), para_id: 1000 },
)
}
// Not used for syncing, but just to determine the genesis values set for the upgrade from shell.
pub fn statemint_config() -> StatemintChainSpec {
let mut properties = sc_chain_spec::Properties::new();
properties.insert("ss58Format".into(), 0.into());
properties.insert("tokenSymbol".into(), "DOT".into());
properties.insert("tokenDecimals".into(), 10.into());
StatemintChainSpec::from_genesis(
// Name
"Statemint",
// ID
"statemint",
ChainType::Live,
move || {
statemint_genesis(
// initial collators.
vec![
(
hex!("4c3d674d2a01060f0ded218e5dcc6f90c1726f43df79885eb3e22d97a20d5421")
.into(),
hex!("4c3d674d2a01060f0ded218e5dcc6f90c1726f43df79885eb3e22d97a20d5421")
.unchecked_into(),
),
(
hex!("c7d7d38d16bc23c6321152c50306212dc22c0efc04a2e52b5cccfc31ab3d7811")
.into(),
hex!("c7d7d38d16bc23c6321152c50306212dc22c0efc04a2e52b5cccfc31ab3d7811")
.unchecked_into(),
),
(
hex!("c5c07ba203d7375675f5c1ebe70f0a5bb729ae57b48bcc877fcc2ab21309b762")
.into(),
hex!("c5c07ba203d7375675f5c1ebe70f0a5bb729ae57b48bcc877fcc2ab21309b762")
.unchecked_into(),
),
(
hex!("0b2d0013fb974794bd7aa452465b567d48ef70373fe231a637c1fb7c547e85b3")
.into(),
hex!("0b2d0013fb974794bd7aa452465b567d48ef70373fe231a637c1fb7c547e85b3")
.unchecked_into(),
),
],
vec![],
1000u32.into(),
)
},
vec![
"/ip4/34.65.251.121/tcp/30334/p2p/12D3KooWG3GrM6XKMM4gp3cvemdwUvu96ziYoJmqmetLZBXE8bSa".parse().unwrap(),
"/ip4/34.65.35.228/tcp/30334/p2p/12D3KooWMRyTLrCEPcAQD6c4EnudL3vVzg9zji3whvsMYPUYevpq".parse().unwrap(),
"/ip4/34.83.247.146/tcp/30334/p2p/12D3KooWE4jFh5FpJDkWVZhnWtFnbSqRhdjvC7Dp9b8b3FTuubQC".parse().unwrap(),
"/ip4/104.199.117.230/tcp/30334/p2p/12D3KooWG9R8pVXKumVo2rdkeVD4j5PVhRTqmYgLHY3a4yPYgLqM".parse().unwrap(),
],
None,
None,
None,
Some(properties),
Extensions { relay_chain: "polkadot".into(), para_id: 1000 },
)
}
fn statemint_genesis(
invulnerables: Vec<(AccountId, AuraId)>,
invulnerables: Vec<(AccountId, StatemintAuraId)>,
endowed_accounts: Vec<AccountId>,
id: ParaId,
) -> statemint_runtime::GenesisConfig {
@@ -386,6 +460,9 @@ fn statemint_genesis(
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: statemint_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
}
}
@@ -406,7 +483,7 @@ pub fn statemine_development_config() -> StatemineChainSpec {
// initial collators.
vec![(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed("Alice"),
get_collator_keys_from_seed::<AuraId>("Alice"),
)],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
@@ -420,6 +497,7 @@ pub fn statemine_development_config() -> StatemineChainSpec {
Vec::new(),
None,
None,
None,
Some(properties),
Extensions { relay_chain: "kusama-dev".into(), para_id: 1000 },
)
@@ -443,11 +521,11 @@ pub fn statemine_local_config() -> StatemineChainSpec {
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed("Alice"),
get_collator_keys_from_seed::<AuraId>("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed("Bob"),
get_collator_keys_from_seed::<AuraId>("Bob"),
),
],
vec![
@@ -470,6 +548,7 @@ pub fn statemine_local_config() -> StatemineChainSpec {
Vec::new(),
None,
None,
None,
Some(properties),
Extensions { relay_chain: "kusama-local".into(), para_id: 1000 },
)
@@ -523,6 +602,7 @@ pub fn statemine_config() -> StatemineChainSpec {
Vec::new(),
None,
None,
None,
Some(properties),
Extensions { relay_chain: "kusama".into(), para_id: 1000 },
)
@@ -567,6 +647,9 @@ fn statemine_genesis(
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: statemine_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
}
}
@@ -586,7 +669,7 @@ pub fn westmint_development_config() -> WestmintChainSpec {
// initial collators.
vec![(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed("Alice"),
get_collator_keys_from_seed::<AuraId>("Alice"),
)],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
@@ -594,13 +677,13 @@ pub fn westmint_development_config() -> WestmintChainSpec {
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
],
get_account_id_from_seed::<sr25519::Public>("Alice"),
1000.into(),
)
},
Vec::new(),
None,
None,
None,
Some(properties),
Extensions { relay_chain: "westend".into(), para_id: 1000 },
)
@@ -623,11 +706,11 @@ pub fn westmint_local_config() -> WestmintChainSpec {
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed("Alice"),
get_collator_keys_from_seed::<AuraId>("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed("Bob"),
get_collator_keys_from_seed::<AuraId>("Bob"),
),
],
vec![
@@ -644,13 +727,13 @@ pub fn westmint_local_config() -> WestmintChainSpec {
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
get_account_id_from_seed::<sr25519::Public>("Alice"),
1000.into(),
)
},
Vec::new(),
None,
None,
None,
Some(properties),
Extensions { relay_chain: "westend-local".into(), para_id: 1000 },
)
@@ -697,14 +780,13 @@ pub fn westmint_config() -> WestmintChainSpec {
),
],
Vec::new(),
// re-use the Westend sudo key
hex!("6648d7f3382690650c681aba1b993cd11e54deb4df21a3a18c3e2177de9f7342").into(),
1000.into(),
)
},
Vec::new(),
None,
None,
None,
Some(properties),
Extensions { relay_chain: "westend".into(), para_id: 1000 },
)
@@ -713,7 +795,6 @@ pub fn westmint_config() -> WestmintChainSpec {
fn westmint_genesis(
invulnerables: Vec<(AccountId, AuraId)>,
endowed_accounts: Vec<AccountId>,
root_key: AccountId,
id: ParaId,
) -> westmint_runtime::GenesisConfig {
westmint_runtime::GenesisConfig {
@@ -725,7 +806,6 @@ fn westmint_genesis(
balances: westmint_runtime::BalancesConfig {
balances: endowed_accounts.iter().cloned().map(|k| (k, WESTMINT_ED * 4096)).collect(),
},
sudo: westmint_runtime::SudoConfig { key: Some(root_key) },
parachain_info: westmint_runtime::ParachainInfoConfig { parachain_id: id },
collator_selection: westmint_runtime::CollatorSelectionConfig {
invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(),
@@ -749,5 +829,264 @@ fn westmint_genesis(
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: westmint_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
}
}
/// We use the same runtime on kusama and rococo.
pub type CanvasKusamaChainSpec =
sc_service::GenericChainSpec<canvas_kusama_runtime::GenesisConfig, Extensions>;
/// No relay chain suffix because the id is the same over all relay chains.
const CANVAS_PARACHAIN_ID: u32 = 1002;
/// The existential deposit is determined by the runtime "canvas-kusama".
const CANVAS_KUSAMA_ED: canvas_kusama_runtime::Balance =
canvas_kusama_runtime::constants::currency::EXISTENTIAL_DEPOSIT;
pub fn canvas_rococo_development_config() -> CanvasKusamaChainSpec {
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "ROC".into());
properties.insert("tokenDecimals".into(), 12.into());
CanvasKusamaChainSpec::from_genesis(
// Name
"Canvas on Rococo Development",
// ID
"canvas-rococo-dev",
ChainType::Development,
move || {
canvas_kusama_genesis(
// initial collators.
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed::<canvas_kusama_runtime::AuraId>("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed::<canvas_kusama_runtime::AuraId>("Bob"),
),
],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
CANVAS_PARACHAIN_ID.into(),
)
},
Vec::new(),
None,
None,
None,
None,
Extensions {
relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
para_id: CANVAS_PARACHAIN_ID,
},
)
}
pub fn canvas_rococo_local_config() -> CanvasKusamaChainSpec {
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "ROC".into());
properties.insert("tokenDecimals".into(), 12.into());
CanvasKusamaChainSpec::from_genesis(
// Name
"Canvas on Rococo",
// ID
"canvas-rococo-local",
ChainType::Local,
move || {
canvas_kusama_genesis(
// initial collators.
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed::<canvas_kusama_runtime::AuraId>("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed::<canvas_kusama_runtime::AuraId>("Bob"),
),
],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
CANVAS_PARACHAIN_ID.into(),
)
},
// Bootnodes
Vec::new(),
// Telemetry
None,
// Protocol ID
None,
// Fork ID
None,
// Properties
Some(properties),
// Extensions
Extensions {
relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
para_id: CANVAS_PARACHAIN_ID,
},
)
}
pub fn canvas_rococo_config() -> CanvasKusamaChainSpec {
// Give your base currency a unit name and decimal places
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "ROC".into());
properties.insert("tokenDecimals".into(), 12.into());
CanvasKusamaChainSpec::from_genesis(
// Name
"Canvas on Rococo",
// ID
"canvas-rococo",
ChainType::Live,
move || {
canvas_kusama_genesis(
vec![
// 5GKFbTTgrVS4Vz1UWWHPqMZQNFWZtqo7H2KpCDyYhEL3aS26
(
hex!["bc09354c12c054c8f6b3da208485eacec4ac648bad348895273b37bab5a0937c"]
.into(),
hex!["bc09354c12c054c8f6b3da208485eacec4ac648bad348895273b37bab5a0937c"]
.unchecked_into(),
),
// 5EPRJHm2GpABVWcwnAujcrhnrjFZyDGd5TwKFzkBoGgdRyv2
(
hex!["66be63b7bcbfb91040e5248e2d1ceb822cf219c57848c5924ffa3a1f8e67ba72"]
.into(),
hex!["66be63b7bcbfb91040e5248e2d1ceb822cf219c57848c5924ffa3a1f8e67ba72"]
.unchecked_into(),
),
// 5GH62vrJrVZxLREcHzm2PR5uTLAT5RQMJitoztCGyaP4o3uM
(
hex!["ba62886472a0a9f66b5e39f1469ce1c5b3d8cad6be39078daf16f111e89d1e44"]
.into(),
hex!["ba62886472a0a9f66b5e39f1469ce1c5b3d8cad6be39078daf16f111e89d1e44"]
.unchecked_into(),
),
// 5FHfoJDLdjRYX5KXLRqMDYBbWrwHLMtti21uK4QByUoUAbJF
(
hex!["8e97f65cda001976311df9bed39e8d0c956089093e94a75ef76fe9347a0eda7b"]
.into(),
hex!["8e97f65cda001976311df9bed39e8d0c956089093e94a75ef76fe9347a0eda7b"]
.unchecked_into(),
),
],
// Warning: The configuration for a production chain should not contain
// any endowed accounts here, otherwise it'll be minting extra native tokens
// from the relay chain on the parachain.
vec![
// NOTE: Remove endowed accounts if deployed on other relay chains.
// Endowed accounts
hex!["baa78c7154c7f82d6d377177e20bcab65d327eca0086513f9964f5a0f6bdad56"].into(),
// AccountId of an account which `ink-waterfall` uses for automated testing
hex!["0e47e2344d523c3cc5c34394b0d58b9a4200e813a038e6c5a6163cc07d70b069"].into(),
],
CANVAS_PARACHAIN_ID.into(),
)
},
// Bootnodes
vec![
"/ip4/34.90.191.237/tcp/30333/p2p/12D3KooWKg3Rpxcr9oJ8n6khoxpGKWztCZydtUZk2cojHqnfLrpj"
.parse()
.expect("MultiaddrWithPeerId"),
"/ip4/35.204.68.28/tcp/30333/p2p/12D3KooWPEXYrz8tHU3nDtPoPw4V7ou5dzMEWSTuUj7vaWiYVAVh"
.parse()
.expect("MultiaddrWithPeerId"),
"/ip4/34.90.139.15/tcp/30333/p2p/12D3KooWEVU8AFNary4nP4qEnEcwJaRuy59Wefekzdu9pKbnVEhk"
.parse()
.expect("MultiaddrWithPeerId"),
"/ip4/35.204.99.97/tcp/30333/p2p/12D3KooWP6pV3ZmcXzGDjv8ZMgA6nZxfAKDxSz4VNiLx6vVCQgJX"
.parse()
.expect("MultiaddrWithPeerId"),
],
// Telemetry
None,
// Protocol ID
None,
// Fork ID
None,
// Properties
Some(properties),
// Extensions
Extensions { relay_chain: "rococo".into(), para_id: CANVAS_PARACHAIN_ID },
)
}
fn canvas_kusama_genesis(
invulnerables: Vec<(AccountId, AuraId)>,
endowed_accounts: Vec<AccountId>,
id: ParaId,
) -> canvas_kusama_runtime::GenesisConfig {
canvas_kusama_runtime::GenesisConfig {
system: canvas_kusama_runtime::SystemConfig {
code: canvas_kusama_runtime::WASM_BINARY
.expect("WASM binary was not build, please build it!")
.to_vec(),
},
balances: canvas_kusama_runtime::BalancesConfig {
balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(),
},
parachain_info: canvas_kusama_runtime::ParachainInfoConfig { parachain_id: id },
collator_selection: canvas_kusama_runtime::CollatorSelectionConfig {
invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(),
candidacy_bond: CANVAS_KUSAMA_ED * 16,
..Default::default()
},
session: canvas_kusama_runtime::SessionConfig {
keys: invulnerables
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
canvas_kusama_runtime::SessionKeys { aura }, // session keys
)
})
.collect(),
},
// no need to pass anything to aura, in fact it will panic if we do. Session will take care
// of this.
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: canvas_kusama_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
sudo: canvas_kusama_runtime::SudoConfig {
key: Some(
hex!["2681a28014e7d3a5bfb32a003b3571f53c408acbc28d351d6bf58f5028c4ef14"].into(),
),
},
}
}
+24 -29
View File
@@ -15,19 +15,19 @@
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::chain_spec;
use clap::Parser;
use sc_cli;
use std::path::PathBuf;
use structopt::StructOpt;
/// Sub-commands supported by the collator.
#[derive(Debug, StructOpt)]
#[derive(Debug, clap::Subcommand)]
pub enum Subcommand {
/// Export the genesis state of the parachain.
#[structopt(name = "export-genesis-state")]
#[clap(name = "export-genesis-state")]
ExportGenesisState(ExportGenesisStateCommand),
/// Export the genesis wasm of the parachain.
#[structopt(name = "export-genesis-wasm")]
#[clap(name = "export-genesis-wasm")]
ExportGenesisWasm(ExportGenesisWasmCommand),
/// Build a chain specification.
@@ -52,69 +52,64 @@ pub enum Subcommand {
Revert(sc_cli::RevertCmd),
/// The custom benchmark subcommmand benchmarking runtime pallets.
#[structopt(name = "benchmark", about = "Benchmark runtime pallets.")]
#[clap(name = "benchmark", about = "Benchmark runtime pallets.")]
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
/// Try some testing command against a specified runtime state.
TryRuntime(try_runtime_cli::TryRuntimeCmd),
/// Key management CLI utilities
#[clap(subcommand)]
Key(sc_cli::KeySubcommand),
}
/// Command for exporting the genesis state of the parachain
#[derive(Debug, StructOpt)]
#[derive(Debug, Parser)]
pub struct ExportGenesisStateCommand {
/// Output file name or stdout if unspecified.
#[structopt(parse(from_os_str))]
#[clap(parse(from_os_str))]
pub output: Option<PathBuf>,
/// Id of the parachain this state is for.
///
/// Default: 100
#[structopt(long)]
pub parachain_id: Option<u32>,
/// Write output in binary. Default is to write in hex.
#[structopt(short, long)]
#[clap(short, long)]
pub raw: bool,
/// The name of the chain for that the genesis state should be exported.
#[structopt(long)]
#[clap(long)]
pub chain: Option<String>,
}
/// Command for exporting the genesis wasm file.
#[derive(Debug, StructOpt)]
#[derive(Debug, Parser)]
pub struct ExportGenesisWasmCommand {
/// Output file name or stdout if unspecified.
#[structopt(parse(from_os_str))]
#[clap(parse(from_os_str))]
pub output: Option<PathBuf>,
/// Write output in binary. Default is to write in hex.
#[structopt(short, long)]
#[clap(short, long)]
pub raw: bool,
/// The name of the chain for that the genesis wasm file should be exported.
#[structopt(long)]
#[clap(long)]
pub chain: Option<String>,
}
#[derive(Debug, StructOpt)]
#[structopt(settings = &[
structopt::clap::AppSettings::GlobalVersion,
structopt::clap::AppSettings::ArgsNegateSubcommands,
structopt::clap::AppSettings::SubcommandsNegateReqs,
])]
#[derive(Debug, Parser)]
#[clap(
propagate_version = true,
args_conflicts_with_subcommands = true,
subcommand_negates_reqs = true
)]
pub struct Cli {
#[structopt(subcommand)]
#[clap(subcommand)]
pub subcommand: Option<Subcommand>,
#[structopt(flatten)]
#[clap(flatten)]
pub run: cumulus_client_cli::RunCmd,
/// Relay chain arguments
#[structopt(raw = true)]
#[clap(raw = true, conflicts_with = "relay-chain-rpc-url")]
pub relaychain_args: Vec<String>,
}
@@ -139,6 +134,6 @@ impl RelayChainCli {
let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec);
let chain_id = extension.map(|e| e.relay_chain.clone());
let base_path = para_config.base_path.as_ref().map(|x| x.path().join("polkadot"));
Self { base_path, chain_id, base: polkadot_cli::RunCmd::from_iter(relay_chain_args) }
Self { base_path, chain_id, base: polkadot_cli::RunCmd::parse_from(relay_chain_args) }
}
}
+103 -36
View File
@@ -18,15 +18,15 @@ use crate::{
chain_spec,
cli::{Cli, RelayChainCli, Subcommand},
service::{
new_partial, Block, RococoParachainRuntimeExecutor, SeedlingRuntimeExecutor,
ShellRuntimeExecutor, StatemineRuntimeExecutor, StatemintRuntimeExecutor,
WestmintRuntimeExecutor,
new_partial, Block, ShellRuntimeExecutor, StatemineRuntimeExecutor,
StatemintRuntimeExecutor, WestmintRuntimeExecutor,
},
};
use codec::Encode;
use cumulus_client_service::genesis::generate_genesis_block;
use cumulus_primitives_core::ParaId;
use log::info;
use parachains_common::{AuraId, StatemintAuraId};
use polkadot_parachain::primitives::AccountIdConversion;
use sc_cli::{
ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams,
@@ -46,6 +46,7 @@ trait IdentifyChain {
fn is_statemint(&self) -> bool;
fn is_statemine(&self) -> bool;
fn is_westmint(&self) -> bool;
fn is_canvas_kusama(&self) -> bool;
}
impl IdentifyChain for dyn sc_service::ChainSpec {
@@ -64,6 +65,10 @@ impl IdentifyChain for dyn sc_service::ChainSpec {
fn is_westmint(&self) -> bool {
self.id().starts_with("westmint")
}
fn is_canvas_kusama(&self) -> bool {
// we use the same runtime on rococo and kusama
self.id().starts_with("canvas-kusama") || self.id().starts_with("canvas-rococo")
}
}
impl<T: sc_service::ChainSpec + 'static> IdentifyChain for T {
@@ -82,6 +87,9 @@ impl<T: sc_service::ChainSpec + 'static> IdentifyChain for T {
fn is_westmint(&self) -> bool {
<dyn sc_service::ChainSpec>::is_westmint(self)
}
fn is_canvas_kusama(&self) -> bool {
<dyn sc_service::ChainSpec>::is_canvas_kusama(self)
}
}
fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
@@ -97,9 +105,17 @@ fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, St
&include_bytes!("../res/track.json")[..],
)?),
"shell" => Box::new(chain_spec::get_shell_chain_spec()),
// -- Statemint
"seedling" => Box::new(chain_spec::get_seedling_chain_spec()),
"statemint-dev" => Box::new(chain_spec::statemint_development_config()),
"statemint-local" => Box::new(chain_spec::statemint_local_config()),
// the chain spec as used for generating the upgrade genesis values
"statemint-genesis" => Box::new(chain_spec::statemint_config()),
// the shell-based chain spec as used for syncing
"statemint" => Box::new(chain_spec::ChainSpec::from_json_bytes(
&include_bytes!("../res/statemint.json")[..],
)?),
// -- Statemine
"statemine-dev" => Box::new(chain_spec::statemine_development_config()),
"statemine-local" => Box::new(chain_spec::statemine_local_config()),
// the chain spec as used for generating the upgrade genesis values
@@ -108,6 +124,7 @@ fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, St
"statemine" => Box::new(chain_spec::ChainSpec::from_json_bytes(
&include_bytes!("../res/statemine.json")[..],
)?),
// -- Westmint
"westmint-dev" => Box::new(chain_spec::westmint_development_config()),
"westmint-local" => Box::new(chain_spec::westmint_local_config()),
// the chain spec as used for generating the upgrade genesis values
@@ -116,7 +133,16 @@ fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, St
"westmint" => Box::new(chain_spec::ChainSpec::from_json_bytes(
&include_bytes!("../res/westmint.json")[..],
)?),
// -- Canvas on Rococo
"canvas-rococo-dev" => Box::new(chain_spec::canvas_rococo_development_config()),
"canvas-rococo-local" => Box::new(chain_spec::canvas_rococo_local_config()),
"canvas-rococo-genesis" => Box::new(chain_spec::canvas_rococo_config()),
"canvas-rococo" => Box::new(chain_spec::ChainSpec::from_json_bytes(
&include_bytes!("../res/canvas-rococo.json")[..],
)?),
// -- Fallback (generic chainspec)
"" => Box::new(chain_spec::get_chain_spec()),
// -- Loading a specific spec from disk
path => {
let chain_spec = chain_spec::ChainSpec::from_json_file(path.into())?;
if chain_spec.is_statemint() {
@@ -129,6 +155,8 @@ fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, St
Box::new(chain_spec::ShellChainSpec::from_json_file(path.into())?)
} else if chain_spec.is_seedling() {
Box::new(chain_spec::SeedlingChainSpec::from_json_file(path.into())?)
} else if chain_spec.is_canvas_kusama() {
Box::new(chain_spec::CanvasKusamaChainSpec::from_json_file(path.into())?)
} else {
Box::new(chain_spec)
}
@@ -182,6 +210,8 @@ impl SubstrateCli for Cli {
&shell_runtime::VERSION
} else if chain_spec.is_seedling() {
&seedling_runtime::VERSION
} else if chain_spec.is_canvas_kusama() {
&canvas_kusama_runtime::VERSION
} else {
&rococo_parachain_runtime::VERSION
}
@@ -243,34 +273,34 @@ macro_rules! construct_async_run {
let runner = $cli.create_runner($cmd)?;
if runner.config().chain_spec.is_westmint() {
runner.async_run(|$config| {
let $components = new_partial::<westmint_runtime::RuntimeApi, WestmintRuntimeExecutor, _>(
let $components = new_partial::<westmint_runtime::RuntimeApi, _>(
&$config,
crate::service::statemint_build_import_queue,
crate::service::statemint_build_import_queue::<_, AuraId>,
)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
} else if runner.config().chain_spec.is_statemine() {
runner.async_run(|$config| {
let $components = new_partial::<statemine_runtime::RuntimeApi, StatemineRuntimeExecutor, _>(
let $components = new_partial::<statemine_runtime::RuntimeApi, _>(
&$config,
crate::service::statemint_build_import_queue,
crate::service::statemint_build_import_queue::<_, AuraId>,
)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
} else if runner.config().chain_spec.is_statemint() {
runner.async_run(|$config| {
let $components = new_partial::<statemint_runtime::RuntimeApi, StatemintRuntimeExecutor, _>(
let $components = new_partial::<statemint_runtime::RuntimeApi, _>(
&$config,
crate::service::statemint_build_import_queue,
crate::service::statemint_build_import_queue::<_, StatemintAuraId>,
)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
} else if runner.config().chain_spec.is_shell() {
runner.async_run(|$config| {
let $components = new_partial::<shell_runtime::RuntimeApi, ShellRuntimeExecutor, _>(
let $components = new_partial::<shell_runtime::RuntimeApi, _>(
&$config,
crate::service::shell_build_import_queue,
)?;
@@ -279,18 +309,26 @@ macro_rules! construct_async_run {
})
} else if runner.config().chain_spec.is_seedling() {
runner.async_run(|$config| {
let $components = new_partial::<seedling_runtime::RuntimeApi, SeedlingRuntimeExecutor, _>(
let $components = new_partial::<seedling_runtime::RuntimeApi, _>(
&$config,
crate::service::shell_build_import_queue,
)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
} else if runner.config().chain_spec.is_canvas_kusama() {
runner.async_run(|$config| {
let $components = new_partial::<canvas_kusama_runtime::RuntimeApi, _>(
&$config,
crate::service::canvas_kusama_build_import_queue,
)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
} else {
runner.async_run(|$config| {
let $components = new_partial::<
rococo_parachain_runtime::RuntimeApi,
RococoParachainRuntimeExecutor,
_
>(
&$config,
@@ -418,7 +456,7 @@ pub fn run() -> Result<()> {
You can enable it with `--features runtime-benchmarks`."
.into())
},
Some(Subcommand::TryRuntime(cmd)) =>
Some(Subcommand::TryRuntime(cmd)) => {
if cfg!(feature = "try-runtime") {
// grab the task manager.
let runner = cli.create_runner(cmd)?;
@@ -448,10 +486,12 @@ pub fn run() -> Result<()> {
}
} else {
Err("Try-runtime must be enabled by `--features try-runtime`.".into())
},
}
},
Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?),
None => {
let runner = cli.create_runner(&cli.run.normalize())?;
let collator_options = cli.run.collator_options();
runner.run_node_until_exit(|config| async move {
let para_id = chain_spec::Extensions::try_get(&*config.chain_spec)
@@ -491,48 +531,71 @@ pub fn run() -> Result<()> {
if config.chain_spec.is_statemint() {
crate::service::start_statemint_node::<
statemint_runtime::RuntimeApi,
StatemintRuntimeExecutor,
>(config, polkadot_config, id)
StatemintAuraId,
>(config, polkadot_config, collator_options, id)
.await
.map(|r| r.0)
.map_err(Into::into)
} else if config.chain_spec.is_statemine() {
crate::service::start_statemint_node::<
statemine_runtime::RuntimeApi,
StatemineRuntimeExecutor,
>(config, polkadot_config, id)
crate::service::start_statemint_node::<statemine_runtime::RuntimeApi, AuraId>(
config,
polkadot_config,
collator_options,
id,
)
.await
.map(|r| r.0)
.map_err(Into::into)
} else if config.chain_spec.is_westmint() {
crate::service::start_statemint_node::<
westmint_runtime::RuntimeApi,
WestmintRuntimeExecutor,
>(config, polkadot_config, id)
crate::service::start_statemint_node::<westmint_runtime::RuntimeApi, AuraId>(
config,
polkadot_config,
collator_options,
id,
)
.await
.map(|r| r.0)
.map_err(Into::into)
} else if config.chain_spec.is_shell() {
crate::service::start_shell_node::<
shell_runtime::RuntimeApi,
ShellRuntimeExecutor,
>(config, polkadot_config, id)
crate::service::start_shell_node::<shell_runtime::RuntimeApi>(
config,
polkadot_config,
collator_options,
id,
)
.await
.map(|r| r.0)
.map_err(Into::into)
} else if config.chain_spec.is_seedling() {
crate::service::start_shell_node::<
seedling_runtime::RuntimeApi,
SeedlingRuntimeExecutor,
>(config, polkadot_config, id)
crate::service::start_shell_node::<seedling_runtime::RuntimeApi>(
config,
polkadot_config,
collator_options,
id,
)
.await
.map(|r| r.0)
.map_err(Into::into)
} else if config.chain_spec.is_canvas_kusama() {
crate::service::start_canvas_kusama_node(
config,
polkadot_config,
collator_options,
id,
)
.await
.map(|r| r.0)
.map_err(Into::into)
} else {
crate::service::start_rococo_parachain_node(config, polkadot_config, id)
.await
.map(|r| r.0)
.map_err(Into::into)
crate::service::start_rococo_parachain_node(
config,
polkadot_config,
collator_options,
id,
)
.await
.map(|r| r.0)
.map_err(Into::into)
}
})
},
@@ -670,4 +733,8 @@ impl CliConfiguration<Self> for RelayChainCli {
) -> Result<Option<sc_telemetry::TelemetryEndpoints>> {
self.base.base.telemetry_endpoints(chain_spec)
}
fn node_name(&self) -> Result<String> {
self.base.base.node_name()
}
}
+31 -2
View File
@@ -20,6 +20,8 @@
use std::sync::Arc;
use pallet_contracts_rpc::{Contracts, ContractsApi};
use parachains_common::{AccountId, Balance, Block, BlockNumber, Hash, Index as Nonce};
use sc_client_api::AuxStore;
pub use sc_rpc::{DenyUnsafe, SubscriptionTaskExecutor};
use sc_transaction_pool_api::TransactionPool;
@@ -27,8 +29,6 @@ use sp_api::ProvideRuntimeApi;
use sp_block_builder::BlockBuilder;
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
use parachains_common::{AccountId, Balance, Block, Index as Nonce};
/// A type representing all RPC extensions.
pub type RpcExtension = jsonrpc_core::IoHandler<sc_rpc::Metadata>;
@@ -68,3 +68,32 @@ where
io
}
/// Instantiate all RPCs we want at the canvas-kusama chain.
pub fn create_canvas_kusama<C, P>(deps: FullDeps<C, P>) -> RpcExtension
where
C: ProvideRuntimeApi<Block>
+ HeaderBackend<Block>
+ AuxStore
+ HeaderMetadata<Block, Error = BlockChainError>
+ Send
+ Sync
+ 'static,
C::Api: frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
C::Api: pallet_contracts_rpc::ContractsRuntimeApi<Block, AccountId, Balance, BlockNumber, Hash>,
C::Api: BlockBuilder<Block>,
P: TransactionPool + Sync + Send + 'static,
{
use frame_rpc_system::{FullSystem, SystemApi};
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
let mut io = jsonrpc_core::IoHandler::default();
let FullDeps { client, pool, deny_unsafe } = deps;
io.extend_with(SystemApi::to_delegate(FullSystem::new(client.clone(), pool, deny_unsafe)));
io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone())));
io.extend_with(ContractsApi::to_delegate(Contracts::new(client)));
io
}
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More