Merge commit '392447f5c8f986ded2559a78457f4cd87942f393' into update-bridges-subtree-r/w

This commit is contained in:
antonio-dropulic
2021-12-01 09:46:14 +01:00
321 changed files with 28385 additions and 10466 deletions
+156 -96
View File
@@ -1,33 +1,111 @@
90 90
annualised/MS
Apache-2.0/M &&
AccountId/MS 1KB
api/SM 1MB
auth 5MB
auths/SM =
API/SM API/SM
APIs APIs
arg AccountId/MS
args Apache-2.0/M
aren Autogenerated
async
Best/MS
benchmarking/MS
BlockId
BFT/M BFT/M
bitfield/MS
blake2/MS
blockchain/MS
boolean
borked
BridgeStorage
BlockNumber
BTC/S BTC/S
Best/MS
BlockId
BlockNumber
BridgeStorage
CLI/MS CLI/MS
Chain1 Chain1
Chain2 Chain2
ChainSpec ChainSpec
ChainTime ChainTime
DOT/S
ERC-20
Ethereum
FN
FinalizationError
GPL/M
GPLv3/M
GiB/S
Handler/MS
Hasher
HeaderA
HeaderId
InitiateChange
Instance1
Instance2
Instance42
InstantCurrencyPayments
KSM/S
KYC/M
keypair/MS
KeyPair
Kovan
Lane1
Lane2
Lane3
LaneId
MIN_SIZE
MIT/M
MMR
MaxUnrewardedRelayerEntriesAtInboundLane
MaybeExtra
MaybeOrphan
Merklized
MessageNonce
MessageNonces
MessagePayload
MetricsParams
Millau/MS
OldHeader
OutboundMessages
PoA
PoV/MS
Pre
RLP
RPC/MS
Rialto/MS
Relayer/MS
Runtime1
Runtime2
SIZE_FACTOR
SS58
SS58Prefix
STALL_SYNC_TIMEOUT
SURI
ServiceFactory/MS
SignedExtension
Stringified
Submitter1
S|N
TCP
ThisChain
TODO
U256
Unparsed
Vec
WND/S
Westend/MS
Wococo/MS
XCM/S
XCMP/M
annualised/MS
api/SM
aren
arg
args
async
auth
auths/SM
backoff
benchmarking/MS
best_substrate_header
bitfield/MS
blake2/MS
blockchain/MS
borked
chain_getBlock chain_getBlock
choosen choosen
config/MS config/MS
@@ -36,146 +114,128 @@ crypto/MS
customizable/B customizable/B
Debian/M Debian/M
decodable/MS decodable/MS
DOT/S delivery_and_dispatch_fee
doesn dev
dispatchable
dispatchables dispatchables
doesn
ed25519 ed25519
enum/MS enum/MS
ERC-20 entrypoint/MS
ethereum/MS ethereum/MS
externality/MS externality/MS
extrinsic/MS extrinsic/MS
extrinsics extrinsics
fedora/M fedora/M
FN functor
FinalizationError fuzzer
GiB/S hasher
GPL/M hardcoded
GPLv3/M
Handler/MS
HeaderA
HeaderId
https https
implementers implementers
include/BG
inherent/MS inherent/MS
initialize/RG initialize/RG
instantiate/B instantiate/B
intrinsic/MS intrinsic/MS
intrinsics invariant/MS
InitiateChange invariants
isn
io io
isn
isolate/BG
js js
keccak256/M jsonrpsee
keypair/MS
KSM/S
Lane1
Lane2
Lane3
LaneId
kusama/S
KYC/M
keccak keccak
Kovan keccak256/M
keyring
keystore/MS
kusama/S
lane
malus
max_value
merkle/MS merkle/MS
MessageNonce metadata
MessageNonces millau
Merklized
MaybeOrphan
MaybeExtra
MetricsParams
MessagePayload
misbehavior/SM misbehavior/SM
misbehaviors misbehaviors
MIN_SIZE
MIT/M
max_value
multivalidator/SM multivalidator/SM
natively natively
OldHeader no_std
nonces nonces
number number
no_std
ok ok
oneshot/MS oneshot/MS
others' others'
OutboundMessages pallet_bridge_grandpa
pallet_bridge_messages
pallet_message_lane
parablock/MS parablock/MS
parachain/MS parachain/MS
param/MS
parameterize/D parameterize/D
pallet_message_lane
plancks plancks
polkadot/MS polkadot/MS
pov-block/MS pov-block/MS
PoA
PoV/MS
precommit precommit
prometheus prometheus
proxying proxying
prune_end
prune_depth
provisioner/MS provisioner/MS
probabilistically
prune_depth
prune_end
receival
reconnection
redhat/M redhat/M
repo/MS repo/MS
receival
RPC/MS
RLP
runtime/MS runtime/MS
Runtime1
Runtime2
rustc/MS rustc/MS
ServiceFactory/MS relayer/MS
SignedExtension shouldn
SIZE_FACTOR source_at_target
source_latest_confirmed
source_latest_generated
sp_finality_grandpa
spawner
sr25519 sr25519
SS58
SS58Prefix
src src
S|N stringified
SURI
source
struct/MS struct/MS
Submitter1
submitters/MS submitters/MS
subsystem/MS subsystem/MS
subsystems' subsystems'
shouldn subcommand/MS
synchronizer synchronizer
target_at_source
target_latest_confirmed
target_latest_received
taskmanager/MS taskmanager/MS
teleport/RG teleport/RG
teleportation/SM teleportation/SM
teleporter/SM teleporter/SM
teleporters teleporters
testnet/MS testnet/MS
timeframe
tokio
timestamp
trie/MS trie/MS
trustless/Y trustless/Y
ThisChain tuple
TCP u32
ubuntu/M ubuntu/M
union/MSG
undeliverable undeliverable
unfinalized unfinalized
union/MSG
unpruned unpruned
unservable/B unservable/B
unsynced unsynced
updatable
validator/SM
ve ve
vec vec
Vec
validator/SM
verifier verifier
w3f/MS w3f/MS
wakeup
wasm/M wasm/M
WND/S websocket
XCM/S x2
XCMP/M ~
include/BG
isolate/BG
Instance1
Instance2
Instance42
Pre
Rialto
stringified
Stringified
millau
Millau
+3
View File
@@ -14,3 +14,6 @@ indent_style=space
indent_size=2 indent_size=2
tab_width=8 tab_width=8
end_of_line=lf end_of_line=lf
[*.md]
max_line_length=80
+1
View File
@@ -18,6 +18,7 @@ hfuzz_workspace
.DS_Store .DS_Store
.cargo
.idea .idea
.vscode .vscode
*.iml *.iml
+38 -17
View File
@@ -15,7 +15,7 @@ variables: &default-vars
GIT_DEPTH: 100 GIT_DEPTH: 100
CARGO_INCREMENTAL: 0 CARGO_INCREMENTAL: 0
ARCH: "x86_64" ARCH: "x86_64"
CI_IMAGE: "paritytech/bridges-ci:production" CI_IMAGE: "paritytech/bridges-ci:staging"
RUST_BACKTRACE: full RUST_BACKTRACE: full
default: default:
@@ -76,6 +76,7 @@ default:
- if: $CI_PIPELINE_SOURCE == "pipeline" - if: $CI_PIPELINE_SOURCE == "pipeline"
when: never when: never
- if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1
- if: $CI_COMMIT_REF_NAME =~ /^v[0-9]{4}-[0-9]{2}-[0-9]{2}.*$/ # i.e. v2021-09-27, v2021-09-27-1
# there are two types of nightly pipelines: # there are two types of nightly pipelines:
# 1. this one is triggered by the schedule with $PIPELINE == "nightly", it's for releasing. # 1. this one is triggered by the schedule with $PIPELINE == "nightly", it's for releasing.
# this job runs only on nightly pipeline with the mentioned variable, against `master` branch # this job runs only on nightly pipeline with the mentioned variable, against `master` branch
@@ -93,26 +94,22 @@ clippy-nightly:
stage: lint stage: lint
<<: *docker-env <<: *docker-env
<<: *test-refs <<: *test-refs
variables:
RUSTFLAGS: "-D warnings"
script: script:
- cargo +nightly clippy --all-targets - SKIP_WASM_BUILD=1 cargo +nightly clippy --all-targets -- -A clippy::redundant_closure
# FIXME: remove when all the warns are fixed
allow_failure: true
fmt: fmt:
stage: lint stage: lint
<<: *docker-env <<: *docker-env
<<: *test-refs <<: *test-refs
script: script:
- cargo fmt --all -- --check - cargo +nightly fmt --all -- --check
spellcheck: spellcheck:
stage: lint stage: lint
<<: *docker-env <<: *docker-env
<<: *test-refs <<: *test-refs
script: script:
- cargo spellcheck check -m 1 -vv $(find modules/currency-exchange/src -name "*.rs") - cargo spellcheck check -vvvv --cfg=.config/spellcheck.toml --checkers hunspell -m 1
#### stage: check #### stage: check
@@ -121,11 +118,11 @@ check:
<<: *docker-env <<: *docker-env
<<: *test-refs <<: *test-refs
script: &check-script script: &check-script
- time cargo check --verbose --workspace - SKIP_WASM_BUILD=1 time cargo check --locked --verbose --workspace
# Check Rialto benchmarks runtime # Check Rialto benchmarks runtime
- time cargo check -p rialto-runtime --features runtime-benchmarks --verbose - SKIP_WASM_BUILD=1 time cargo check -p rialto-runtime --locked --features runtime-benchmarks --verbose
# Check Millau benchmarks runtime # Check Millau benchmarks runtime
- time cargo check -p millau-runtime --features runtime-benchmarks --verbose - SKIP_WASM_BUILD=1 time cargo check -p millau-runtime --locked --features runtime-benchmarks --verbose
check-nightly: check-nightly:
stage: check stage: check
@@ -141,8 +138,13 @@ test:
stage: test stage: test
<<: *docker-env <<: *docker-env
<<: *test-refs <<: *test-refs
# variables:
# RUSTFLAGS: "-D warnings"
script: &test-script script: &test-script
- time cargo test --verbose --workspace - time cargo fetch
- time cargo fetch --manifest-path=`cargo metadata --format-version=1 | jq --compact-output --raw-output ".packages[] | select(.name == \"polkadot-test-runtime\").manifest_path"`
- time cargo fetch --manifest-path=`cargo metadata --format-version=1 | jq --compact-output --raw-output ".packages[] | select(.name == \"polkadot-runtime\").manifest_path"`
- CARGO_NET_OFFLINE=true time cargo test --verbose --workspace
test-nightly: test-nightly:
stage: test stage: test
@@ -189,12 +191,17 @@ build:
<<: *collect-artifacts <<: *collect-artifacts
# master # master
script: &build-script script: &build-script
- time cargo build --release --verbose --workspace - time cargo fetch
- time cargo fetch --manifest-path=`cargo metadata --format-version=1 | jq --compact-output --raw-output ".packages[] | select(.name == \"polkadot-test-runtime\").manifest_path"`
- time cargo fetch --manifest-path=`cargo metadata --format-version=1 | jq --compact-output --raw-output ".packages[] | select(.name == \"polkadot-runtime\").manifest_path"`
- CARGO_NET_OFFLINE=true time cargo build --release --verbose --workspace
after_script: after_script:
# Prepare artifacts # Prepare artifacts
- mkdir -p ./artifacts - mkdir -p ./artifacts
- strip ./target/release/rialto-bridge-node - strip ./target/release/rialto-bridge-node
- mv -v ./target/release/rialto-bridge-node ./artifacts/ - mv -v ./target/release/rialto-bridge-node ./artifacts/
- strip ./target/release/rialto-parachain-collator
- mv -v ./target/release/rialto-parachain-collator ./artifacts/
- strip ./target/release/millau-bridge-node - strip ./target/release/millau-bridge-node
- mv -v ./target/release/millau-bridge-node ./artifacts/ - mv -v ./target/release/millau-bridge-node ./artifacts/
- strip ./target/release/ethereum-poa-relay - strip ./target/release/ethereum-poa-relay
@@ -223,6 +230,9 @@ build-nightly:
GIT_STRATEGY: none GIT_STRATEGY: none
DOCKERFILE: ci.Dockerfile DOCKERFILE: ci.Dockerfile
IMAGE_NAME: docker.io/paritytech/$CI_JOB_NAME IMAGE_NAME: docker.io/paritytech/$CI_JOB_NAME
VAULT_SERVER_URL: "https://vault.parity-mgmt-vault.parity.io"
VAULT_AUTH_PATH: "gitlab-parity-io-jwt"
VAULT_AUTH_ROLE: "cicd_gitlab_parity_${CI_PROJECT_NAME}"
needs: needs:
- job: build - job: build
artifacts: true artifacts: true
@@ -233,8 +243,15 @@ build-nightly:
VERSION=$(echo ${CI_COMMIT_REF_NAME} | sed -r 's#/+#-#g'); VERSION=$(echo ${CI_COMMIT_REF_NAME} | sed -r 's#/+#-#g');
fi fi
- echo "Effective tags = ${VERSION} sha-${CI_COMMIT_SHORT_SHA} latest" - echo "Effective tags = ${VERSION} sha-${CI_COMMIT_SHORT_SHA} latest"
secrets:
DOCKER_HUB_USER:
vault: cicd/gitlab/parity/DOCKER_HUB_USER@kv
file: false
DOCKER_HUB_PASS:
vault: cicd/gitlab/parity/DOCKER_HUB_PASS@kv
file: false
script: script:
- test "${Docker_Hub_User_Parity}" -a "${Docker_Hub_Pass_Parity}" || - test "${DOCKER_HUB_USER}" -a "${DOCKER_HUB_PASS}" ||
( echo "no docker credentials provided"; exit 1 ) ( echo "no docker credentials provided"; exit 1 )
- cd ./artifacts - cd ./artifacts
- buildah bud - buildah bud
@@ -248,19 +265,23 @@ build-nightly:
--tag "${IMAGE_NAME}:latest" --tag "${IMAGE_NAME}:latest"
--file "${DOCKERFILE}" . --file "${DOCKERFILE}" .
# The job will success only on the protected branch # The job will success only on the protected branch
- echo "$Docker_Hub_Pass_Parity" | - echo "${DOCKER_HUB_PASS}" |
buildah login --username "$Docker_Hub_User_Parity" --password-stdin docker.io buildah login --username "${DOCKER_HUB_USER}" --password-stdin docker.io
- buildah info - buildah info
- buildah push --format=v2s2 "${IMAGE_NAME}:${VERSION}" - buildah push --format=v2s2 "${IMAGE_NAME}:${VERSION}"
- buildah push --format=v2s2 "${IMAGE_NAME}:sha-${CI_COMMIT_SHORT_SHA}" - buildah push --format=v2s2 "${IMAGE_NAME}:sha-${CI_COMMIT_SHORT_SHA}"
- buildah push --format=v2s2 "${IMAGE_NAME}:latest" - buildah push --format=v2s2 "${IMAGE_NAME}:latest"
after_script: after_script:
- env REGISTRY_AUTH_FILE= buildah logout "$IMAGE_NAME" - env REGISTRY_AUTH_FILE= buildah logout --all
rialto-bridge-node: rialto-bridge-node:
stage: publish stage: publish
<<: *build-push-image <<: *build-push-image
rialto-parachain-collator:
stage: publish
<<: *build-push-image
millau-bridge-node: millau-bridge-node:
stage: publish stage: publish
<<: *build-push-image <<: *build-push-image
@@ -0,0 +1,103 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for `{{pallet}}`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}}
//! DATE: {{date}}, STEPS: {{cmd.steps}}, REPEAT: {{cmd.repeat}}
//! LOW RANGE: {{cmd.lowest_range_values}}, HIGH RANGE: {{cmd.highest_range_values}}
//! EXECUTION: {{cmd.execution}}, WASM-EXECUTION: {{cmd.wasm_execution}}
//! CHAIN: {{cmd.chain}}, DB CACHE: {{cmd.db_cache}}
// Executed Command:
{{#each args as |arg|~}}
// {{arg}}
{{/each}}
#![allow(clippy::all)]
#![allow(unused_parens)]
#![allow(unused_imports)]
use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use sp_std::marker::PhantomData;
/// Weight functions needed for `{{pallet}}`.
pub trait WeightInfo {
{{~#each benchmarks as |benchmark|}}
fn {{benchmark.name~}}
(
{{~#each benchmark.components as |c| ~}}
{{c.name}}: u32, {{/each~}}
) -> Weight;
{{~/each}}
}
/// Weights for `{{pallet}}` using the Millau node and recommended hardware.
pub struct MillauWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for MillauWeight<T> {
{{~#each benchmarks as |benchmark|}}
fn {{benchmark.name~}}
(
{{~#each benchmark.components as |c| ~}}
{{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}}
) -> Weight {
({{underscore benchmark.base_weight}} as Weight)
{{~#each benchmark.component_weight as |cw|}}
.saturating_add(({{underscore cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))
{{~/each}}
{{~#if (ne benchmark.base_reads "0")}}
.saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}} as Weight))
{{~/if}}
{{~#each benchmark.component_reads as |cr|}}
.saturating_add(T::DbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight)))
{{~/each}}
{{~#if (ne benchmark.base_writes "0")}}
.saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}} as Weight))
{{~/if}}
{{~#each benchmark.component_writes as |cw|}}
.saturating_add(T::DbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight)))
{{~/each}}
}
{{~/each}}
}
// For backwards compatibility and tests
impl WeightInfo for () {
{{~#each benchmarks as |benchmark|}}
fn {{benchmark.name~}}
(
{{~#each benchmark.components as |c| ~}}
{{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}}
) -> Weight {
({{underscore benchmark.base_weight}} as Weight)
{{~#each benchmark.component_weight as |cw|}}
.saturating_add(({{underscore cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))
{{~/each}}
{{~#if (ne benchmark.base_reads "0")}}
.saturating_add(RocksDbWeight::get().reads({{benchmark.base_reads}} as Weight))
{{~/if}}
{{~#each benchmark.component_reads as |cr|}}
.saturating_add(RocksDbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight)))
{{~/each}}
{{~#if (ne benchmark.base_writes "0")}}
.saturating_add(RocksDbWeight::get().writes({{benchmark.base_writes}} as Weight))
{{~/if}}
{{~#each benchmark.component_writes as |cw|}}
.saturating_add(RocksDbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight)))
{{~/each}}
}
{{~/each}}
}
@@ -12,9 +12,10 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. // along with Parity Bridges Common. If not, see
<http: //www.gnu.org/licenses />.
//! Autogenerated weights for {{cmd.pallet}} //! Autogenerated weights for `{{pallet}}`
//! //!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}} //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}}
//! DATE: {{date}}, STEPS: {{cmd.steps}}, REPEAT: {{cmd.repeat}} //! DATE: {{date}}, STEPS: {{cmd.steps}}, REPEAT: {{cmd.repeat}}
@@ -34,7 +35,7 @@
use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use sp_std::marker::PhantomData; use sp_std::marker::PhantomData;
/// Weight functions needed for {{pallet}}. /// Weight functions needed for `{{pallet}}`.
pub trait WeightInfo { pub trait WeightInfo {
{{~#each benchmarks as |benchmark|}} {{~#each benchmarks as |benchmark|}}
fn {{benchmark.name~}} fn {{benchmark.name~}}
@@ -45,7 +46,7 @@ pub trait WeightInfo {
{{~/each}} {{~/each}}
} }
/// Weights for {{pallet}} using the Rialto node and recommended hardware. /// Weights for `{{pallet}}` using the Rialto node and recommended hardware.
pub struct RialtoWeight<T>(PhantomData<T>); pub struct RialtoWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for RialtoWeight<T> { impl<T: frame_system::Config> WeightInfo for RialtoWeight<T> {
{{~#each benchmarks as |benchmark|}} {{~#each benchmarks as |benchmark|}}
@@ -62,13 +63,15 @@ impl<T: frame_system::Config> WeightInfo for RialtoWeight<T> {
.saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}} as Weight)) .saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}} as Weight))
{{~/if}} {{~/if}}
{{~#each benchmark.component_reads as |cr|}} {{~#each benchmark.component_reads as |cr|}}
.saturating_add(T::DbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight))) .saturating_add(T::DbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as
Weight)))
{{~/each}} {{~/each}}
{{~#if (ne benchmark.base_writes "0")}} {{~#if (ne benchmark.base_writes "0")}}
.saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}} as Weight)) .saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}} as Weight))
{{~/if}} {{~/if}}
{{~#each benchmark.component_writes as |cw|}} {{~#each benchmark.component_writes as |cw|}}
.saturating_add(T::DbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))) .saturating_add(T::DbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as
Weight)))
{{~/each}} {{~/each}}
} }
{{~/each}} {{~/each}}
@@ -90,13 +93,15 @@ impl WeightInfo for () {
.saturating_add(RocksDbWeight::get().reads({{benchmark.base_reads}} as Weight)) .saturating_add(RocksDbWeight::get().reads({{benchmark.base_reads}} as Weight))
{{~/if}} {{~/if}}
{{~#each benchmark.component_reads as |cr|}} {{~#each benchmark.component_reads as |cr|}}
.saturating_add(RocksDbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight))) .saturating_add(RocksDbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as
Weight)))
{{~/each}} {{~/each}}
{{~#if (ne benchmark.base_writes "0")}} {{~#if (ne benchmark.base_writes "0")}}
.saturating_add(RocksDbWeight::get().writes({{benchmark.base_writes}} as Weight)) .saturating_add(RocksDbWeight::get().writes({{benchmark.base_writes}} as Weight))
{{~/if}} {{~/if}}
{{~#each benchmark.component_writes as |cw|}} {{~#each benchmark.component_writes as |cw|}}
.saturating_add(RocksDbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))) .saturating_add(RocksDbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as
Weight)))
{{~/each}} {{~/each}}
} }
{{~/each}} {{~/each}}
+4982 -2388
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
[workspace]
resolver = "2"
members = [
"bin/*/node",
"bin/*/runtime",
"fuzz/*",
"modules/*",
"primitives/*",
"relays/*",
]
+88 -56
View File
@@ -38,6 +38,25 @@ cargo build --all
cargo test --all cargo test --all
``` ```
Also you can build the repo with
[Parity CI Docker image](https://github.com/paritytech/scripts/tree/master/dockerfiles/bridges-ci):
```bash
docker pull paritytech/bridges-ci:production
mkdir ~/cache
chown 1000:1000 ~/cache #processes in the container runs as "nonroot" user with UID 1000
docker run --rm -it -w /shellhere/parity-bridges-common \
-v /home/$(whoami)/cache/:/cache/ \
-v "$(pwd)":/shellhere/parity-bridges-common \
-e CARGO_HOME=/cache/cargo/ \
-e SCCACHE_DIR=/cache/sccache/ \
-e CARGO_TARGET_DIR=/cache/target/ paritytech/bridges-ci:production cargo build --all
#artifacts can be found in ~/cache/target
```
If you want to reproduce other steps of CI process you can use the following
[guide](https://github.com/paritytech/scripts#reproduce-ci-locally).
If you need more information about setting up your development environment Substrate's If you need more information about setting up your development environment Substrate's
[Getting Started](https://substrate.dev/docs/en/knowledgebase/getting-started/) page is a good [Getting Started](https://substrate.dev/docs/en/knowledgebase/getting-started/) page is a good
resource. resource.
@@ -102,10 +121,9 @@ the `relays` which are used to pass messages between chains.
To run the Bridge you need to be able to connect the bridge relay node to the RPC interface of nodes To run the Bridge you need to be able to connect the bridge relay node to the RPC interface of nodes
on each side of the bridge (source and target chain). on each side of the bridge (source and target chain).
There are 3 ways to run the bridge, described below: There are 2 ways to run the bridge, described below:
- building & running from source, - building & running from source
- building or using Docker images for each individual component,
- running a Docker Compose setup (recommended). - running a Docker Compose setup (recommended).
### Using the Source ### Using the Source
@@ -119,88 +137,102 @@ cargo build -p millau-bridge-node
cargo build -p substrate-relay cargo build -p substrate-relay
``` ```
### Running ### Running a Dev network
To run a simple dev network you'll can use the scripts located in We will launch a dev network to demonstrate how to relay a message between two Substrate based
[the `deployments/local-scripts` folder](./deployments/local-scripts). Since the relayer connects to chains (named Rialto and Millau).
both Substrate chains it must be run last.
To do this we will need two nodes, two relayers which will relay headers, and two relayers which
will relay messages.
#### Running from local scripts
To run a simple dev network you can use the scripts located in the
[`deployments/local-scripts` folder](./deployments/local-scripts).
First, we must run the two Substrate nodes.
```bash ```bash
# In `parity-bridges-common` folder # In `parity-bridges-common` folder
./deployments/local-scripts/run-rialto-node.sh ./deployments/local-scripts/run-rialto-node.sh
./deployments/local-scripts/run-millau-node.sh ./deployments/local-scripts/run-millau-node.sh
```
After the nodes are up we can run the header relayers.
```bash
./deployments/local-scripts/relay-millau-to-rialto.sh ./deployments/local-scripts/relay-millau-to-rialto.sh
./deployments/local-scripts/relay-rialto-to-millau.sh
``` ```
At this point you should see the relayer submitting headers from the Millau Substrate chain to the At this point you should see the relayer submitting headers from the Millau Substrate chain to the
Rialto Substrate chain. Rialto Substrate chain.
### Local Docker Setup ```
# Header Relayer Logs
To get up and running quickly you can use published Docker images for the bridge nodes and relayer. [Millau_to_Rialto_Sync] [date] DEBUG bridge Going to submit finality proof of Millau header #147 to Rialto
The images are published on [Docker Hub](https://hub.docker.com/u/paritytech). [...] [date] INFO bridge Synced 147 of 147 headers
[...] [date] DEBUG bridge Going to submit finality proof of Millau header #148 to Rialto
To run the dev network we first run the two bridge nodes: [...] [date] INFO bridge Synced 148 of 149 headers
```bash
docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \
-it paritytech/rialto-bridge-node --dev --tmp \
--rpc-cors=all --unsafe-rpc-external --unsafe-ws-external
docker run -p 30334:30333 -p 9934:9933 -p 9945:9944 \
-it paritytech/millau-bridge-node --dev --tmp \
--rpc-cors=all --unsafe-rpc-external --unsafe-ws-external
``` ```
Notice that the `docker run` command will accept all the normal Substrate flags. For local Finally, we can run the message relayers.
development you should at minimum run with the `--dev` flag or else no blocks will be produced.
Then we need to initialize and run the relayer:
```bash ```bash
docker run --network=host -it \ ./deployments/local-scripts/relay-messages-millau-to-rialto.sh
paritytech/substrate-relay init-bridge RialtoToMillau \ ./deployments/local-scripts/relay-messages-rialto-to-millau.sh
--target-host localhost \
--target-port 9945 \
--source-host localhost \
--source-port 9944 \
--target-signer //Alice
docker run --network=host -it \
paritytech/substrate-relay relay-headers RialtoToMillau \
--target-host localhost \
--target-port 9945 \
--source-host localhost \
--source-port 9944 \
--target-signer //Bob \
``` ```
You should now see the relayer submitting headers from the Millau chain to the Rialto chain. You will also see the message lane relayers listening for new messages.
If you don't want to use the published Docker images you can build images yourself. You can do this ```
by running the following commands at the top level of the repository. # Message Relayer Logs
[Millau_to_Rialto_MessageLane_00000000] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about best message nonces
```bash [...] [date] INFO bridge Synced Some(2) of Some(3) nonces in Millau::MessagesDelivery -> Rialto::MessagesDelivery race
# In `parity-bridges-common` folder [...] [date] DEBUG bridge Asking Millau::MessagesDelivery about message nonces
docker build . -t local/rialto-bridge-node --build-arg PROJECT=rialto-bridge-node [...] [date] DEBUG bridge Received best nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { latest_nonce: 0, nonces_data: () }
docker build . -t local/millau-bridge-node --build-arg PROJECT=millau-bridge-node [...] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about finalized message nonces
docker build . -t local/substrate-relay --build-arg PROJECT=substrate-relay [...] [date] DEBUG bridge Received finalized nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { latest_nonce: 0, nonces_data: () }
[...] [date] DEBUG bridge Received nonces from Millau::MessagesDelivery: SourceClientNonces { new_nonces: {}, confirmed_nonce: Some(0) }
[...] [date] DEBUG bridge Asking Millau node about its state
[...] [date] DEBUG bridge Received state from Millau node: ClientState { best_self: HeaderId(1593, 0xacac***), best_finalized_self: HeaderId(1590, 0x0be81d...), best_finalized_peer_at_best_self: HeaderId(0, 0xdcdd89...) }
``` ```
_Note: Building the node images will take a long time, so make sure you have some coffee handy._ To send a message see the ["How to send a message" section](#how-to-send-a-message).
Once you have the images built you can use them in the previous commands by replacing
`paritytech/<component_name>` with `local/<component_name>` everywhere.
### Full Network Docker Compose Setup ### Full Network Docker Compose Setup
For a more sophisticated deployment which includes bidirectional header sync, message passing, For a more sophisticated deployment which includes bidirectional header sync, message passing,
monitoring dashboards, etc. see the [Deployments README](./deployments/README.md). monitoring dashboards, etc. see the [Deployments README](./deployments/README.md).
You should note that you can find images for all the bridge components published on
[Docker Hub](https://hub.docker.com/u/paritytech).
To run a Rialto node for example, you can use the following command:
```bash
docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \
-it paritytech/rialto-bridge-node --dev --tmp \
--rpc-cors=all --unsafe-rpc-external --unsafe-ws-external
```
### How to send a message ### How to send a message
A straightforward way to interact with and test the bridge is sending messages. This is explained In this section we'll show you how to quickly send a bridge message, if you want to
in the [send message](./docs/send-message.md) document. interact with and test the bridge see more details in [send message](./docs/send-message.md)
```bash
# In `parity-bridges-common` folder
./scripts/send-message-from-millau-rialto.sh remark
```
After sending a message you will see the following logs showing a message was successfully sent:
```
INFO bridge Sending message to Rialto. Size: 286. Dispatch weight: 1038000. Fee: 275,002,568
INFO bridge Signed Millau Call: 0x7904...
TRACE bridge Sent transaction to Millau node: 0x5e68...
```
## Community ## Community
+2 -7
View File
@@ -10,13 +10,12 @@ repository = "https://github.com/paritytech/parity-bridges-common/"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0" license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies] [dependencies]
jsonrpc-core = "15.1.0" jsonrpc-core = "18.0"
structopt = "0.3.21" structopt = "0.3.21"
serde_json = "1.0.59" serde_json = "1.0.59"
# Bridge dependencies # Bridge dependencies
bp-messages = { path = "../../../primitives/messages" }
bp-millau = { path = "../../../primitives/chain-millau" } bp-millau = { path = "../../../primitives/chain-millau" }
bp-runtime = { path = "../../../primitives/runtime" } bp-runtime = { path = "../../../primitives/runtime" }
millau-runtime = { path = "../runtime" } millau-runtime = { path = "../runtime" }
@@ -45,7 +44,6 @@ sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "mast
sp-consensus-aura = { 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-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -56,9 +54,6 @@ frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", bran
[features] [features]
default = [] default = []
# TODO: https://github.com/paritytech/parity-bridges-common/issues/390
# I've left the feature flag here to test our CI configuration
runtime-benchmarks = [ runtime-benchmarks = [
# "millau-runtime/runtime-benchmarks", "millau-runtime/runtime-benchmarks",
] ]
@@ -16,8 +16,9 @@
use bp_millau::derive_account_from_rialto_id; use bp_millau::derive_account_from_rialto_id;
use millau_runtime::{ use millau_runtime::{
AccountId, AuraConfig, BalancesConfig, BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, SessionConfig, AccountId, AuraConfig, BalancesConfig, BridgeRialtoMessagesConfig, BridgeWestendGrandpaConfig,
SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig,
WASM_BINARY,
}; };
use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{sr25519, Pair, Public}; use sp_core::{sr25519, Pair, Public};
@@ -70,10 +71,7 @@ impl Alternative {
let properties = Some( let properties = Some(
serde_json::json!({ serde_json::json!({
"tokenDecimals": 9, "tokenDecimals": 9,
"tokenSymbol": "MLAU", "tokenSymbol": "MLAU"
"bridgeIds": {
"Rialto": bp_runtime::RIALTO_CHAIN_ID,
}
}) })
.as_object() .as_object()
.expect("Map given; qed") .expect("Map given; qed")
@@ -81,8 +79,8 @@ impl Alternative {
); );
match self { match self {
Alternative::Development => ChainSpec::from_genesis( Alternative::Development => ChainSpec::from_genesis(
"Development", "Millau Development",
"dev", "millau_dev",
sc_service::ChainType::Development, sc_service::ChainType::Development,
|| { || {
testnet_genesis( testnet_genesis(
@@ -107,8 +105,8 @@ impl Alternative {
None, None,
), ),
Alternative::LocalTestnet => ChainSpec::from_genesis( Alternative::LocalTestnet => ChainSpec::from_genesis(
"Local Testnet", "Millau Local",
"local_testnet", "millau_local",
sc_service::ChainType::Local, sc_service::ChainType::Local,
|| { || {
testnet_genesis( testnet_genesis(
@@ -137,10 +135,12 @@ impl Alternative {
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"), get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
get_account_id_from_seed::<sr25519::Public>("George//stash"), get_account_id_from_seed::<sr25519::Public>("George//stash"),
get_account_id_from_seed::<sr25519::Public>("Harry//stash"), get_account_id_from_seed::<sr25519::Public>("Harry//stash"),
pallet_bridge_messages::Pallet::< get_account_id_from_seed::<sr25519::Public>("RialtoMessagesOwner"),
millau_runtime::Runtime, get_account_id_from_seed::<sr25519::Public>("WithRialtoTokenSwap"),
pallet_bridge_messages::DefaultInstance, pallet_bridge_messages::relayer_fund_account_id::<
>::relayer_fund_account_id(), bp_millau::AccountId,
bp_millau::AccountIdConverter,
>(),
derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( derive_account_from_rialto_id(bp_runtime::SourceAccount::Account(
get_account_id_from_seed::<sr25519::Public>("Alice"), get_account_id_from_seed::<sr25519::Public>("Alice"),
)), )),
@@ -191,12 +191,8 @@ fn testnet_genesis(
balances: BalancesConfig { balances: BalancesConfig {
balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(),
}, },
aura: AuraConfig { aura: AuraConfig { authorities: Vec::new() },
authorities: Vec::new(), grandpa: GrandpaConfig { authorities: Vec::new() },
},
grandpa: GrandpaConfig {
authorities: Vec::new(),
},
sudo: SudoConfig { key: root_key }, sudo: SudoConfig { key: root_key },
session: SessionConfig { session: SessionConfig {
keys: initial_authorities keys: initial_authorities
@@ -211,15 +207,17 @@ fn testnet_genesis(
owner: Some(get_account_id_from_seed::<sr25519::Public>("George")), owner: Some(get_account_id_from_seed::<sr25519::Public>("George")),
..Default::default() ..Default::default()
}, },
bridge_rialto_messages: BridgeRialtoMessagesConfig {
owner: Some(get_account_id_from_seed::<sr25519::Public>("RialtoMessagesOwner")),
..Default::default()
},
} }
} }
#[test] #[test]
fn derived_dave_account_is_as_expected() { fn derived_dave_account_is_as_expected() {
let dave = get_account_id_from_seed::<sr25519::Public>("Dave"); let dave = get_account_id_from_seed::<sr25519::Public>("Dave");
let derived: AccountId = derive_account_from_rialto_id(bp_runtime::SourceAccount::Account(dave)); let derived: AccountId =
assert_eq!( derive_account_from_rialto_id(bp_runtime::SourceAccount::Account(dave));
derived.to_string(), assert_eq!(derived.to_string(), "5DNW6UVnb7TN6wX5KwXtDYR3Eccecbdzuw89HqjyNfkzce6J".to_string());
"5DNW6UVnb7TN6wX5KwXtDYR3Eccecbdzuw89HqjyNfkzce6J".to_string()
);
} }
+2 -2
View File
@@ -29,10 +29,10 @@ pub struct Cli {
/// Possible subcommands of the main binary. /// Possible subcommands of the main binary.
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
pub enum Subcommand { pub enum Subcommand {
/// Key management cli utilities /// Key management CLI utilities
Key(sc_cli::KeySubcommand), Key(sc_cli::KeySubcommand),
/// Verify a signature for a message, provided on STDIN, with a given (public or secret) key. /// Verify a signature for a message, provided on `STDIN`, with a given (public or secret) key.
Verify(sc_cli::VerifyCmd), Verify(sc_cli::VerifyCmd),
/// Generate a seed that provides a vanity address. /// Generate a seed that provides a vanity address.
+26 -41
View File
@@ -14,9 +14,11 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::cli::{Cli, Subcommand}; use crate::{
use crate::service; cli::{Cli, Subcommand},
use crate::service::new_partial; service,
service::new_partial,
};
use millau_runtime::{Block, RuntimeApi}; use millau_runtime::{Block, RuntimeApi};
use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli};
use sc_service::PartialComponents; use sc_service::PartialComponents;
@@ -75,19 +77,18 @@ pub fn run() -> sc_cli::Result<()> {
)); ));
match &cli.subcommand { match &cli.subcommand {
Some(Subcommand::Benchmark(cmd)) => { Some(Subcommand::Benchmark(cmd)) =>
if cfg!(feature = "runtime-benchmarks") { if cfg!(feature = "runtime-benchmarks") {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run::<Block, service::Executor>(config)) runner.sync_run(|config| cmd.run::<Block, service::ExecutorDispatch>(config))
} else { } else {
println!( println!(
"Benchmarking wasn't enabled when building the node. \ "Benchmarking wasn't enabled when building the node. \
You can enable it with `--features runtime-benchmarks`." You can enable it with `--features runtime-benchmarks`."
); );
Ok(()) Ok(())
} },
}
Some(Subcommand::Key(cmd)) => cmd.run(&cli), Some(Subcommand::Key(cmd)) => cmd.run(&cli),
Some(Subcommand::Sign(cmd)) => cmd.run(), Some(Subcommand::Sign(cmd)) => cmd.run(),
Some(Subcommand::Verify(cmd)) => cmd.run(), Some(Subcommand::Verify(cmd)) => cmd.run(),
@@ -95,69 +96,53 @@ pub fn run() -> sc_cli::Result<()> {
Some(Subcommand::BuildSpec(cmd)) => { Some(Subcommand::BuildSpec(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
} },
Some(Subcommand::CheckBlock(cmd)) => { Some(Subcommand::CheckBlock(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.async_run(|config| { runner.async_run(|config| {
let PartialComponents { let PartialComponents { client, task_manager, import_queue, .. } =
client, new_partial(&config)?;
task_manager,
import_queue,
..
} = new_partial(&config)?;
Ok((cmd.run(client, import_queue), task_manager)) Ok((cmd.run(client, import_queue), task_manager))
}) })
} },
Some(Subcommand::ExportBlocks(cmd)) => { Some(Subcommand::ExportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.async_run(|config| { runner.async_run(|config| {
let PartialComponents { let PartialComponents { client, task_manager, .. } = new_partial(&config)?;
client, task_manager, ..
} = new_partial(&config)?;
Ok((cmd.run(client, config.database), task_manager)) Ok((cmd.run(client, config.database), task_manager))
}) })
} },
Some(Subcommand::ExportState(cmd)) => { Some(Subcommand::ExportState(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.async_run(|config| { runner.async_run(|config| {
let PartialComponents { let PartialComponents { client, task_manager, .. } = new_partial(&config)?;
client, task_manager, ..
} = new_partial(&config)?;
Ok((cmd.run(client, config.chain_spec), task_manager)) Ok((cmd.run(client, config.chain_spec), task_manager))
}) })
} },
Some(Subcommand::ImportBlocks(cmd)) => { Some(Subcommand::ImportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.async_run(|config| { runner.async_run(|config| {
let PartialComponents { let PartialComponents { client, task_manager, import_queue, .. } =
client, new_partial(&config)?;
task_manager,
import_queue,
..
} = new_partial(&config)?;
Ok((cmd.run(client, import_queue), task_manager)) Ok((cmd.run(client, import_queue), task_manager))
}) })
} },
Some(Subcommand::PurgeChain(cmd)) => { Some(Subcommand::PurgeChain(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.database)) runner.sync_run(|config| cmd.run(config.database))
} },
Some(Subcommand::Revert(cmd)) => { Some(Subcommand::Revert(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.async_run(|config| { runner.async_run(|config| {
let PartialComponents { let PartialComponents { client, task_manager, backend, .. } = new_partial(&config)?;
client,
task_manager,
backend,
..
} = new_partial(&config)?;
Ok((cmd.run(client, backend), task_manager)) Ok((cmd.run(client, backend), task_manager))
}) })
} },
Some(Subcommand::Inspect(cmd)) => { Some(Subcommand::Inspect(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run::<Block, RuntimeApi, service::Executor>(config)) runner
} .sync_run(|config| cmd.run::<Block, RuntimeApi, service::ExecutorDispatch>(config))
},
None => { None => {
let runner = cli.create_runner(&cli.run)?; let runner = cli.create_runner(&cli.run)?;
runner.run_node_until_exit(|config| async move { runner.run_node_until_exit(|config| async move {
@@ -167,6 +152,6 @@ pub fn run() -> sc_cli::Result<()> {
} }
.map_err(sc_cli::Error::Service) .map_err(sc_cli::Error::Service)
}) })
} },
} }
} }
+91 -41
View File
@@ -21,8 +21,8 @@
// ===================================================================================== // =====================================================================================
// UPDATE GUIDE: // UPDATE GUIDE:
// 1) replace everything with node-template/src/service.rs contents (found in main Substrate repo); // 1) replace everything with node-template/src/service.rs contents (found in main Substrate repo);
// 2) the only thing to keep from old code, is `rpc_extensions_builder` - we use our own custom RPCs; // 2) the only thing to keep from old code, is `rpc_extensions_builder` - we use our own custom
// 3) fix compilation errors; // RPCs; 3) fix compilation errors;
// 4) test :) // 4) test :)
// ===================================================================================== // =====================================================================================
// ===================================================================================== // =====================================================================================
@@ -40,6 +40,8 @@ use sp_consensus::SlotData;
use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
type Executor = NativeElseWasmExecutor<ExecutorDispatch>;
// Our native executor instance. // Our native executor instance.
pub struct ExecutorDispatch; pub struct ExecutorDispatch;
@@ -55,7 +57,8 @@ impl sc_executor::NativeExecutionDispatch for ExecutorDispatch {
} }
} }
type FullClient = sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>; type FullClient =
sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;
type FullBackend = sc_service::TFullBackend<Block>; type FullBackend = sc_service::TFullBackend<Block>;
type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>; type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
@@ -70,7 +73,12 @@ pub fn new_partial(
sc_consensus::DefaultImportQueue<Block, FullClient>, sc_consensus::DefaultImportQueue<Block, FullClient>,
sc_transaction_pool::FullPool<Block, FullClient>, sc_transaction_pool::FullPool<Block, FullClient>,
( (
sc_finality_grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, FullSelectChain>, sc_finality_grandpa::GrandpaBlockImport<
FullBackend,
Block,
FullClient,
FullSelectChain,
>,
sc_finality_grandpa::LinkHalf<Block, FullClient, FullSelectChain>, sc_finality_grandpa::LinkHalf<Block, FullClient, FullSelectChain>,
Option<Telemetry>, Option<Telemetry>,
), ),
@@ -78,7 +86,7 @@ pub fn new_partial(
ServiceError, ServiceError,
> { > {
if config.keystore_remote.is_some() { if config.keystore_remote.is_some() {
return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())); return Err(ServiceError::Other("Remote Keystores are not supported.".to_string()))
} }
let telemetry = config let telemetry = config
@@ -92,9 +100,17 @@ pub fn new_partial(
}) })
.transpose()?; .transpose()?;
let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::<Block, RuntimeApi, Executor>( let executor = NativeElseWasmExecutor::<ExecutorDispatch>::new(
config.wasm_method,
config.default_heap_pages,
config.max_runtime_instances,
);
let (client, backend, keystore_container, task_manager) =
sc_service::new_full_parts::<Block, RuntimeApi, Executor>(
config, config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
executor,
)?; )?;
let client = Arc::new(client); let client = Arc::new(client);
@@ -122,14 +138,16 @@ pub fn new_partial(
let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration();
let import_queue = sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _, _>(ImportQueueParams { let import_queue =
sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _, _>(ImportQueueParams {
block_import: grandpa_block_import.clone(), block_import: grandpa_block_import.clone(),
justification_import: Some(Box::new(grandpa_block_import.clone())), justification_import: Some(Box::new(grandpa_block_import.clone())),
client: client.clone(), client: client.clone(),
create_inherent_data_providers: move |_, ()| async move { create_inherent_data_providers: move |_, ()| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( let slot =
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp, *timestamp,
slot_duration, slot_duration,
); );
@@ -137,7 +155,9 @@ pub fn new_partial(
Ok((timestamp, slot)) Ok((timestamp, slot))
}, },
spawner: &task_manager.spawn_essential_handle(), spawner: &task_manager.spawn_essential_handle(),
can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(
client.executor().clone(),
),
registry: config.prometheus_registry(), registry: config.prometheus_registry(),
check_for_equivocation: Default::default(), check_for_equivocation: Default::default(),
telemetry: telemetry.as_ref().map(|x| x.handle()), telemetry: telemetry.as_ref().map(|x| x.handle()),
@@ -178,21 +198,23 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
if let Some(url) = &config.keystore_remote { if let Some(url) = &config.keystore_remote {
match remote_keystore(url) { match remote_keystore(url) {
Ok(k) => keystore_container.set_remote_keystore(k), Ok(k) => keystore_container.set_remote_keystore(k),
Err(e) => { Err(e) =>
return Err(ServiceError::Other(format!( return Err(ServiceError::Other(format!(
"Error hooking up remote keystore for {}: {}", "Error hooking up remote keystore for {}: {}",
url, e url, e
))) ))),
}
}; };
} }
config config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config());
.network let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new(
.extra_sets backend.clone(),
.push(sc_finality_grandpa::grandpa_peers_set_config()); grandpa_link.shared_authority_set().clone(),
vec![],
));
let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { let (network, system_rpc_tx, network_starter) =
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config, config: &config,
client: client.clone(), client: client.clone(),
transaction_pool: transaction_pool.clone(), transaction_pool: transaction_pool.clone(),
@@ -200,10 +222,16 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
import_queue, import_queue,
on_demand: None, on_demand: None,
block_announce_validator_builder: None, block_announce_validator_builder: None,
warp_sync: Some(warp_sync),
})?; })?;
if config.offchain_worker.enabled { if config.offchain_worker.enabled {
sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); sc_service::build_offchain_workers(
&config,
task_manager.spawn_handle(),
client.clone(),
network.clone(),
);
} }
let role = config.role.clone(); let role = config.role.clone();
@@ -230,8 +258,10 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
let shared_authority_set = grandpa_link.shared_authority_set().clone(); let shared_authority_set = grandpa_link.shared_authority_set().clone();
let shared_voter_state = shared_voter_state.clone(); let shared_voter_state = shared_voter_state.clone();
let finality_proof_provider = let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(
GrandpaFinalityProofProvider::new_for_service(backend, Some(shared_authority_set.clone())); backend,
Some(shared_authority_set.clone()),
);
Box::new(move |_, subscription_executor| { Box::new(move |_, subscription_executor| {
let mut io = jsonrpc_core::IoHandler::default(); let mut io = jsonrpc_core::IoHandler::default();
@@ -250,7 +280,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
subscription_executor, subscription_executor,
finality_proof_provider.clone(), finality_proof_provider.clone(),
))); )));
io Ok(io)
}) })
}; };
@@ -278,12 +308,14 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
telemetry.as_ref().map(|x| x.handle()), telemetry.as_ref().map(|x| x.handle()),
); );
let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); let can_author_with =
sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone());
let slot_duration = sc_consensus_aura::slot_duration(&*client)?; let slot_duration = sc_consensus_aura::slot_duration(&*client)?;
let raw_slot_duration = slot_duration.slot_duration(); let raw_slot_duration = slot_duration.slot_duration();
let aura = sc_consensus_aura::start_aura::<AuraPair, _, _, _, _, _, _, _, _, _, _, _>(StartAuraParams { let aura = sc_consensus_aura::start_aura::<AuraPair, _, _, _, _, _, _, _, _, _, _, _>(
StartAuraParams {
slot_duration, slot_duration,
client, client,
select_chain, select_chain,
@@ -308,7 +340,8 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32),
max_block_proposal_slot_portion: None, max_block_proposal_slot_portion: None,
telemetry: telemetry.as_ref().map(|x| x.handle()), telemetry: telemetry.as_ref().map(|x| x.handle()),
})?; },
)?;
// the AURA authoring task is considered essential, i.e. if it // the AURA authoring task is considered essential, i.e. if it
// fails we take down the service with it. // fails we take down the service with it.
@@ -317,11 +350,8 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
// if the node isn't actively participating in consensus then it doesn't // if the node isn't actively participating in consensus then it doesn't
// need a keystore, regardless of which protocol we use below. // need a keystore, regardless of which protocol we use below.
let keystore = if role.is_authority() { let keystore =
Some(keystore_container.sync_keystore()) if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None };
} else {
None
};
let grandpa_config = sc_finality_grandpa::Config { let grandpa_config = sc_finality_grandpa::Config {
// FIXME #1578 make this available through chainspec // FIXME #1578 make this available through chainspec
@@ -353,9 +383,10 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
// the GRANDPA voter task is considered infallible, i.e. // the GRANDPA voter task is considered infallible, i.e.
// if it fails we take down the service with it. // if it fails we take down the service with it.
task_manager task_manager.spawn_essential_handle().spawn_blocking(
.spawn_essential_handle() "grandpa-voter",
.spawn_blocking("grandpa-voter", sc_finality_grandpa::run_grandpa_voter(grandpa_config)?); sc_finality_grandpa::run_grandpa_voter(grandpa_config)?,
);
} }
network_starter.start_network(); network_starter.start_network();
@@ -375,10 +406,17 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
}) })
.transpose()?; .transpose()?;
let executor = NativeElseWasmExecutor::<ExecutorDispatch>::new(
config.wasm_method,
config.default_heap_pages,
config.max_runtime_instances,
);
let (client, backend, keystore_container, mut task_manager, on_demand) = let (client, backend, keystore_container, mut task_manager, on_demand) =
sc_service::new_light_parts::<Block, RuntimeApi, Executor>( sc_service::new_light_parts::<Block, RuntimeApi, Executor>(
&config, &config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
executor,
)?; )?;
let mut telemetry = telemetry.map(|(worker, telemetry)| { let mut telemetry = telemetry.map(|(worker, telemetry)| {
@@ -386,10 +424,7 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
telemetry telemetry
}); });
config config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config());
.network
.extra_sets
.push(sc_finality_grandpa::grandpa_peers_set_config());
let select_chain = sc_consensus::LongestChain::new(backend.clone()); let select_chain = sc_consensus::LongestChain::new(backend.clone());
@@ -410,14 +445,16 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration();
let import_queue = sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _, _>(ImportQueueParams { let import_queue =
sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _, _>(ImportQueueParams {
block_import: grandpa_block_import.clone(), block_import: grandpa_block_import.clone(),
justification_import: Some(Box::new(grandpa_block_import)), justification_import: Some(Box::new(grandpa_block_import)),
client: client.clone(), client: client.clone(),
create_inherent_data_providers: move |_, ()| async move { create_inherent_data_providers: move |_, ()| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( let slot =
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp, *timestamp,
slot_duration, slot_duration,
); );
@@ -431,7 +468,14 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
telemetry: telemetry.as_ref().map(|x| x.handle()), telemetry: telemetry.as_ref().map(|x| x.handle()),
})?; })?;
let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new(
backend.clone(),
grandpa_link.shared_authority_set().clone(),
vec![],
));
let (network, system_rpc_tx, network_starter) =
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config, config: &config,
client: client.clone(), client: client.clone(),
transaction_pool: transaction_pool.clone(), transaction_pool: transaction_pool.clone(),
@@ -439,10 +483,16 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
import_queue, import_queue,
on_demand: Some(on_demand.clone()), on_demand: Some(on_demand.clone()),
block_announce_validator_builder: None, block_announce_validator_builder: None,
warp_sync: Some(warp_sync),
})?; })?;
if config.offchain_worker.enabled { if config.offchain_worker.enabled {
sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); sc_service::build_offchain_workers(
&config,
task_manager.spawn_handle(),
client.clone(),
network.clone(),
);
} }
let enable_grandpa = !config.disable_grandpa; let enable_grandpa = !config.disable_grandpa;
@@ -470,7 +520,7 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
transaction_pool, transaction_pool,
task_manager: &mut task_manager, task_manager: &mut task_manager,
on_demand: Some(on_demand), on_demand: Some(on_demand),
rpc_extensions_builder: Box::new(|_, _| ()), rpc_extensions_builder: Box::new(|_, _| Ok(())),
config, config,
client, client,
keystore: keystore_container.sync_keystore(), keystore: keystore_container.sync_keystore(),
+13 -5
View File
@@ -8,9 +8,10 @@ repository = "https://github.com/paritytech/parity-bridges-common/"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0" license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies] [dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
hex-literal = "0.3" hex-literal = "0.3"
serde = { version = "1.0.124", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
serde = { version = "1.0", optional = true, features = ["derive"] }
# Bridge dependencies # Bridge dependencies
@@ -24,10 +25,12 @@ bridge-runtime-common = { path = "../../runtime-common", default-features = fals
pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false } pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false }
pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false }
pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false }
pallet-bridge-token-swap = { path = "../../../modules/token-swap", default-features = false }
pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false }
# Substrate Dependencies # Substrate Dependencies
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } 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-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 } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
@@ -78,6 +81,7 @@ std = [
"pallet-bridge-dispatch/std", "pallet-bridge-dispatch/std",
"pallet-bridge-grandpa/std", "pallet-bridge-grandpa/std",
"pallet-bridge-messages/std", "pallet-bridge-messages/std",
"pallet-bridge-token-swap/std",
"pallet-grandpa/std", "pallet-grandpa/std",
"pallet-randomness-collective-flip/std", "pallet-randomness-collective-flip/std",
"pallet-session/std", "pallet-session/std",
@@ -86,6 +90,7 @@ std = [
"pallet-timestamp/std", "pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std", "pallet-transaction-payment/std",
"scale-info/std",
"serde", "serde",
"sp-api/std", "sp-api/std",
"sp-block-builder/std", "sp-block-builder/std",
@@ -101,6 +106,9 @@ std = [
"sp-trie/std", "sp-trie/std",
"sp-version/std", "sp-version/std",
] ]
# TODO: https://github.com/paritytech/parity-bridges-common/issues/390 runtime-benchmarks = [
# I've left the feature flag here to test our CI configuration "frame-benchmarking",
runtime-benchmarks = [] "frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-bridge-token-swap/runtime-benchmarks",
]
+172 -49
View File
@@ -34,18 +34,21 @@ pub mod rialto_messages;
use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}; use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge};
use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_delivery_fee, MessageBridge}; use bridge_runtime_common::messages::{
use codec::Decode; source::estimate_message_dispatch_and_delivery_fee, MessageBridge,
use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; };
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use pallet_grandpa::{
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
};
use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo};
use sp_api::impl_runtime_apis; use sp_api::impl_runtime_apis;
use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys};
use sp_runtime::{ use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys, create_runtime_str, generic, impl_opaque_keys,
traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys},
transaction_validity::{TransactionSource, TransactionValidity}, transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, MultiSignature, MultiSigner, ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill,
}; };
use sp_std::prelude::*; use sp_std::prelude::*;
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -62,8 +65,7 @@ pub use frame_support::{
pub use frame_system::Call as SystemCall; pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall; pub use pallet_balances::Call as BalancesCall;
pub use pallet_bridge_grandpa::Call as BridgeGrandpaRialtoCall; pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall;
pub use pallet_bridge_grandpa::Call as BridgeGrandpaWestendCall;
pub use pallet_bridge_messages::Call as MessagesCall; pub use pallet_bridge_messages::Call as MessagesCall;
pub use pallet_sudo::Call as SudoCall; pub use pallet_sudo::Call as SudoCall;
pub use pallet_timestamp::Call as TimestampCall; pub use pallet_timestamp::Call as TimestampCall;
@@ -90,7 +92,7 @@ pub type AccountIndex = u32;
pub type Balance = bp_millau::Balance; pub type Balance = bp_millau::Balance;
/// Index of a transaction in the chain. /// Index of a transaction in the chain.
pub type Index = u32; pub type Index = bp_millau::Index;
/// A hash of some data used by the chain. /// A hash of some data used by the chain.
pub type Hash = bp_millau::Hash; pub type Hash = bp_millau::Hash;
@@ -139,10 +141,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
/// The version information used to identify this runtime when compiled natively. /// The version information used to identify this runtime when compiled natively.
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub fn native_version() -> NativeVersion { pub fn native_version() -> NativeVersion {
NativeVersion { NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
runtime_version: VERSION,
can_author_with: Default::default(),
}
} }
parameter_types! { parameter_types! {
@@ -214,10 +213,11 @@ parameter_types! {
impl pallet_aura::Config for Runtime { impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId; type AuthorityId = AuraId;
type MaxAuthorities = MaxAuthorities; type MaxAuthorities = MaxAuthorities;
type DisabledValidators = ();
} }
impl pallet_bridge_dispatch::Config for Runtime { impl pallet_bridge_dispatch::Config for Runtime {
type Event = Event; type Event = Event;
type MessageId = (bp_messages::LaneId, bp_messages::MessageNonce); type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce);
type Call = Call; type Call = Call;
type CallFilter = frame_support::traits::Everything; type CallFilter = frame_support::traits::Everything;
type EncodedCall = crate::rialto_messages::FromRialtoEncodedCall; type EncodedCall = crate::rialto_messages::FromRialtoEncodedCall;
@@ -231,12 +231,16 @@ impl pallet_grandpa::Config for Runtime {
type Event = Event; type Event = Event;
type Call = Call; type Call = Call;
type KeyOwnerProofSystem = (); type KeyOwnerProofSystem = ();
type KeyOwnerProof = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof; type KeyOwnerProof =
type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;
<Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::IdentificationTuple; type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(
KeyTypeId,
GrandpaId,
)>>::IdentificationTuple;
type HandleEquivocation = (); type HandleEquivocation = ();
// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
type WeightInfo = (); type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
} }
parameter_types! { parameter_types! {
@@ -244,7 +248,7 @@ parameter_types! {
} }
impl pallet_timestamp::Config for Runtime { impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the Unix epoch. /// A timestamp: milliseconds since the UNIX epoch.
type Moment = u64; type Moment = u64;
type OnTimestampSet = Aura; type OnTimestampSet = Aura;
type MinimumPeriod = MinimumPeriod; type MinimumPeriod = MinimumPeriod;
@@ -278,13 +282,25 @@ impl pallet_balances::Config for Runtime {
parameter_types! { parameter_types! {
pub const TransactionBaseFee: Balance = 0; pub const TransactionBaseFee: Balance = 0;
pub const TransactionByteFee: Balance = 1; pub const TransactionByteFee: Balance = 1;
pub const OperationalFeeMultiplier: u8 = 5;
// values for following parameters are copied from polkadot repo, but it is fine
// not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains
pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25);
pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000);
pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128);
} }
impl pallet_transaction_payment::Config for Runtime { impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, ()>; type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, ()>;
type TransactionByteFee = TransactionByteFee; type TransactionByteFee = TransactionByteFee;
type WeightToFee = IdentityFee<Balance>; type OperationalFeeMultiplier = OperationalFeeMultiplier;
type FeeMultiplierUpdate = (); type WeightToFee = bp_millau::WeightToFee;
type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment<
Runtime,
TargetBlockFullness,
AdjustmentVariable,
MinimumMultiplier,
>;
} }
impl pallet_sudo::Config for Runtime { impl pallet_sudo::Config for Runtime {
@@ -357,10 +373,11 @@ parameter_types! {
pub const GetDeliveryConfirmationTransactionFee: Balance = pub const GetDeliveryConfirmationTransactionFee: Balance =
bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _;
pub const RootAccountForPayments: Option<AccountId> = None; pub const RootAccountForPayments: Option<AccountId> = None;
pub const RialtoChainId: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID;
} }
/// Instance of the messages pallet used to relay messages to/from Rialto chain. /// Instance of the messages pallet used to relay messages to/from Rialto chain.
pub type WithRialtoMessagesInstance = pallet_bridge_messages::DefaultInstance; pub type WithRialtoMessagesInstance = ();
impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime { impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime {
type Event = Event; type Event = Event;
@@ -382,16 +399,45 @@ impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime {
type TargetHeaderChain = crate::rialto_messages::Rialto; type TargetHeaderChain = crate::rialto_messages::Rialto;
type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier;
type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< type MessageDeliveryAndDispatchPayment =
pallet_bridge_messages::instant_payments::InstantCurrencyPayments<
Runtime, Runtime,
(),
pallet_balances::Pallet<Runtime>, pallet_balances::Pallet<Runtime>,
GetDeliveryConfirmationTransactionFee, GetDeliveryConfirmationTransactionFee,
RootAccountForPayments, RootAccountForPayments,
>; >;
type OnDeliveryConfirmed = (); type OnMessageAccepted = ();
type OnDeliveryConfirmed =
pallet_bridge_token_swap::Pallet<Runtime, WithRialtoTokenSwapInstance>;
type SourceHeaderChain = crate::rialto_messages::Rialto; type SourceHeaderChain = crate::rialto_messages::Rialto;
type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch;
type BridgedChainId = RialtoChainId;
}
parameter_types! {
pub const TokenSwapMessagesLane: bp_messages::LaneId = *b"swap";
}
/// Instance of the with-Rialto token swap pallet.
pub type WithRialtoTokenSwapInstance = ();
impl pallet_bridge_token_swap::Config<WithRialtoTokenSwapInstance> for Runtime {
type Event = Event;
type WeightInfo = ();
type BridgedChainId = RialtoChainId;
type OutboundMessageLaneId = TokenSwapMessagesLane;
#[cfg(not(feature = "runtime-benchmarks"))]
type MessagesBridge = pallet_bridge_messages::Pallet<Runtime, WithRialtoMessagesInstance>;
#[cfg(feature = "runtime-benchmarks")]
type MessagesBridge = bp_messages::source_chain::NoopMessagesBridge;
type ThisCurrency = pallet_balances::Pallet<Runtime>;
type FromSwapToThisAccountIdConverter = bp_rialto::AccountIdConverter;
type BridgedChain = bp_rialto::Rialto;
type FromBridgedToThisAccountIdConverter = bp_millau::AccountIdConverter;
} }
construct_runtime!( construct_runtime!(
@@ -400,20 +446,30 @@ construct_runtime!(
NodeBlock = opaque::Block, NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic UncheckedExtrinsic = UncheckedExtrinsic
{ {
BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>},
BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event<T>},
BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
BridgeWestendGrandpa: pallet_bridge_grandpa::<Instance1>::{Pallet, Call, Config<T>, Storage},
System: frame_system::{Pallet, Call, Config, Storage, Event<T>}, System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
// Must be before session.
Aura: pallet_aura::{Pallet, Config<T>}, Aura: pallet_aura::{Pallet, Config<T>},
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>}, Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, TransactionPayment: pallet_transaction_payment::{Pallet, Storage},
Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>},
// Consensus support.
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>}, Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>},
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event},
ShiftSessionManager: pallet_shift_session_manager::{Pallet}, ShiftSessionManager: pallet_shift_session_manager::{Pallet},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},
// Rialto bridge modules.
BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event<T>},
BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>, Config<T>},
BridgeRialtoTokenSwap: pallet_bridge_token_swap::{Pallet, Call, Storage, Event<T>},
// Westend bridge modules.
BridgeWestendGrandpa: pallet_bridge_grandpa::<Instance1>::{Pallet, Call, Config<T>, Storage},
} }
); );
@@ -449,7 +505,7 @@ pub type Executive = frame_executive::Executive<
Block, Block,
frame_system::ChainContext<Runtime>, frame_system::ChainContext<Runtime>,
Runtime, Runtime,
AllPalletsWithSystem, AllPallets,
>; >;
impl_runtime_apis! { impl_runtime_apis! {
@@ -522,7 +578,7 @@ impl_runtime_apis! {
} }
fn authorities() -> Vec<AuraId> { fn authorities() -> Vec<AuraId> {
Aura::authorities() Aura::authorities().to_vec()
} }
} }
@@ -551,6 +607,10 @@ impl_runtime_apis! {
} }
impl fg_primitives::GrandpaApi<Block> for Runtime { impl fg_primitives::GrandpaApi<Block> for Runtime {
fn current_set_id() -> fg_primitives::SetId {
Grandpa::current_set_id()
}
fn grandpa_authorities() -> GrandpaAuthorityList { fn grandpa_authorities() -> GrandpaAuthorityList {
Grandpa::grandpa_authorities() Grandpa::grandpa_authorities()
} }
@@ -619,20 +679,11 @@ impl_runtime_apis! {
begin: bp_messages::MessageNonce, begin: bp_messages::MessageNonce,
end: bp_messages::MessageNonce, end: bp_messages::MessageNonce,
) -> Vec<bp_messages::MessageDetails<Balance>> { ) -> Vec<bp_messages::MessageDetails<Balance>> {
(begin..=end).filter_map(|nonce| { bridge_runtime_common::messages_api::outbound_message_details::<
let message_data = BridgeRialtoMessages::outbound_message_data(lane, nonce)?; Runtime,
let decoded_payload = rialto_messages::ToRialtoMessagePayload::decode( WithRialtoMessagesInstance,
&mut &message_data.payload[..] WithRialtoMessageBridge,
).ok()?; >(lane, begin, end)
Some(bp_messages::MessageDetails {
nonce,
dispatch_weight: decoded_payload.weight,
size: message_data.payload.len() as _,
delivery_and_dispatch_fee: message_data.fee,
dispatch_fee_payment: decoded_payload.dispatch_fee_payment,
})
})
.collect()
} }
fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce {
@@ -657,6 +708,67 @@ impl_runtime_apis! {
BridgeRialtoMessages::inbound_unrewarded_relayers_state(lane) BridgeRialtoMessages::inbound_unrewarded_relayers_state(lane)
} }
} }
#[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::{list_benchmark, Benchmarking, BenchmarkList};
use frame_support::traits::StorageInfoTrait;
let mut list = Vec::<BenchmarkList>::new();
list_benchmark!(list, extra, pallet_bridge_token_swap, BridgeRialtoTokenSwap);
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, add_benchmark};
let whitelist: Vec<TrackedStorageKey> = vec![
// Block Number
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").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(),
// Caller 0 Account
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da946c154ffd9992e395af90b5b13cc6f295c77033fce8a9045824a6690bbf99c6db269502f0a8d1d2a008542d5690a0749").to_vec().into(),
];
let mut batches = Vec::<BenchmarkBatch>::new();
let params = (&config, &whitelist);
use pallet_bridge_token_swap::benchmarking::Config as TokenSwapConfig;
impl TokenSwapConfig<WithRialtoTokenSwapInstance> for Runtime {
fn initialize_environment() {
let relayers_fund_account = pallet_bridge_messages::relayer_fund_account_id::<
bp_millau::AccountId,
bp_millau::AccountIdConverter,
>();
pallet_balances::Pallet::<Runtime>::make_free_balance_be(
&relayers_fund_account,
Balance::MAX / 100,
);
}
}
add_benchmark!(params, batches, pallet_bridge_token_swap, BridgeRialtoTokenSwap);
if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
Ok(batches)
}
}
} }
/// Rialto account ownership digest from Millau. /// Rialto account ownership digest from Millau.
@@ -698,6 +810,7 @@ mod tests {
bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT,
bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT, bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT,
DbWeight::get(),
); );
let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add(
@@ -707,10 +820,13 @@ mod tests {
bp_millau::max_extrinsic_size(), bp_millau::max_extrinsic_size(),
bp_millau::max_extrinsic_weight(), bp_millau::max_extrinsic_weight(),
max_incoming_message_proof_size, max_incoming_message_proof_size,
messages::target::maximal_incoming_message_dispatch_weight(bp_millau::max_extrinsic_weight()), messages::target::maximal_incoming_message_dispatch_weight(
bp_millau::max_extrinsic_weight(),
),
); );
let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( let max_incoming_inbound_lane_data_proof_size =
bp_messages::InboundLaneData::<()>::encoded_size_hint(
bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _,
bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _,
@@ -722,6 +838,13 @@ mod tests {
max_incoming_inbound_lane_data_proof_size, max_incoming_inbound_lane_data_proof_size,
bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
DbWeight::get(),
); );
} }
#[test]
fn call_size() {
const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests
assert!(core::mem::size_of::<Call>() <= MAX_CALL_SIZE);
}
} }
@@ -31,25 +31,34 @@ use frame_support::{
weights::{DispatchClass, Weight}, weights::{DispatchClass, Weight},
RuntimeDebug, RuntimeDebug,
}; };
use sp_runtime::{traits::Zero, FixedPointNumber, FixedU128}; use scale_info::TypeInfo;
use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128};
use sp_std::{convert::TryFrom, ops::RangeInclusive}; use sp_std::{convert::TryFrom, ops::RangeInclusive};
/// Initial value of `RialtoToMillauConversionRate` parameter. /// Initial value of `RialtoToMillauConversionRate` parameter.
pub const INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV); pub const INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE: FixedU128 =
FixedU128::from_inner(FixedU128::DIV);
/// Initial value of `RialtoFeeMultiplier` parameter.
pub const INITIAL_RIALTO_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV);
parameter_types! { parameter_types! {
/// Rialto to Millau conversion rate. Initially we treat both tokens as equal. /// Rialto to Millau conversion rate. Initially we treat both tokens as equal.
pub storage RialtoToMillauConversionRate: FixedU128 = INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE; pub storage RialtoToMillauConversionRate: FixedU128 = INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE;
/// Fee multiplier value at Rialto chain.
pub storage RialtoFeeMultiplier: FixedU128 = INITIAL_RIALTO_FEE_MULTIPLIER;
} }
/// Message payload for Millau -> Rialto messages. /// Message payload for Millau -> Rialto messages.
pub type ToRialtoMessagePayload = messages::source::FromThisChainMessagePayload<WithRialtoMessageBridge>; pub type ToRialtoMessagePayload =
messages::source::FromThisChainMessagePayload<WithRialtoMessageBridge>;
/// Message verifier for Millau -> Rialto messages. /// Message verifier for Millau -> Rialto messages.
pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifier<WithRialtoMessageBridge>; pub type ToRialtoMessageVerifier =
messages::source::FromThisChainMessageVerifier<WithRialtoMessageBridge>;
/// Message payload for Rialto -> Millau messages. /// Message payload for Rialto -> Millau messages.
pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload<WithRialtoMessageBridge>; pub type FromRialtoMessagePayload =
messages::target::FromBridgedChainMessagePayload<WithRialtoMessageBridge>;
/// Encoded Millau Call as it comes from Rialto. /// Encoded Millau Call as it comes from Rialto.
pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessageCall<crate::Call>; pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessageCall<crate::Call>;
@@ -58,14 +67,15 @@ pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessag
type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_rialto::Hash>; type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_rialto::Hash>;
/// Messages delivery proof for Millau -> Rialto messages. /// Messages delivery proof for Millau -> Rialto messages.
type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof<bp_rialto::Hash>; type ToRialtoMessagesDeliveryProof =
messages::source::FromBridgedChainMessagesDeliveryProof<bp_rialto::Hash>;
/// Call-dispatch based message dispatch for Rialto -> Millau messages. /// Call-dispatch based message dispatch for Rialto -> Millau messages.
pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch< pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch<
WithRialtoMessageBridge, WithRialtoMessageBridge,
crate::Runtime, crate::Runtime,
pallet_balances::Pallet<Runtime>, pallet_balances::Pallet<Runtime>,
pallet_bridge_dispatch::DefaultInstance, (),
>; >;
/// Millau <-> Rialto message bridge. /// Millau <-> Rialto message bridge.
@@ -76,13 +86,15 @@ impl MessageBridge for WithRialtoMessageBridge {
const RELAYER_FEE_PERCENT: u32 = 10; const RELAYER_FEE_PERCENT: u32 = 10;
const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID;
const BRIDGED_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = RIALTO_CHAIN_ID;
const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME;
type ThisChain = Millau; type ThisChain = Millau;
type BridgedChain = Rialto; type BridgedChain = Rialto;
type BridgedMessagesInstance = crate::WithRialtoMessagesInstance;
fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance { fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance {
bp_millau::Balance::try_from(RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance)) bp_millau::Balance::try_from(
RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance),
)
.unwrap_or(bp_millau::Balance::MAX) .unwrap_or(bp_millau::Balance::MAX)
} }
} }
@@ -104,7 +116,9 @@ impl messages::ThisChainWithMessages for Millau {
type Call = crate::Call; type Call = crate::Call;
fn is_outbound_lane_enabled(lane: &LaneId) -> bool { fn is_outbound_lane_enabled(lane: &LaneId) -> bool {
*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] *lane == [0, 0, 0, 0] ||
*lane == [0, 0, 0, 1] ||
*lane == crate::TokenSwapMessagesLane::get()
} }
fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce {
@@ -128,11 +142,15 @@ impl messages::ThisChainWithMessages for Millau {
} }
fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_millau::Balance { fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_millau::Balance {
// `transaction` may represent transaction from the future, when multiplier value will
// be larger, so let's use slightly increased value
let multiplier = FixedU128::saturating_from_rational(110, 100)
.saturating_mul(pallet_transaction_payment::Pallet::<Runtime>::next_fee_multiplier());
// in our testnets, both per-byte fee and weight-to-fee are 1:1 // in our testnets, both per-byte fee and weight-to-fee are 1:1
messages::transaction_payment( messages::transaction_payment(
bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic,
1, 1,
FixedU128::zero(), multiplier,
|weight| weight as _, |weight| weight as _,
transaction, transaction,
) )
@@ -159,12 +177,15 @@ impl messages::BridgedChainWithMessages for Rialto {
fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive<Weight> { fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive<Weight> {
// we don't want to relay too large messages + keep reserve for future upgrades // we don't want to relay too large messages + keep reserve for future upgrades
let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(
bp_rialto::max_extrinsic_weight(),
);
// we're charging for payload bytes in `WithRialtoMessageBridge::transaction_payment` function // we're charging for payload bytes in `WithRialtoMessageBridge::transaction_payment`
// function
// //
// this bridge may be used to deliver all kind of messages, so we're not making any assumptions about // this bridge may be used to deliver all kind of messages, so we're not making any
// minimal dispatch weight here // assumptions about minimal dispatch weight here
0..=upper_limit 0..=upper_limit
} }
@@ -195,11 +216,14 @@ impl messages::BridgedChainWithMessages for Rialto {
} }
fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_rialto::Balance { fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_rialto::Balance {
// we don't have a direct access to the value of multiplier at Rialto chain
// => it is a messages module parameter
let multiplier = RialtoFeeMultiplier::get();
// in our testnets, both per-byte fee and weight-to-fee are 1:1 // in our testnets, both per-byte fee and weight-to-fee are 1:1
messages::transaction_payment( messages::transaction_payment(
bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic,
1, 1,
FixedU128::zero(), multiplier,
|weight| weight as _, |weight| weight as _,
transaction, transaction,
) )
@@ -221,9 +245,11 @@ impl TargetHeaderChain<ToRialtoMessagePayload, bp_rialto::AccountId> for Rialto
fn verify_messages_delivery_proof( fn verify_messages_delivery_proof(
proof: Self::MessagesDeliveryProof, proof: Self::MessagesDeliveryProof,
) -> Result<(LaneId, InboundLaneData<bp_millau::AccountId>), Self::Error> { ) -> Result<(LaneId, InboundLaneData<bp_millau::AccountId>), Self::Error> {
messages::source::verify_messages_delivery_proof::<WithRialtoMessageBridge, Runtime, crate::RialtoGrandpaInstance>( messages::source::verify_messages_delivery_proof::<
proof, WithRialtoMessageBridge,
) Runtime,
crate::RialtoGrandpaInstance,
>(proof)
} }
} }
@@ -240,15 +266,16 @@ impl SourceHeaderChain<bp_rialto::Balance> for Rialto {
proof: Self::MessagesProof, proof: Self::MessagesProof,
messages_count: u32, messages_count: u32,
) -> Result<ProvedMessages<Message<bp_rialto::Balance>>, Self::Error> { ) -> Result<ProvedMessages<Message<bp_rialto::Balance>>, Self::Error> {
messages::target::verify_messages_proof::<WithRialtoMessageBridge, Runtime, crate::RialtoGrandpaInstance>( messages::target::verify_messages_proof::<
proof, WithRialtoMessageBridge,
messages_count, Runtime,
) crate::RialtoGrandpaInstance,
>(proof, messages_count)
} }
} }
/// Millau -> Rialto message lane pallet parameters. /// Millau -> Rialto message lane pallet parameters.
#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq)] #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)]
pub enum MillauToRialtoMessagesParameter { pub enum MillauToRialtoMessagesParameter {
/// The conversion formula we use is: `MillauTokens = RialtoTokens * conversion_rate`. /// The conversion formula we use is: `MillauTokens = RialtoTokens * conversion_rate`.
RialtoToMillauConversionRate(FixedU128), RialtoToMillauConversionRate(FixedU128),
@@ -257,9 +284,8 @@ pub enum MillauToRialtoMessagesParameter {
impl MessagesParameter for MillauToRialtoMessagesParameter { impl MessagesParameter for MillauToRialtoMessagesParameter {
fn save(&self) { fn save(&self) {
match *self { match *self {
MillauToRialtoMessagesParameter::RialtoToMillauConversionRate(ref conversion_rate) => { MillauToRialtoMessagesParameter::RialtoToMillauConversionRate(ref conversion_rate) =>
RialtoToMillauConversionRate::set(conversion_rate) RialtoToMillauConversionRate::set(conversion_rate),
}
} }
} }
} }
@@ -0,0 +1,89 @@
[package]
name = "rialto-parachain-collator"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/parity-bridges-common/"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[build-dependencies]
substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
[[bin]]
name = 'rialto-parachain-collator'
[features]
default = []
runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks']
[dependencies]
derive_more = '0.99.2'
log = '0.4.14'
codec = { package = 'parity-scale-codec', version = '2.0.0' }
structopt = '0.3.8'
serde = { version = '1.0', features = ['derive'] }
hex-literal = '0.3.1'
# RPC related Dependencies
jsonrpc-core = '18.0'
# Local Dependencies
rialto-parachain-runtime = { path = '../runtime' }
# Substrate Dependencies
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-benchmarking-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-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-keystore = { 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", 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" }
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" }
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-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
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" }
# Cumulus dependencies
cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "master" }
cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "master" }
cumulus-client-collator = { git = "https://github.com/paritytech/cumulus", branch = "master" }
cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "master" }
cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "master" }
cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "master" }
cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master" }
cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "master" }
# 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" }
polkadot-test-service = { git = "https://github.com/paritytech/polkadot", branch = "master" }
@@ -0,0 +1,22 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed};
fn main() {
generate_cargo_keys();
rerun_if_git_head_changed();
}
@@ -0,0 +1,165 @@
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use cumulus_primitives_core::ParaId;
use rialto_parachain_runtime::{AccountId, AuraId, Signature};
use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};
use sc_service::ChainType;
use serde::{Deserialize, Serialize};
use sp_core::{sr25519, Pair, Public};
use sp_runtime::traits::{IdentifyAccount, Verify};
/// Specialized `ChainSpec` for the normal parachain runtime.
pub type ChainSpec =
sc_service::GenericChainSpec<rialto_parachain_runtime::GenesisConfig, Extensions>;
/// 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)
.expect("static values are valid; qed")
.public()
}
/// The extensions for the [`ChainSpec`].
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)]
#[serde(deny_unknown_fields)]
pub struct Extensions {
/// The relay chain of the Parachain.
pub relay_chain: String,
/// The id of the Parachain.
pub para_id: u32,
}
impl Extensions {
/// Try to get the extension from the given `ChainSpec`.
pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> {
sc_chain_spec::get_extension(chain_spec.extensions())
}
}
type AccountPublic = <Signature as Verify>::Signer;
/// Helper function to generate an account ID from seed
pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
where
AccountPublic: From<<TPublic::Pair as Pair>::Public>,
{
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
}
pub fn development_config(id: ParaId) -> ChainSpec {
// Give your base currency a unit name and decimal places
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "UNIT".into());
properties.insert("tokenDecimals".into(), 12.into());
ChainSpec::from_genesis(
// Name
"Development",
// ID
"dev",
ChainType::Local,
move || {
testnet_genesis(
get_account_id_from_seed::<sr25519::Public>("Alice"),
vec![get_from_seed::<AuraId>("Alice"), get_from_seed::<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>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
],
id,
)
},
vec![],
None,
None,
None,
Extensions {
relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
para_id: id.into(),
},
)
}
pub fn local_testnet_config(id: ParaId) -> ChainSpec {
// Give your base currency a unit name and decimal places
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "UNIT".into());
properties.insert("tokenDecimals".into(), 12.into());
ChainSpec::from_genesis(
// Name
"Local Testnet",
// ID
"local_testnet",
ChainType::Local,
move || {
testnet_genesis(
get_account_id_from_seed::<sr25519::Public>("Alice"),
vec![get_from_seed::<AuraId>("Alice"), get_from_seed::<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"),
],
id,
)
},
Vec::new(),
None,
None,
None,
Extensions {
relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
para_id: id.into(),
},
)
}
fn testnet_genesis(
root_key: AccountId,
initial_authorities: Vec<AuraId>,
endowed_accounts: Vec<AccountId>,
id: ParaId,
) -> rialto_parachain_runtime::GenesisConfig {
rialto_parachain_runtime::GenesisConfig {
system: rialto_parachain_runtime::SystemConfig {
code: rialto_parachain_runtime::WASM_BINARY
.expect("WASM binary was not build, please build it!")
.to_vec(),
changes_trie_config: Default::default(),
},
balances: rialto_parachain_runtime::BalancesConfig {
balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(),
},
sudo: rialto_parachain_runtime::SudoConfig { key: root_key },
parachain_info: rialto_parachain_runtime::ParachainInfoConfig { parachain_id: id },
aura: rialto_parachain_runtime::AuraConfig { authorities: initial_authorities },
aura_ext: Default::default(),
// parachain_system: Default::default(),
}
}
@@ -0,0 +1,137 @@
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::chain_spec;
use std::path::PathBuf;
use structopt::StructOpt;
/// Sub-commands supported by the collator.
#[derive(Debug, StructOpt)]
pub enum Subcommand {
/// Export the genesis state of the parachain.
#[structopt(name = "export-genesis-state")]
ExportGenesisState(ExportGenesisStateCommand),
/// Export the genesis wasm of the parachain.
#[structopt(name = "export-genesis-wasm")]
ExportGenesisWasm(ExportGenesisWasmCommand),
/// Build a chain specification.
BuildSpec(sc_cli::BuildSpecCmd),
/// Validate blocks.
CheckBlock(sc_cli::CheckBlockCmd),
/// Export blocks.
ExportBlocks(sc_cli::ExportBlocksCmd),
/// Export the state of a given block into a chain spec.
ExportState(sc_cli::ExportStateCmd),
/// Import blocks.
ImportBlocks(sc_cli::ImportBlocksCmd),
/// Remove the whole chain.
PurgeChain(cumulus_client_cli::PurgeChainCmd),
/// Revert the chain to a previous state.
Revert(sc_cli::RevertCmd),
/// The custom benchmark subcommmand benchmarking runtime pallets.
#[structopt(name = "benchmark", about = "Benchmark runtime pallets.")]
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
}
/// Command for exporting the genesis state of the parachain
#[derive(Debug, StructOpt)]
pub struct ExportGenesisStateCommand {
/// Output file name or stdout if unspecified.
#[structopt(parse(from_os_str))]
pub output: Option<PathBuf>,
/// Id of the parachain this state is for.
///
/// Default: 100
#[structopt(long, conflicts_with = "chain")]
pub parachain_id: Option<u32>,
/// Write output in binary. Default is to write in hex.
#[structopt(short, long)]
pub raw: bool,
/// The name of the chain for that the genesis state should be exported.
#[structopt(long, conflicts_with = "parachain-id")]
pub chain: Option<String>,
}
/// Command for exporting the genesis wasm file.
#[derive(Debug, StructOpt)]
pub struct ExportGenesisWasmCommand {
/// Output file name or stdout if unspecified.
#[structopt(parse(from_os_str))]
pub output: Option<PathBuf>,
/// Write output in binary. Default is to write in hex.
#[structopt(short, long)]
pub raw: bool,
/// The name of the chain for that the genesis wasm file should be exported.
#[structopt(long)]
pub chain: Option<String>,
}
#[derive(Debug, StructOpt)]
#[structopt(settings = &[
structopt::clap::AppSettings::GlobalVersion,
structopt::clap::AppSettings::ArgsNegateSubcommands,
structopt::clap::AppSettings::SubcommandsNegateReqs,
])]
pub struct Cli {
#[structopt(subcommand)]
pub subcommand: Option<Subcommand>,
#[structopt(flatten)]
pub run: cumulus_client_cli::RunCmd,
/// Relaychain arguments
#[structopt(raw = true)]
pub relaychain_args: Vec<String>,
}
#[derive(Debug)]
pub struct RelayChainCli {
/// The actual relay chain cli object.
pub base: polkadot_cli::RunCmd,
/// Optional chain id that should be passed to the relay chain.
pub chain_id: Option<String>,
/// The base path that should be used by the relay chain.
pub base_path: Option<PathBuf>,
}
impl RelayChainCli {
/// Parse the relay chain CLI parameters using the para chain `Configuration`.
pub fn new<'a>(
para_config: &sc_service::Configuration,
relay_chain_args: impl Iterator<Item = &'a String>,
) -> Self {
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("rialto-bridge-node"));
Self { base_path, chain_id, base: polkadot_cli::RunCmd::from_iter(relay_chain_args) }
}
}
@@ -0,0 +1,424 @@
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::{
chain_spec,
cli::{Cli, RelayChainCli, Subcommand},
service::{new_partial, ParachainRuntimeExecutor},
};
use codec::Encode;
use cumulus_client_service::genesis::generate_genesis_block;
use cumulus_primitives_core::ParaId;
use log::info;
use polkadot_parachain::primitives::AccountIdConversion;
use rialto_parachain_runtime::{Block, RuntimeApi};
use sc_cli::{
ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams,
NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli,
};
use sc_service::config::{BasePath, PrometheusConfig};
use sp_core::hexdisplay::HexDisplay;
use sp_runtime::traits::Block as BlockT;
use std::{io::Write, net::SocketAddr};
fn load_spec(
id: &str,
para_id: ParaId,
) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
Ok(match id {
"dev" => Box::new(chain_spec::development_config(para_id)),
"" | "local" => Box::new(chain_spec::local_testnet_config(para_id)),
path => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?),
})
}
impl SubstrateCli for Cli {
fn impl_name() -> String {
"Parachain Collator Template".into()
}
fn impl_version() -> String {
env!("SUBSTRATE_CLI_IMPL_VERSION").into()
}
fn description() -> String {
format!(
"Parachain Collator Template\n\nThe command-line arguments provided first will be \
passed to the parachain node, while the arguments provided after -- will be passed \
to the relaychain node.\n\n\
{} [parachain-args] -- [relaychain-args]",
Self::executable_name()
)
}
fn author() -> String {
env!("CARGO_PKG_AUTHORS").into()
}
fn support_url() -> String {
"https://github.com/substrate-developer-hub/substrate-parachain-template/issues/new".into()
}
fn copyright_start_year() -> i32 {
2017
}
fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
load_spec(id, self.run.parachain_id.unwrap_or(2000).into())
}
fn native_runtime_version(_: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {
&rialto_parachain_runtime::VERSION
}
}
impl SubstrateCli for RelayChainCli {
fn impl_name() -> String {
"Parachain Collator Template".into()
}
fn impl_version() -> String {
env!("SUBSTRATE_CLI_IMPL_VERSION").into()
}
fn description() -> String {
"Parachain Collator Template\n\nThe command-line arguments provided first will be \
passed to the parachain node, while the arguments provided after -- will be passed \
to the relaychain node.\n\n\
parachain-collator [parachain-args] -- [relaychain-args]"
.into()
}
fn author() -> String {
env!("CARGO_PKG_AUTHORS").into()
}
fn support_url() -> String {
"https://github.com/substrate-developer-hub/substrate-parachain-template/issues/new".into()
}
fn copyright_start_year() -> i32 {
2017
}
fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
polkadot_cli::Cli::from_iter([RelayChainCli::executable_name()].iter()).load_spec(id)
}
fn native_runtime_version(chain_spec: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {
polkadot_cli::Cli::native_runtime_version(chain_spec)
}
}
fn extract_genesis_wasm(chain_spec: &dyn sc_service::ChainSpec) -> Result<Vec<u8>> {
let mut storage = chain_spec.build_storage()?;
storage
.top
.remove(sp_core::storage::well_known_keys::CODE)
.ok_or_else(|| "Could not find wasm file in genesis state!".into())
}
macro_rules! construct_async_run {
(|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{
let runner = $cli.create_runner($cmd)?;
runner.async_run(|$config| {
let $components = new_partial::<
RuntimeApi,
ParachainRuntimeExecutor,
_
>(
&$config,
crate::service::parachain_build_import_queue,
)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
}}
}
/// Parse command line arguments into service configuration.
pub fn run() -> Result<()> {
let cli = Cli::from_args();
sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::Custom(
rialto_parachain_runtime::SS58Prefix::get() as u16,
));
match &cli.subcommand {
Some(Subcommand::BuildSpec(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
},
Some(Subcommand::CheckBlock(cmd)) => {
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, components.import_queue))
})
},
Some(Subcommand::ExportBlocks(cmd)) => {
construct_async_run!(|components, cli, cmd, config| Ok(
cmd.run(components.client, config.database)
))
},
Some(Subcommand::ExportState(cmd)) => {
construct_async_run!(|components, cli, cmd, config| Ok(
cmd.run(components.client, config.chain_spec)
))
},
Some(Subcommand::ImportBlocks(cmd)) => {
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, components.import_queue))
})
},
Some(Subcommand::PurgeChain(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| {
let polkadot_cli = RelayChainCli::new(
&config,
[RelayChainCli::executable_name()].iter().chain(cli.relaychain_args.iter()),
);
let polkadot_config = SubstrateCli::create_configuration(
&polkadot_cli,
&polkadot_cli,
config.tokio_handle.clone(),
)
.map_err(|err| format!("Relay chain argument error: {}", err))?;
cmd.run(config, polkadot_config)
})
},
Some(Subcommand::Revert(cmd)) => {
construct_async_run!(|components, cli, cmd, config| Ok(
cmd.run(components.client, components.backend)
))
},
Some(Subcommand::ExportGenesisState(params)) => {
let mut builder = sc_cli::LoggerBuilder::new("");
builder.with_profiling(sc_tracing::TracingReceiver::Log, "");
let _ = builder.init();
let block: Block = generate_genesis_block(&load_spec(
&params.chain.clone().unwrap_or_default(),
params.parachain_id.expect("Missing ParaId").into(),
)?)?;
let raw_header = block.header().encode();
let output_buf = if params.raw {
raw_header
} else {
format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes()
};
if let Some(output) = &params.output {
std::fs::write(output, output_buf)?;
} else {
std::io::stdout().write_all(&output_buf)?;
}
Ok(())
},
Some(Subcommand::ExportGenesisWasm(params)) => {
let mut builder = sc_cli::LoggerBuilder::new("");
builder.with_profiling(sc_tracing::TracingReceiver::Log, "");
let _ = builder.init();
let raw_wasm_blob =
extract_genesis_wasm(&*cli.load_spec(&params.chain.clone().unwrap_or_default())?)?;
let output_buf = if params.raw {
raw_wasm_blob
} else {
format!("0x{:?}", HexDisplay::from(&raw_wasm_blob)).into_bytes()
};
if let Some(output) = &params.output {
std::fs::write(output, output_buf)?;
} else {
std::io::stdout().write_all(&output_buf)?;
}
Ok(())
},
Some(Subcommand::Benchmark(cmd)) =>
if cfg!(feature = "runtime-benchmarks") {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run::<Block, ParachainRuntimeExecutor>(config))
} else {
Err("Benchmarking wasn't enabled when building the node. \
You can enable it with `--features runtime-benchmarks`."
.into())
},
None => {
let runner = cli.create_runner(&cli.run.normalize())?;
runner.run_node_until_exit(|config| async move {
let para_id =
chain_spec::Extensions::try_get(&*config.chain_spec).map(|e| e.para_id);
let polkadot_cli = RelayChainCli::new(
&config,
[RelayChainCli::executable_name()].iter().chain(cli.relaychain_args.iter()),
);
let id = ParaId::from(cli.run.parachain_id.or(para_id).expect("Missing ParaId"));
let parachain_account =
AccountIdConversion::<polkadot_primitives::v0::AccountId>::into_account(&id);
let block: Block =
generate_genesis_block(&config.chain_spec).map_err(|e| format!("{:?}", e))?;
let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode()));
let polkadot_config = SubstrateCli::create_configuration(
&polkadot_cli,
&polkadot_cli,
config.tokio_handle.clone(),
)
.map_err(|err| format!("Relay chain argument error: {}", err))?;
info!("Parachain id: {:?}", id);
info!("Parachain Account: {}", parachain_account);
info!("Parachain genesis state: {}", genesis_state);
info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" });
crate::service::start_node(config, polkadot_config, id)
.await
.map(|r| r.0)
.map_err(Into::into)
})
},
}
}
impl DefaultConfigurationValues for RelayChainCli {
fn p2p_listen_port() -> u16 {
30334
}
fn rpc_ws_listen_port() -> u16 {
9945
}
fn rpc_http_listen_port() -> u16 {
9934
}
fn prometheus_listen_port() -> u16 {
9616
}
}
impl CliConfiguration<Self> for RelayChainCli {
fn shared_params(&self) -> &SharedParams {
self.base.base.shared_params()
}
fn import_params(&self) -> Option<&ImportParams> {
self.base.base.import_params()
}
fn network_params(&self) -> Option<&NetworkParams> {
self.base.base.network_params()
}
fn keystore_params(&self) -> Option<&KeystoreParams> {
self.base.base.keystore_params()
}
fn base_path(&self) -> Result<Option<BasePath>> {
Ok(self
.shared_params()
.base_path()
.or_else(|| self.base_path.clone().map(Into::into)))
}
fn rpc_http(&self, default_listen_port: u16) -> Result<Option<SocketAddr>> {
self.base.base.rpc_http(default_listen_port)
}
fn rpc_ipc(&self) -> Result<Option<String>> {
self.base.base.rpc_ipc()
}
fn rpc_ws(&self, default_listen_port: u16) -> Result<Option<SocketAddr>> {
self.base.base.rpc_ws(default_listen_port)
}
fn prometheus_config(&self, default_listen_port: u16) -> Result<Option<PrometheusConfig>> {
self.base.base.prometheus_config(default_listen_port)
}
fn init<C: SubstrateCli>(&self) -> Result<()> {
unreachable!("PolkadotCli is never initialized; qed");
}
fn chain_id(&self, is_dev: bool) -> Result<String> {
let chain_id = self.base.base.chain_id(is_dev)?;
Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id })
}
fn role(&self, is_dev: bool) -> Result<sc_service::Role> {
self.base.base.role(is_dev)
}
fn transaction_pool(&self) -> Result<sc_service::config::TransactionPoolOptions> {
self.base.base.transaction_pool()
}
fn state_cache_child_ratio(&self) -> Result<Option<usize>> {
self.base.base.state_cache_child_ratio()
}
fn rpc_methods(&self) -> Result<sc_service::config::RpcMethods> {
self.base.base.rpc_methods()
}
fn rpc_ws_max_connections(&self) -> Result<Option<usize>> {
self.base.base.rpc_ws_max_connections()
}
fn rpc_cors(&self, is_dev: bool) -> Result<Option<Vec<String>>> {
self.base.base.rpc_cors(is_dev)
}
fn default_heap_pages(&self) -> Result<Option<u64>> {
self.base.base.default_heap_pages()
}
fn force_authoring(&self) -> Result<bool> {
self.base.base.force_authoring()
}
fn disable_grandpa(&self) -> Result<bool> {
self.base.base.disable_grandpa()
}
fn max_runtime_instances(&self) -> Result<Option<usize>> {
self.base.base.max_runtime_instances()
}
fn announce_block(&self) -> Result<bool> {
self.base.base.announce_block()
}
fn telemetry_endpoints(
&self,
chain_spec: &Box<dyn ChainSpec>,
) -> Result<Option<sc_telemetry::TelemetryEndpoints>> {
self.base.base.telemetry_endpoints(chain_spec)
}
}
@@ -0,0 +1,18 @@
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
pub mod chain_spec;
pub mod service;
@@ -0,0 +1,29 @@
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Substrate Parachain Node Template CLI
#![warn(missing_docs)]
mod chain_spec;
#[macro_use]
mod service;
mod cli;
mod command;
fn main() -> sc_cli::Result<()> {
command::run()
}
@@ -0,0 +1,496 @@
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
// std
use std::sync::Arc;
// Local Runtime Types
use rialto_parachain_runtime::RuntimeApi;
// Cumulus Imports
use cumulus_client_consensus_aura::{
build_aura_consensus, BuildAuraConsensusParams, SlotProportion,
};
use cumulus_client_consensus_common::ParachainConsensus;
use cumulus_client_network::build_block_announce_validator;
use cumulus_client_service::{
prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams,
};
use cumulus_primitives_core::ParaId;
// Substrate Imports
use sc_client_api::ExecutorProvider;
use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch};
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;
// Runtime type overrides
type BlockNumber = u32;
type Header = sp_runtime::generic::Header<BlockNumber, sp_runtime::traits::BlakeTwo256>;
pub type Block = sp_runtime::generic::Block<Header, sp_runtime::OpaqueExtrinsic>;
type Hash = sp_core::H256;
pub type ParachainRuntimeExecutor = ExecutorDispatch;
// Our native executor instance.
pub struct ExecutorDispatch;
impl NativeExecutionDispatch for ExecutorDispatch {
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
rialto_parachain_runtime::api::dispatch(method, data)
}
fn native_version() -> sc_executor::NativeVersion {
rialto_parachain_runtime::native_version()
}
}
/// Starts a `ServiceBuilder` for a full service.
///
/// Use this macro if you don't actually need the full service, but just the builder in order to
/// be able to perform chain operations.
#[allow(clippy::type_complexity)]
pub fn new_partial<RuntimeApi, Executor, BIQ>(
config: &Configuration,
build_import_queue: BIQ,
) -> Result<
PartialComponents<
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
TFullBackend<Block>,
(),
sc_consensus::DefaultImportQueue<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
>,
sc_transaction_pool::FullPool<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
>,
(Option<Telemetry>, Option<TelemetryWorkerHandle>),
>,
sc_service::Error,
>
where
RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>
+ Send
+ Sync
+ 'static,
RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::Metadata<Block>
+ sp_session::SessionKeys<Block>
+ sp_api::ApiExt<
Block,
StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,
> + sp_offchain::OffchainWorkerApi<Block>
+ sp_block_builder::BlockBuilder<Block>,
sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,
Executor: NativeExecutionDispatch + 'static,
BIQ: FnOnce(
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
&Configuration,
Option<TelemetryHandle>,
&TaskManager,
) -> Result<
sc_consensus::DefaultImportQueue<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
>,
sc_service::Error,
>,
{
let telemetry = config
.telemetry_endpoints
.clone()
.filter(|x| !x.is_empty())
.map(|endpoints| -> Result<_, sc_telemetry::Error> {
let worker = TelemetryWorker::new(16)?;
let telemetry = worker.handle().new_telemetry(endpoints);
Ok((worker, telemetry))
})
.transpose()?;
let executor = sc_executor::NativeElseWasmExecutor::<Executor>::new(
config.wasm_method,
config.default_heap_pages,
config.max_runtime_instances,
);
let (client, backend, keystore_container, task_manager) =
sc_service::new_full_parts::<Block, RuntimeApi, _>(
config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
executor,
)?;
let client = Arc::new(client);
let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());
let telemetry = telemetry.map(|(worker, telemetry)| {
task_manager.spawn_handle().spawn("telemetry", worker.run());
telemetry
});
let transaction_pool = sc_transaction_pool::BasicPool::new_full(
config.transaction_pool.clone(),
config.role.is_authority().into(),
config.prometheus_registry(),
task_manager.spawn_essential_handle(),
client.clone(),
);
let import_queue = build_import_queue(
client.clone(),
config,
telemetry.as_ref().map(|telemetry| telemetry.handle()),
&task_manager,
)?;
let params = PartialComponents {
backend,
client,
import_queue,
keystore_container,
task_manager,
transaction_pool,
select_chain: (),
other: (telemetry, telemetry_worker_handle),
};
Ok(params)
}
/// 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.
#[sc_tracing::logging::prefix_logs_with("Parachain")]
async fn start_node_impl<RuntimeApi, Executor, RB, BIQ, BIC>(
parachain_config: Configuration,
polkadot_config: Configuration,
id: ParaId,
rpc_ext_builder: RB,
build_import_queue: BIQ,
build_consensus: BIC,
) -> sc_service::error::Result<(
TaskManager,
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
)>
where
RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>
+ Send
+ Sync
+ 'static,
RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::Metadata<Block>
+ sp_session::SessionKeys<Block>
+ sp_api::ApiExt<
Block,
StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,
> + sp_offchain::OffchainWorkerApi<Block>
+ sp_block_builder::BlockBuilder<Block>
+ cumulus_primitives_core::CollectCollationInfo<Block>,
sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,
Executor: NativeExecutionDispatch + 'static,
RB: Fn(
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
) -> jsonrpc_core::IoHandler<sc_rpc::Metadata>
+ Send
+ 'static,
BIQ: FnOnce(
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
&Configuration,
Option<TelemetryHandle>,
&TaskManager,
) -> Result<
sc_consensus::DefaultImportQueue<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
>,
sc_service::Error,
>,
BIC: FnOnce(
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
Option<&Registry>,
Option<TelemetryHandle>,
&TaskManager,
&polkadot_service::NewFull<polkadot_service::Client>,
Arc<
sc_transaction_pool::FullPool<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
>,
>,
Arc<NetworkService<Block, Hash>>,
SyncCryptoStorePtr,
bool,
) -> Result<Box<dyn ParachainConsensus<Block>>, sc_service::Error>,
{
if matches!(parachain_config.role, Role::Light) {
return Err("Light client not supported!".into())
}
let parachain_config = prepare_node_config(parachain_config);
let params = new_partial::<RuntimeApi, Executor, BIQ>(&parachain_config, build_import_queue)?;
let (mut telemetry, telemetry_worker_handle) = params.other;
let relay_chain_full_node =
cumulus_client_service::build_polkadot_full_node(polkadot_config, telemetry_worker_handle)
.map_err(|e| match e {
polkadot_service::Error::Sub(x) => x,
s => format!("{}", s).into(),
})?;
let client = params.client.clone();
let backend = params.backend.clone();
let block_announce_validator = build_block_announce_validator(
relay_chain_full_node.client.clone(),
id,
Box::new(relay_chain_full_node.network.clone()),
relay_chain_full_node.backend.clone(),
);
let force_authoring = parachain_config.force_authoring;
let validator = parachain_config.role.is_authority();
let prometheus_registry = parachain_config.prometheus_registry().cloned();
let transaction_pool = params.transaction_pool.clone();
let mut task_manager = params.task_manager;
let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue);
let (network, system_rpc_tx, start_network) =
sc_service::build_network(sc_service::BuildNetworkParams {
config: &parachain_config,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue: import_queue.clone(),
on_demand: None,
block_announce_validator_builder: Some(Box::new(|_| block_announce_validator)),
warp_sync: None,
})?;
let rpc_client = client.clone();
let rpc_extensions_builder = Box::new(move |_, _| Ok(rpc_ext_builder(rpc_client.clone())));
sc_service::spawn_tasks(sc_service::SpawnTasksParams {
on_demand: None,
remote_blockchain: None,
rpc_extensions_builder,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
task_manager: &mut task_manager,
config: parachain_config,
keystore: params.keystore_container.sync_keystore(),
backend: backend.clone(),
network: network.clone(),
system_rpc_tx,
telemetry: telemetry.as_mut(),
})?;
let announce_block = {
let network = network.clone();
Arc::new(move |hash, data| network.announce_block(hash, data))
};
if validator {
let parachain_consensus = build_consensus(
client.clone(),
prometheus_registry.as_ref(),
telemetry.as_ref().map(|t| t.handle()),
&task_manager,
&relay_chain_full_node,
transaction_pool,
network,
params.keystore_container.sync_keystore(),
force_authoring,
)?;
let spawner = task_manager.spawn_handle();
let params = StartCollatorParams {
para_id: id,
block_status: client.clone(),
announce_block,
client: client.clone(),
task_manager: &mut task_manager,
relay_chain_full_node,
spawner,
parachain_consensus,
import_queue,
};
start_collator(params).await?;
} else {
let params = StartFullNodeParams {
client: client.clone(),
announce_block,
task_manager: &mut task_manager,
para_id: id,
relay_chain_full_node,
};
start_full_node(params)?;
}
start_network.start_network();
Ok((task_manager, client))
}
/// Build the import queue for the the parachain runtime.
#[allow(clippy::type_complexity)]
pub fn parachain_build_import_queue(
client: Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ParachainRuntimeExecutor>>>,
config: &Configuration,
telemetry: Option<TelemetryHandle>,
task_manager: &TaskManager,
) -> Result<
sc_consensus::DefaultImportQueue<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ParachainRuntimeExecutor>>,
>,
sc_service::Error,
> {
let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;
cumulus_client_consensus_aura::import_queue::<
sp_consensus_aura::sr25519::AuthorityPair,
_,
_,
_,
_,
_,
_,
>(cumulus_client_consensus_aura::ImportQueueParams {
block_import: client.clone(),
client: client.clone(),
create_inherent_data_providers: move |_, _| async move {
let time = sp_timestamp::InherentDataProvider::from_system_time();
let slot =
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*time,
slot_duration.slot_duration(),
);
Ok((time, slot))
},
registry: config.prometheus_registry(),
can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),
spawner: &task_manager.spawn_essential_handle(),
telemetry,
})
.map_err(Into::into)
}
/// Start a normal parachain node.
pub async fn start_node(
parachain_config: Configuration,
polkadot_config: Configuration,
id: ParaId,
) -> sc_service::error::Result<(
TaskManager,
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ParachainRuntimeExecutor>>>,
)> {
start_node_impl::<RuntimeApi, ParachainRuntimeExecutor, _, _, _>(
parachain_config,
polkadot_config,
id,
|_| Default::default(),
parachain_build_import_queue,
|client,
prometheus_registry,
telemetry,
task_manager,
relay_chain_node,
transaction_pool,
sync_oracle,
keystore,
force_authoring| {
let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;
let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(
task_manager.spawn_handle(),
client.clone(),
transaction_pool,
prometheus_registry,
telemetry.clone(),
);
let relay_chain_backend = relay_chain_node.backend.clone();
let relay_chain_client = relay_chain_node.client.clone();
Ok(build_aura_consensus::<
sp_consensus_aura::sr25519::AuthorityPair,
_,
_,
_,
_,
_,
_,
_,
_,
_,
>(BuildAuraConsensusParams {
proposer_factory,
create_inherent_data_providers: move |_, (relay_parent, validation_data)| {
let parachain_inherent =
cumulus_primitives_parachain_inherent::ParachainInherentData::create_at_with_client(
relay_parent,
&relay_chain_client,
&*relay_chain_backend,
&validation_data,
id,
);
async move {
let time = sp_timestamp::InherentDataProvider::from_system_time();
let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*time,
slot_duration.slot_duration(),
);
let parachain_inherent = parachain_inherent.ok_or_else(|| {
Box::<dyn std::error::Error + Send + Sync>::from(
"Failed to create parachain inherent",
)
})?;
Ok((time, slot, parachain_inherent))
}
},
block_import: client.clone(),
relay_chain_client: relay_chain_node.client.clone(),
relay_chain_backend: relay_chain_node.backend.clone(),
para_client: client,
backoff_authoring_blocks: Option::<()>::None,
sync_oracle,
keystore,
force_authoring,
slot_duration,
// We got around 500ms for proposing
block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32),
telemetry,
max_block_proposal_slot_portion: None,
}))
},
)
.await
}
@@ -0,0 +1,122 @@
[package]
name = "rialto-parachain-runtime"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/parity-bridges-common/"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[build-dependencies]
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
[dependencies]
codec = { package = 'parity-scale-codec', version = '2.0.0', default-features = false, features = ['derive']}
log = { version = "0.4.14", default-features = false }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
serde = { version = '1.0', optional = true, features = ['derive'] }
# Bridge depedencies
bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false }
# Substrate Dependencies
## Substrate Primitive Dependencies
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-block-builder = { 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-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-inherents = { 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-offchain = { 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-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
## Substrate FRAME Dependencies
frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
## Substrate Pallet Dependencies
pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
# Cumulus Dependencies
cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
# Polkadot Dependencies
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
[features]
default = ['std']
runtime-benchmarks = [
'sp-runtime/runtime-benchmarks',
'frame-benchmarking',
'frame-support/runtime-benchmarks',
'frame-system-benchmarking',
'frame-system/runtime-benchmarks',
'pallet-balances/runtime-benchmarks',
'pallet-timestamp/runtime-benchmarks',
]
std = [
"bp-rialto-parachain/std",
"codec/std",
"log/std",
"scale-info/std",
"serde",
"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-system/std",
"pallet-balances/std",
"pallet-randomness-collective-flip/std",
"pallet-timestamp/std",
"pallet-sudo/std",
"pallet-transaction-payment/std",
"parachain-info/std",
"cumulus-pallet-aura-ext/std",
"cumulus-pallet-parachain-system/std",
"cumulus-pallet-xcmp-queue/std",
"cumulus-pallet-xcm/std",
"cumulus-primitives-core/std",
"cumulus-primitives-timestamp/std",
"cumulus-primitives-utility/std",
"xcm/std",
"xcm-builder/std",
"xcm-executor/std",
"pallet-aura/std",
"sp-consensus-aura/std",
]
@@ -0,0 +1,25 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use substrate_wasm_builder::WasmBuilder;
fn main() {
WasmBuilder::new()
.with_current_project()
.export_heap_base()
.import_memory()
.build()
}
@@ -0,0 +1,646 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! The Rialto parachain runtime. This can be compiled with `#[no_std]`, ready for Wasm.
//!
//! Originally a copy of runtime from https://github.com/substrate-developer-hub/substrate-parachain-template.
#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit = "256"]
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{AccountIdLookup, Block as BlockT},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
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::{Everything, IsInVec, Randomness},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
DispatchClass, IdentityFee, Weight,
},
StorageValue,
};
pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall;
pub use pallet_timestamp::Call as TimestampCall;
pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
pub use sp_runtime::{MultiAddress, Perbill, Permill};
pub use bp_rialto_parachain::{
AccountId, Balance, BlockLength, BlockNumber, BlockWeights, Hash, Hasher as Hashing, Header,
Index, Signature, MAXIMUM_BLOCK_WEIGHT,
};
// Polkadot & XCM imports
use pallet_xcm::XcmPassthrough;
use polkadot_parachain::primitives::Sibling;
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset,
ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, UsingComponents,
};
use xcm_executor::{Config, XcmExecutor};
/// The address format for describing accounts.
pub type Address = 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::CheckSpecVersion<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,
AllPallets,
>;
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: Aura,
}
}
/// This runtime version.
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("template-parachain"),
impl_name: create_runtime_str!("template-parachain"),
authoring_version: 1,
spec_version: 1,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
};
/// This determines the average expected block time that we are targeting.
/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`.
/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked
/// up by `pallet_aura` to implement `fn slot_duration()`.
///
/// Change this to adjust the block time.
pub const MILLISECS_PER_BLOCK: u64 = 12000;
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
pub const EPOCH_DURATION_IN_BLOCKS: u32 = 10 * MINUTES;
// Time is measured by number of blocks.
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;
// Unit = the base number of indivisible units for balances
pub const UNIT: Balance = 1_000_000_000_000;
pub const MILLIUNIT: Balance = 1_000_000_000;
pub const MICROUNIT: Balance = 1_000_000;
// 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks.
pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4);
/// 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 BlockHashCount: BlockNumber = 250;
pub const Version: RuntimeVersion = VERSION;
pub const SS58Prefix: u8 = 48;
}
// Configure FRAME pallets to include in runtime.
impl frame_system::Config for Runtime {
/// The identifier used to distinguish between accounts.
type AccountId = AccountId;
/// The aggregated dispatch type that is available for extrinsics.
type Call = Call;
/// The lookup mechanism to get account ID from whatever is passed in dispatchers.
type Lookup = AccountIdLookup<AccountId, ()>;
/// The index type for storing how many extrinsics an account has signed.
type Index = Index;
/// The index type for blocks.
type BlockNumber = BlockNumber;
/// The type for hashing blocks and tries.
type Hash = Hash;
/// The hashing algorithm used.
type Hashing = Hashing;
/// The header type.
type Header = generic::Header<BlockNumber, Hashing>;
/// The ubiquitous event type.
type Event = Event;
/// The ubiquitous origin type.
type Origin = Origin;
/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
type BlockHashCount = BlockHashCount;
/// Runtime version.
type Version = Version;
/// Converts a module to an index of this module in the runtime.
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<Balance>;
/// What to do if a new account is created.
type OnNewAccount = ();
/// What to do if an account is fully reaped from the system.
type OnKilledAccount = ();
/// The weight of database operations that the runtime can invoke.
type DbWeight = ();
/// The basic call filter to use in dispatchable.
type BaseCallFilter = Everything;
/// Weight information for the extrinsics of this pallet.
type SystemWeightInfo = ();
/// Block & extrinsics weights: base values and limits.
type BlockWeights = BlockWeights;
/// The maximum length of a block (in bytes).
type BlockLength = BlockLength;
/// This is used as an identifier of the chain. 42 is the generic substrate prefix.
type SS58Prefix = SS58Prefix;
/// The action to take on a Runtime Upgrade
type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
}
parameter_types! {
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
}
impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the Unix epoch.
type Moment = u64;
type OnTimestampSet = ();
type MinimumPeriod = MinimumPeriod;
type WeightInfo = ();
}
parameter_types! {
pub const ExistentialDeposit: u128 = MILLIUNIT;
pub const TransferFee: u128 = MILLIUNIT;
pub const CreationFee: u128 = MILLIUNIT;
pub const TransactionByteFee: u128 = MICROUNIT;
pub const OperationalFeeMultiplier: u8 = 5;
pub const MaxLocks: u32 = 50;
pub const MaxReserves: u32 = 50;
}
impl pallet_balances::Config for Runtime {
/// The type for recording an account's balance.
type Balance = Balance;
/// The ubiquitous event type.
type Event = Event;
type DustRemoval = ();
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
type MaxLocks = MaxLocks;
type MaxReserves = MaxReserves;
type ReserveIdentifier = [u8; 8];
}
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, ()>;
type TransactionByteFee = TransactionByteFee;
type OperationalFeeMultiplier = OperationalFeeMultiplier;
type WeightToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = ();
}
impl pallet_sudo::Config for Runtime {
type Call = Call;
type Event = Event;
}
parameter_types! {
pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
}
impl cumulus_pallet_parachain_system::Config for Runtime {
type Event = Event;
type OnValidationData = ();
type SelfParaId = parachain_info::Pallet<Runtime>;
type OutboundXcmpMessageSource = XcmpQueue;
type DmpMessageHandler = DmpQueue;
type ReservedDmpWeight = ReservedDmpWeight;
type XcmpMessageHandler = XcmpQueue;
type ReservedXcmpWeight = ReservedXcmpWeight;
}
impl parachain_info::Config for Runtime {}
impl cumulus_pallet_aura_ext::Config for Runtime {}
impl pallet_randomness_collective_flip::Config for Runtime {}
parameter_types! {
pub const RelayLocation: MultiLocation = MultiLocation::parent();
pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
pub RelayOrigin: 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 `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
// recognised.
RelayChainAsNative<RelayOrigin, 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 weight - almost certainly a conservative estimate.
pub UnitWeightCost: Weight = 1_000_000;
// One UNIT buys 1 second of weight.
pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT);
pub const MaxInstructions: u32 = 100;
pub const MaxAuthorities: u32 = 100_000;
}
match_type! {
pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }
};
}
pub type Barrier = (
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom<Everything>,
AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>,
// ^^^ Parent & its unit plurality gets 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 = NativeAsset; // <- should be enough to allow teleportation of UNIT
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;
}
/// 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 = Everything;
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 = ();
}
impl cumulus_pallet_dmp_queue::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
}
impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
type DisabledValidators = ();
type MaxAuthorities = MaxAuthorities;
}
// /// Configure the pallet template in pallets/template.
// impl template::Config for Runtime {
// type Event = Event;
// }
// Create the runtime by composing the FRAME pallets that were previously configured.
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = generic::Block<Header, sp_runtime::OpaqueExtrinsic>,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Storage, Config, Event<T>},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},
TransactionPayment: pallet_transaction_payment::{Pallet, Storage},
ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event<T>} = 20,
ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,
Aura: pallet_aura::{Pallet, Config<T>},
AuraExt: cumulus_pallet_aura_ext::{Pallet, Config},
// XCM helpers.
XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,
DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
// //Template
// TemplatePallet: template::{Pallet, Call, Storage, Event<T>},
}
);
impl_runtime_apis! {
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 decode_session_keys(
encoded: Vec<u8>,
) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
SessionKeys::decode_into_raw_public_keys(&encoded)
}
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
SessionKeys::generate(seed)
}
}
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().to_vec()
}
}
impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
fn collect_collation_info() -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info()
}
}
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)
}
}
#[cfg(feature = "runtime-benchmarks")]
impl frame_benchmarking::Benchmark<Block> for Runtime {
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_system_benchmarking::Pallet as SystemBench;
impl frame_system_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_benchmark!(params, batches, frame_system, SystemBench::<Runtime>);
add_benchmark!(params, batches, pallet_balances, Balances);
add_benchmark!(params, batches, pallet_timestamp, Timestamp);
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,
);
+55 -5
View File
@@ -10,13 +10,17 @@ repository = "https://github.com/paritytech/parity-bridges-common/"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0" license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies] [dependencies]
jsonrpc-core = "15.1.0" futures = "0.3"
jsonrpc-core = "18.0"
kvdb = "0.10"
kvdb-rocksdb = "0.12"
lru = "0.7"
structopt = "0.3.21" structopt = "0.3.21"
serde_json = "1.0.59" serde_json = "1.0.59"
thiserror = "1.0"
# Bridge dependencies # Bridge dependencies
bp-messages = { path = "../../../primitives/messages" }
bp-runtime = { path = "../../../primitives/runtime" } bp-runtime = { path = "../../../primitives/runtime" }
bp-rialto = { path = "../../../primitives/chain-rialto" } bp-rialto = { path = "../../../primitives/chain-rialto" }
pallet-bridge-messages = { path = "../../../modules/messages" } pallet-bridge-messages = { path = "../../../modules/messages" }
@@ -24,32 +28,78 @@ rialto-runtime = { path = "../runtime" }
# Substrate Dependencies # Substrate Dependencies
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] } sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] }
sc-client-api = { 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 = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus-slots = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus-uncles = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
#sc-finality-grandpa-warp-sync = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } 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 = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { 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-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-authorship = { 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-consensus = { 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-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-frame-rpc-system = { 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" }
# Polkadot (parachain) Dependencies
polkadot-approval-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-availability-bitfield-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-availability-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-availability-recovery = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-collator-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-dispute-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-gossip-support = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-network-bridge = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-collation-generation = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-approval-voting = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-av-store = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-backing = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-bitfield-signing = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-candidate-validation = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-chain-api = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-chain-selection = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-dispute-participation = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-parachains-inherent = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-provisioner = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-runtime-api = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-dispute-coordinator = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-network-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-subsystem-util = { 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" }
polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-statement-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
[build-dependencies] [build-dependencies]
substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -15,12 +15,15 @@
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use bp_rialto::derive_account_from_millau_id; use bp_rialto::derive_account_from_millau_id;
use polkadot_primitives::v1::{AssignmentId, ValidatorId};
use rialto_runtime::{ use rialto_runtime::{
AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoPoaConfig, GenesisConfig, GrandpaConfig, AccountId, BabeConfig, BalancesConfig, BridgeKovanConfig, BridgeMillauMessagesConfig,
SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, BridgeRialtoPoaConfig, ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig,
SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY,
}; };
use serde_json::json; use serde_json::json;
use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_consensus_babe::AuthorityId as BabeId;
use sp_core::{sr25519, Pair, Public}; use sp_core::{sr25519, Pair, Public};
use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_finality_grandpa::AuthorityId as GrandpaId;
use sp_runtime::traits::{IdentifyAccount, Verify}; use sp_runtime::traits::{IdentifyAccount, Verify};
@@ -56,12 +59,17 @@ where
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account() AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
} }
/// Helper function to generate an authority key for Aura /// Helper function to generate authority keys.
pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { pub fn get_authority_keys_from_seed(
s: &str,
) -> (AccountId, BabeId, GrandpaId, ValidatorId, AssignmentId, AuthorityDiscoveryId) {
( (
get_account_id_from_seed::<sr25519::Public>(s), get_account_id_from_seed::<sr25519::Public>(s),
get_from_seed::<AuraId>(s), get_from_seed::<BabeId>(s),
get_from_seed::<GrandpaId>(s), get_from_seed::<GrandpaId>(s),
get_from_seed::<ValidatorId>(s),
get_from_seed::<AssignmentId>(s),
get_from_seed::<AuthorityDiscoveryId>(s),
) )
} }
@@ -71,10 +79,7 @@ impl Alternative {
let properties = Some( let properties = Some(
json!({ json!({
"tokenDecimals": 9, "tokenDecimals": 9,
"tokenSymbol": "RLT", "tokenSymbol": "RLT"
"bridgeIds": {
"Millau": bp_runtime::MILLAU_CHAIN_ID,
}
}) })
.as_object() .as_object()
.expect("Map given; qed") .expect("Map given; qed")
@@ -82,8 +87,8 @@ impl Alternative {
); );
match self { match self {
Alternative::Development => ChainSpec::from_genesis( Alternative::Development => ChainSpec::from_genesis(
"Development", "Rialto Development",
"dev", "rialto_dev",
sc_service::ChainType::Development, sc_service::ChainType::Development,
|| { || {
testnet_genesis( testnet_genesis(
@@ -108,8 +113,8 @@ impl Alternative {
None, None,
), ),
Alternative::LocalTestnet => ChainSpec::from_genesis( Alternative::LocalTestnet => ChainSpec::from_genesis(
"Local Testnet", "Rialto Local",
"local_testnet", "rialto_local",
sc_service::ChainType::Local, sc_service::ChainType::Local,
|| { || {
testnet_genesis( testnet_genesis(
@@ -138,10 +143,12 @@ impl Alternative {
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"), get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
get_account_id_from_seed::<sr25519::Public>("George//stash"), get_account_id_from_seed::<sr25519::Public>("George//stash"),
get_account_id_from_seed::<sr25519::Public>("Harry//stash"), get_account_id_from_seed::<sr25519::Public>("Harry//stash"),
pallet_bridge_messages::Pallet::< get_account_id_from_seed::<sr25519::Public>("MillauMessagesOwner"),
rialto_runtime::Runtime, get_account_id_from_seed::<sr25519::Public>("WithMillauTokenSwap"),
pallet_bridge_messages::DefaultInstance, pallet_bridge_messages::relayer_fund_account_id::<
>::relayer_fund_account_id(), bp_rialto::AccountId,
bp_rialto::AccountIdConverter,
>(),
derive_account_from_millau_id(bp_runtime::SourceAccount::Account( derive_account_from_millau_id(bp_runtime::SourceAccount::Account(
get_account_id_from_seed::<sr25519::Public>("Alice"), get_account_id_from_seed::<sr25519::Public>("Alice"),
)), )),
@@ -174,12 +181,25 @@ impl Alternative {
} }
} }
fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys { fn session_keys(
SessionKeys { aura, grandpa } babe: BabeId,
grandpa: GrandpaId,
para_validator: ValidatorId,
para_assignment: AssignmentId,
authority_discovery: AuthorityDiscoveryId,
) -> SessionKeys {
SessionKeys { babe, grandpa, para_validator, para_assignment, authority_discovery }
} }
fn testnet_genesis( fn testnet_genesis(
initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>, initial_authorities: Vec<(
AccountId,
BabeId,
GrandpaId,
ValidatorId,
AssignmentId,
AuthorityDiscoveryId,
)>,
root_key: AccountId, root_key: AccountId,
endowed_accounts: Vec<AccountId>, endowed_accounts: Vec<AccountId>,
_enable_println: bool, _enable_println: bool,
@@ -192,21 +212,82 @@ fn testnet_genesis(
balances: BalancesConfig { balances: BalancesConfig {
balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(),
}, },
aura: AuraConfig { babe: BabeConfig {
authorities: Vec::new(), authorities: Vec::new(),
epoch_config: Some(rialto_runtime::BABE_GENESIS_EPOCH_CONFIG),
}, },
bridge_rialto_poa: load_rialto_poa_bridge_config(), bridge_rialto_poa: load_rialto_poa_bridge_config(),
bridge_kovan: load_kovan_bridge_config(), bridge_kovan: load_kovan_bridge_config(),
grandpa: GrandpaConfig { grandpa: GrandpaConfig { authorities: Vec::new() },
authorities: Vec::new(),
},
sudo: SudoConfig { key: root_key }, sudo: SudoConfig { key: root_key },
session: SessionConfig { session: SessionConfig {
keys: initial_authorities keys: initial_authorities
.iter() .iter()
.map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) .map(|x| {
(
x.0.clone(),
x.0.clone(),
session_keys(
x.1.clone(),
x.2.clone(),
x.3.clone(),
x.4.clone(),
x.5.clone(),
),
)
})
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
}, },
authority_discovery: Default::default(),
hrmp: Default::default(),
// this configuration is exact copy of configuration from Polkadot repo
// (see /node/service/src/chain_spec.rs:default_parachains_host_configuration)
configuration: ConfigurationConfig {
config: polkadot_runtime_parachains::configuration::HostConfiguration {
validation_upgrade_frequency: 1u32,
validation_upgrade_delay: 1,
code_retention_period: 1200,
max_code_size: polkadot_primitives::v1::MAX_CODE_SIZE,
max_pov_size: polkadot_primitives::v1::MAX_POV_SIZE,
max_head_data_size: 32 * 1024,
group_rotation_frequency: 20,
chain_availability_period: 4,
thread_availability_period: 4,
max_upward_queue_count: 8,
max_upward_queue_size: 1024 * 1024,
max_downward_message_size: 1024,
// this is approximatelly 4ms.
//
// Same as `4 * frame_support::weights::WEIGHT_PER_MILLIS`. We don't bother with
// an import since that's a made up number and should be replaced with a constant
// obtained by benchmarking anyway.
ump_service_total_weight: 4 * 1_000_000_000,
max_upward_message_size: 1024 * 1024,
max_upward_message_num_per_candidate: 5,
hrmp_sender_deposit: 0,
hrmp_recipient_deposit: 0,
hrmp_channel_max_capacity: 8,
hrmp_channel_max_total_size: 8 * 1024,
hrmp_max_parachain_inbound_channels: 4,
hrmp_max_parathread_inbound_channels: 4,
hrmp_channel_max_message_size: 1024 * 1024,
hrmp_max_parachain_outbound_channels: 4,
hrmp_max_parathread_outbound_channels: 4,
hrmp_max_message_num_per_candidate: 5,
dispute_period: 6,
no_show_slots: 2,
n_delay_tranches: 25,
needed_approvals: 2,
relay_vrf_modulo_samples: 2,
zeroth_delay_tranche_width: 0,
..Default::default()
},
},
paras: Default::default(),
bridge_millau_messages: BridgeMillauMessagesConfig {
owner: Some(get_account_id_from_seed::<sr25519::Public>("MillauMessagesOwner")),
..Default::default()
},
} }
} }
@@ -229,9 +310,7 @@ fn load_kovan_bridge_config() -> BridgeKovanConfig {
#[test] #[test]
fn derived_dave_account_is_as_expected() { fn derived_dave_account_is_as_expected() {
let dave = get_account_id_from_seed::<sr25519::Public>("Dave"); let dave = get_account_id_from_seed::<sr25519::Public>("Dave");
let derived: AccountId = derive_account_from_millau_id(bp_runtime::SourceAccount::Account(dave)); let derived: AccountId =
assert_eq!( derive_account_from_millau_id(bp_runtime::SourceAccount::Account(dave));
derived.to_string(), assert_eq!(derived.to_string(), "5HZhdv53gSJmWWtD8XR5Ypu4PgbT5JNWwGw2mkE75cN61w9t".to_string());
"5HZhdv53gSJmWWtD8XR5Ypu4PgbT5JNWwGw2mkE75cN61w9t".to_string()
);
} }
+17 -2
View File
@@ -29,10 +29,10 @@ pub struct Cli {
/// Possible subcommands of the main binary. /// Possible subcommands of the main binary.
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
pub enum Subcommand { pub enum Subcommand {
/// Key management cli utilities /// Key management CLI utilities
Key(sc_cli::KeySubcommand), Key(sc_cli::KeySubcommand),
/// Verify a signature for a message, provided on STDIN, with a given (public or secret) key. /// Verify a signature for a message, provided on `STDIN`, with a given (public or secret) key.
Verify(sc_cli::VerifyCmd), Verify(sc_cli::VerifyCmd),
/// Generate a seed that provides a vanity address. /// Generate a seed that provides a vanity address.
@@ -67,4 +67,19 @@ pub enum Subcommand {
/// Benchmark runtime pallets. /// Benchmark runtime pallets.
Benchmark(frame_benchmarking_cli::BenchmarkCmd), Benchmark(frame_benchmarking_cli::BenchmarkCmd),
/// FOR INTERNAL USE: analog of the "prepare-worker" command of the polkadot binary.
#[structopt(name = "prepare-worker", setting = structopt::clap::AppSettings::Hidden)]
PvfPrepareWorker(ValidationWorkerCommand),
/// FOR INTERNAL USE: analog of the "execute-worker" command of the polkadot binary.
#[structopt(name = "execute-worker", setting = structopt::clap::AppSettings::Hidden)]
PvfExecuteWorker(ValidationWorkerCommand),
}
/// Validation worker command.
#[derive(Debug, StructOpt)]
pub struct ValidationWorkerCommand {
/// The path to the validation host's socket.
pub socket_path: String,
} }
+70 -50
View File
@@ -14,9 +14,10 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::cli::{Cli, Subcommand}; use crate::{
use crate::service; cli::{Cli, Subcommand},
use crate::service::new_partial; service::new_partial,
};
use rialto_runtime::{Block, RuntimeApi}; use rialto_runtime::{Block, RuntimeApi};
use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli};
use sc_service::PartialComponents; use sc_service::PartialComponents;
@@ -74,19 +75,18 @@ pub fn run() -> sc_cli::Result<()> {
)); ));
match &cli.subcommand { match &cli.subcommand {
Some(Subcommand::Benchmark(cmd)) => { Some(Subcommand::Benchmark(cmd)) =>
if cfg!(feature = "runtime-benchmarks") { if cfg!(feature = "runtime-benchmarks") {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run::<Block, service::Executor>(config)) runner.sync_run(|config| cmd.run::<Block, crate::service::ExecutorDispatch>(config))
} else { } else {
println!( println!(
"Benchmarking wasn't enabled when building the node. \ "Benchmarking wasn't enabled when building the node. \
You can enable it with `--features runtime-benchmarks`." You can enable it with `--features runtime-benchmarks`."
); );
Ok(()) Ok(())
} },
}
Some(Subcommand::Key(cmd)) => cmd.run(&cli), Some(Subcommand::Key(cmd)) => cmd.run(&cli),
Some(Subcommand::Sign(cmd)) => cmd.run(), Some(Subcommand::Sign(cmd)) => cmd.run(),
Some(Subcommand::Verify(cmd)) => cmd.run(), Some(Subcommand::Verify(cmd)) => cmd.run(),
@@ -94,79 +94,99 @@ pub fn run() -> sc_cli::Result<()> {
Some(Subcommand::BuildSpec(cmd)) => { Some(Subcommand::BuildSpec(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
} },
Some(Subcommand::CheckBlock(cmd)) => { Some(Subcommand::CheckBlock(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.async_run(|config| { runner.async_run(|mut config| {
let PartialComponents { let PartialComponents { client, task_manager, import_queue, .. } =
client, new_partial(&mut config).map_err(service_error)?;
task_manager,
import_queue,
..
} = new_partial(&config)?;
Ok((cmd.run(client, import_queue), task_manager)) Ok((cmd.run(client, import_queue), task_manager))
}) })
} },
Some(Subcommand::ExportBlocks(cmd)) => { Some(Subcommand::ExportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.async_run(|config| { runner.async_run(|mut config| {
let PartialComponents { let PartialComponents { client, task_manager, .. } =
client, task_manager, .. new_partial(&mut config).map_err(service_error)?;
} = new_partial(&config)?;
Ok((cmd.run(client, config.database), task_manager)) Ok((cmd.run(client, config.database), task_manager))
}) })
} },
Some(Subcommand::ExportState(cmd)) => { Some(Subcommand::ExportState(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.async_run(|config| { runner.async_run(|mut config| {
let PartialComponents { let PartialComponents { client, task_manager, .. } =
client, task_manager, .. new_partial(&mut config).map_err(service_error)?;
} = new_partial(&config)?;
Ok((cmd.run(client, config.chain_spec), task_manager)) Ok((cmd.run(client, config.chain_spec), task_manager))
}) })
} },
Some(Subcommand::ImportBlocks(cmd)) => { Some(Subcommand::ImportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.async_run(|config| { runner.async_run(|mut config| {
let PartialComponents { let PartialComponents { client, task_manager, import_queue, .. } =
client, new_partial(&mut config).map_err(service_error)?;
task_manager,
import_queue,
..
} = new_partial(&config)?;
Ok((cmd.run(client, import_queue), task_manager)) Ok((cmd.run(client, import_queue), task_manager))
}) })
} },
Some(Subcommand::PurgeChain(cmd)) => { Some(Subcommand::PurgeChain(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.database)) runner.sync_run(|config| cmd.run(config.database))
} },
Some(Subcommand::Revert(cmd)) => { Some(Subcommand::Revert(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.async_run(|config| { runner.async_run(|mut config| {
let PartialComponents { let PartialComponents { client, task_manager, backend, .. } =
client, new_partial(&mut config).map_err(service_error)?;
task_manager,
backend,
..
} = new_partial(&config)?;
Ok((cmd.run(client, backend), task_manager)) Ok((cmd.run(client, backend), task_manager))
}) })
} },
Some(Subcommand::Inspect(cmd)) => { Some(Subcommand::Inspect(cmd)) => {
let runner = cli.create_runner(cmd)?; let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run::<Block, RuntimeApi, service::Executor>(config)) runner.sync_run(|config| {
} cmd.run::<Block, RuntimeApi, crate::service::ExecutorDispatch>(config)
})
},
Some(Subcommand::PvfPrepareWorker(cmd)) => {
let mut builder = sc_cli::LoggerBuilder::new("");
builder.with_colors(false);
let _ = builder.init();
polkadot_node_core_pvf::prepare_worker_entrypoint(&cmd.socket_path);
Ok(())
},
Some(crate::cli::Subcommand::PvfExecuteWorker(cmd)) => {
let mut builder = sc_cli::LoggerBuilder::new("");
builder.with_colors(false);
let _ = builder.init();
polkadot_node_core_pvf::execute_worker_entrypoint(&cmd.socket_path);
Ok(())
},
None => { None => {
let runner = cli.create_runner(&cli.run)?; let runner = cli.create_runner(&cli.run)?;
runner
.run_node_until_exit(|config| async move { // some parameters that are used by polkadot nodes, but that are not used by our binary
// let jaeger_agent = None;
// let grandpa_pause = None;
// let no_beefy = true;
// let telemetry_worker_handler = None;
// let is_collator = crate::service::IsCollator::No;
let overseer_gen = crate::overseer::RealOverseerGen;
runner.run_node_until_exit(|config| async move {
match config.role { match config.role {
Role::Light => service::new_light(config), Role::Light => Err(sc_cli::Error::Service(sc_service::Error::Other(
_ => service::new_full(config), "Light client is not supported by this node".into(),
))),
_ => crate::service::build_full(config, overseer_gen)
.map(|full| full.task_manager)
.map_err(service_error),
} }
}) })
.map_err(sc_cli::Error::Service) },
} }
} }
// We don't want to change 'service.rs' too much to ease future updates => it'll keep using
// its own error enum like original polkadot service does.
fn service_error(err: crate::service::Error) -> sc_cli::Error {
sc_cli::Error::Application(Box::new(err))
} }
@@ -23,6 +23,8 @@ mod chain_spec;
mod service; mod service;
mod cli; mod cli;
mod command; mod command;
mod overseer;
mod parachains_db;
/// Run the Rialto Node /// Run the Rialto Node
fn main() -> sc_cli::Result<()> { fn main() -> sc_cli::Result<()> {
@@ -0,0 +1,319 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! This is almost 1:1 copy of `node/service/src/overseer.rs` file from Polkadot repository.
//! The only exception is that we don't support db upgrades => no `upgrade.rs` module.
// this warning comes from `polkadot_overseer::AllSubsystems` type
#![allow(clippy::type_complexity)]
use crate::service::{AuthorityDiscoveryApi, Error};
use rialto_runtime::{opaque::Block, Hash};
use lru::LruCache;
use polkadot_availability_distribution::IncomingRequestReceivers;
use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig;
use polkadot_node_core_av_store::Config as AvailabilityConfig;
use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig;
use polkadot_node_core_chain_selection::Config as ChainSelectionConfig;
use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig;
use polkadot_node_network_protocol::request_response::{v1 as request_v1, IncomingRequestReceiver};
use polkadot_overseer::{
metrics::Metrics as OverseerMetrics, BlockInfo, MetricsTrait, Overseer, OverseerBuilder,
OverseerConnector, OverseerHandle,
};
use polkadot_primitives::v1::ParachainHost;
use sc_authority_discovery::Service as AuthorityDiscoveryService;
use sc_client_api::AuxStore;
use sc_keystore::LocalKeystore;
use sp_api::ProvideRuntimeApi;
use sp_blockchain::HeaderBackend;
use sp_consensus_babe::BabeApi;
use sp_core::traits::SpawnNamed;
use std::sync::Arc;
use substrate_prometheus_endpoint::Registry;
pub use polkadot_approval_distribution::ApprovalDistribution as ApprovalDistributionSubsystem;
pub use polkadot_availability_bitfield_distribution::BitfieldDistribution as BitfieldDistributionSubsystem;
pub use polkadot_availability_distribution::AvailabilityDistributionSubsystem;
pub use polkadot_availability_recovery::AvailabilityRecoverySubsystem;
pub use polkadot_collator_protocol::{CollatorProtocolSubsystem, ProtocolSide};
pub use polkadot_dispute_distribution::DisputeDistributionSubsystem;
pub use polkadot_gossip_support::GossipSupport as GossipSupportSubsystem;
pub use polkadot_network_bridge::NetworkBridge as NetworkBridgeSubsystem;
pub use polkadot_node_collation_generation::CollationGenerationSubsystem;
pub use polkadot_node_core_approval_voting::ApprovalVotingSubsystem;
pub use polkadot_node_core_av_store::AvailabilityStoreSubsystem;
pub use polkadot_node_core_backing::CandidateBackingSubsystem;
pub use polkadot_node_core_bitfield_signing::BitfieldSigningSubsystem;
pub use polkadot_node_core_candidate_validation::CandidateValidationSubsystem;
pub use polkadot_node_core_chain_api::ChainApiSubsystem;
pub use polkadot_node_core_chain_selection::ChainSelectionSubsystem;
pub use polkadot_node_core_dispute_coordinator::DisputeCoordinatorSubsystem;
pub use polkadot_node_core_dispute_participation::DisputeParticipationSubsystem;
pub use polkadot_node_core_provisioner::ProvisioningSubsystem as ProvisionerSubsystem;
pub use polkadot_node_core_runtime_api::RuntimeApiSubsystem;
pub use polkadot_statement_distribution::StatementDistribution as StatementDistributionSubsystem;
/// Arguments passed for overseer construction.
pub struct OverseerGenArgs<'a, Spawner, RuntimeClient>
where
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
Spawner: 'static + SpawnNamed + Clone + Unpin,
{
/// Set of initial relay chain leaves to track.
pub leaves: Vec<BlockInfo>,
/// The keystore to use for i.e. validator keys.
pub keystore: Arc<LocalKeystore>,
/// Runtime client generic, providing the `ProvieRuntimeApi` trait besides others.
pub runtime_client: Arc<RuntimeClient>,
/// The underlying key value store for the parachains.
pub parachains_db: Arc<dyn kvdb::KeyValueDB>,
/// Underlying network service implementation.
pub network_service: Arc<sc_network::NetworkService<Block, Hash>>,
/// Underlying authority discovery service.
pub authority_discovery_service: AuthorityDiscoveryService,
/// POV request receiver
pub pov_req_receiver: IncomingRequestReceiver<request_v1::PoVFetchingRequest>,
pub chunk_req_receiver: IncomingRequestReceiver<request_v1::ChunkFetchingRequest>,
pub collation_req_receiver: IncomingRequestReceiver<request_v1::CollationFetchingRequest>,
pub available_data_req_receiver:
IncomingRequestReceiver<request_v1::AvailableDataFetchingRequest>,
pub statement_req_receiver: IncomingRequestReceiver<request_v1::StatementFetchingRequest>,
pub dispute_req_receiver: IncomingRequestReceiver<request_v1::DisputeRequest>,
/// Prometheus registry, commonly used for production systems, less so for test.
pub registry: Option<&'a Registry>,
/// Task spawner to be used throughout the overseer and the APIs it provides.
pub spawner: Spawner,
/// Configuration for the approval voting subsystem.
pub approval_voting_config: ApprovalVotingConfig,
/// Configuration for the availability store subsystem.
pub availability_config: AvailabilityConfig,
/// Configuration for the candidate validation subsystem.
pub candidate_validation_config: CandidateValidationConfig,
/// Configuration for the chain selection subsystem.
pub chain_selection_config: ChainSelectionConfig,
/// Configuration for the dispute coordinator subsystem.
pub dispute_coordinator_config: DisputeCoordinatorConfig,
}
/// Obtain a prepared `OverseerBuilder`, that is initialized
/// with all default values.
pub fn prepared_overseer_builder<Spawner, RuntimeClient>(
OverseerGenArgs {
leaves,
keystore,
runtime_client,
parachains_db,
network_service,
authority_discovery_service,
pov_req_receiver,
chunk_req_receiver,
collation_req_receiver: _,
available_data_req_receiver,
statement_req_receiver,
dispute_req_receiver,
registry,
spawner,
approval_voting_config,
availability_config,
candidate_validation_config,
chain_selection_config,
dispute_coordinator_config,
}: OverseerGenArgs<'_, Spawner, RuntimeClient>,
) -> Result<
OverseerBuilder<
Spawner,
Arc<RuntimeClient>,
CandidateValidationSubsystem,
CandidateBackingSubsystem<Spawner>,
StatementDistributionSubsystem,
AvailabilityDistributionSubsystem,
AvailabilityRecoverySubsystem,
BitfieldSigningSubsystem<Spawner>,
BitfieldDistributionSubsystem,
ProvisionerSubsystem<Spawner>,
RuntimeApiSubsystem<RuntimeClient>,
AvailabilityStoreSubsystem,
NetworkBridgeSubsystem<
Arc<sc_network::NetworkService<Block, Hash>>,
AuthorityDiscoveryService,
>,
ChainApiSubsystem<RuntimeClient>,
CollationGenerationSubsystem,
CollatorProtocolSubsystem,
ApprovalDistributionSubsystem,
ApprovalVotingSubsystem,
GossipSupportSubsystem<AuthorityDiscoveryService>,
DisputeCoordinatorSubsystem,
DisputeParticipationSubsystem,
DisputeDistributionSubsystem<AuthorityDiscoveryService>,
ChainSelectionSubsystem,
>,
Error,
>
where
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
Spawner: 'static + SpawnNamed + Clone + Unpin,
{
use polkadot_node_subsystem_util::metrics::Metrics;
use std::iter::FromIterator;
let metrics = <OverseerMetrics as MetricsTrait>::register(registry)?;
let builder = Overseer::builder()
.availability_distribution(AvailabilityDistributionSubsystem::new(
keystore.clone(),
IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver },
Metrics::register(registry)?,
))
.availability_recovery(AvailabilityRecoverySubsystem::with_chunks_only(
available_data_req_receiver,
Metrics::register(registry)?,
))
.availability_store(AvailabilityStoreSubsystem::new(
parachains_db.clone(),
availability_config,
Metrics::register(registry)?,
))
.bitfield_distribution(BitfieldDistributionSubsystem::new(Metrics::register(registry)?))
.bitfield_signing(BitfieldSigningSubsystem::new(
spawner.clone(),
keystore.clone(),
Metrics::register(registry)?,
))
.candidate_backing(CandidateBackingSubsystem::new(
spawner.clone(),
keystore.clone(),
Metrics::register(registry)?,
))
.candidate_validation(CandidateValidationSubsystem::with_config(
candidate_validation_config,
Metrics::register(registry)?, // candidate-validation metrics
Metrics::register(registry)?, // validation host metrics
))
.chain_api(ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?))
.collation_generation(CollationGenerationSubsystem::new(Metrics::register(registry)?))
.collator_protocol(CollatorProtocolSubsystem::new(ProtocolSide::Validator {
keystore: keystore.clone(),
eviction_policy: Default::default(),
metrics: Metrics::register(registry)?,
}))
.network_bridge(NetworkBridgeSubsystem::new(
network_service.clone(),
authority_discovery_service.clone(),
Box::new(network_service.clone()),
Metrics::register(registry)?,
))
.provisioner(ProvisionerSubsystem::new(spawner.clone(), (), Metrics::register(registry)?))
.runtime_api(RuntimeApiSubsystem::new(
runtime_client.clone(),
Metrics::register(registry)?,
spawner.clone(),
))
.statement_distribution(StatementDistributionSubsystem::new(
keystore.clone(),
statement_req_receiver,
Metrics::register(registry)?,
))
.approval_distribution(ApprovalDistributionSubsystem::new(Metrics::register(registry)?))
.approval_voting(ApprovalVotingSubsystem::with_config(
approval_voting_config,
parachains_db.clone(),
keystore.clone(),
Box::new(network_service),
Metrics::register(registry)?,
))
.gossip_support(GossipSupportSubsystem::new(
keystore.clone(),
authority_discovery_service.clone(),
))
.dispute_coordinator(DisputeCoordinatorSubsystem::new(
parachains_db.clone(),
dispute_coordinator_config,
keystore.clone(),
Metrics::register(registry)?,
))
.dispute_participation(DisputeParticipationSubsystem::new())
.dispute_distribution(DisputeDistributionSubsystem::new(
keystore,
dispute_req_receiver,
authority_discovery_service,
Metrics::register(registry)?,
))
.chain_selection(ChainSelectionSubsystem::new(chain_selection_config, parachains_db))
.leaves(Vec::from_iter(
leaves
.into_iter()
.map(|BlockInfo { hash, parent_hash: _, number }| (hash, number)),
))
.activation_external_listeners(Default::default())
.span_per_active_leaf(Default::default())
.active_leaves(Default::default())
.supports_parachains(runtime_client)
.known_leaves(LruCache::new(KNOWN_LEAVES_CACHE_SIZE))
.metrics(metrics)
.spawner(spawner);
Ok(builder)
}
/// Trait for the `fn` generating the overseer.
///
/// Default behavior is to create an unmodified overseer, as `RealOverseerGen`
/// would do.
pub trait OverseerGen {
/// Overwrite the full generation of the overseer, including the subsystems.
fn generate<Spawner, RuntimeClient>(
&self,
connector: OverseerConnector,
args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
) -> Result<(Overseer<Spawner, Arc<RuntimeClient>>, OverseerHandle), Error>
where
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
Spawner: 'static + SpawnNamed + Clone + Unpin,
{
let gen = RealOverseerGen;
RealOverseerGen::generate::<Spawner, RuntimeClient>(&gen, connector, args)
}
// It would be nice to make `create_subsystems` part of this trait,
// but the amount of generic arguments that would be required as
// as consequence make this rather annoying to implement and use.
}
use polkadot_overseer::KNOWN_LEAVES_CACHE_SIZE;
/// The regular set of subsystems.
pub struct RealOverseerGen;
impl OverseerGen for RealOverseerGen {
fn generate<Spawner, RuntimeClient>(
&self,
connector: OverseerConnector,
args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
) -> Result<(Overseer<Spawner, Arc<RuntimeClient>>, OverseerHandle), Error>
where
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
Spawner: 'static + SpawnNamed + Clone + Unpin,
{
prepared_overseer_builder(args)?
.build_with_connector(connector)
.map_err(|e| e.into())
}
}
@@ -0,0 +1,104 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! This is almost 1:1 copy of `node/service/parachains_db/mod.rs` file from Polkadot repository.
//! The only exception is that we don't support db upgrades => no `upgrade.rs` module.
use kvdb::KeyValueDB;
use std::{io, path::PathBuf, sync::Arc};
mod columns {
pub const NUM_COLUMNS: u32 = 5;
pub const COL_AVAILABILITY_DATA: u32 = 0;
pub const COL_AVAILABILITY_META: u32 = 1;
pub const COL_APPROVAL_DATA: u32 = 2;
pub const COL_CHAIN_SELECTION_DATA: u32 = 3;
pub const COL_DISPUTE_COORDINATOR_DATA: u32 = 4;
}
/// Columns used by different subsystems.
#[derive(Debug, Clone)]
pub struct ColumnsConfig {
/// The column used by the av-store for data.
pub col_availability_data: u32,
/// The column used by the av-store for meta information.
pub col_availability_meta: u32,
/// The column used by approval voting for data.
pub col_approval_data: u32,
/// The column used by chain selection for data.
pub col_chain_selection_data: u32,
/// The column used by dispute coordinator for data.
pub col_dispute_coordinator_data: u32,
}
/// The real columns used by the parachains DB.
pub const REAL_COLUMNS: ColumnsConfig = ColumnsConfig {
col_availability_data: columns::COL_AVAILABILITY_DATA,
col_availability_meta: columns::COL_AVAILABILITY_META,
col_approval_data: columns::COL_APPROVAL_DATA,
col_chain_selection_data: columns::COL_CHAIN_SELECTION_DATA,
col_dispute_coordinator_data: columns::COL_DISPUTE_COORDINATOR_DATA,
};
/// The cache size for each column, in megabytes.
#[derive(Debug, Clone)]
pub struct CacheSizes {
/// Cache used by availability data.
pub availability_data: usize,
/// Cache used by availability meta.
pub availability_meta: usize,
/// Cache used by approval data.
pub approval_data: usize,
}
impl Default for CacheSizes {
fn default() -> Self {
CacheSizes { availability_data: 25, availability_meta: 1, approval_data: 5 }
}
}
fn other_io_error(err: String) -> io::Error {
io::Error::new(io::ErrorKind::Other, err)
}
/// Open the database on disk, creating it if it doesn't exist.
pub fn open_creating(root: PathBuf, cache_sizes: CacheSizes) -> io::Result<Arc<dyn KeyValueDB>> {
use kvdb_rocksdb::{Database, DatabaseConfig};
let path = root.join("parachains").join("db");
let mut db_config = DatabaseConfig::with_columns(columns::NUM_COLUMNS);
let _ = db_config
.memory_budget
.insert(columns::COL_AVAILABILITY_DATA, cache_sizes.availability_data);
let _ = db_config
.memory_budget
.insert(columns::COL_AVAILABILITY_META, cache_sizes.availability_meta);
let _ = db_config
.memory_budget
.insert(columns::COL_APPROVAL_DATA, cache_sizes.approval_data);
let path_str = path
.to_str()
.ok_or_else(|| other_io_error(format!("Bad database path: {:?}", path)))?;
std::fs::create_dir_all(&path_str)?;
let db = Database::open(&db_config, path_str)?;
Ok(Arc::new(db))
}
File diff suppressed because it is too large Load Diff
+22 -10
View File
@@ -8,11 +8,12 @@ repository = "https://github.com/paritytech/parity-bridges-common/"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0" license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies] [dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] }
hex-literal = "0.3" hex-literal = "0.3"
libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] } libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] }
log = { version = "0.4.14", default-features = false } log = { version = "0.4.14", default-features = false }
serde = { version = "1.0.124", optional = true, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] }
serde = { version = "1.0", optional = true, features = ["derive"] }
# Bridge dependencies # Bridge dependencies
@@ -39,18 +40,19 @@ frame-executive = { git = "https://github.com/paritytech/substrate", branch = "m
frame-support = { 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 } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-block-builder = { 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-consensus-babe = { 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-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
@@ -63,9 +65,14 @@ sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
# Polkadot (parachain) Dependencies
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
[dev-dependencies] [dev-dependencies]
libsecp256k1 = { version = "0.3.4", features = ["hmac"] } libsecp256k1 = { version = "0.7", features = ["hmac"] }
[build-dependencies] [build-dependencies]
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -89,7 +96,8 @@ std = [
"frame-system-rpc-runtime-api/std", "frame-system-rpc-runtime-api/std",
"frame-system/std", "frame-system/std",
"log/std", "log/std",
"pallet-aura/std", "pallet-authority-discovery/std",
"pallet-babe/std",
"pallet-balances/std", "pallet-balances/std",
"pallet-bridge-currency-exchange/std", "pallet-bridge-currency-exchange/std",
"pallet-bridge-dispatch/std", "pallet-bridge-dispatch/std",
@@ -97,16 +105,20 @@ std = [
"pallet-bridge-grandpa/std", "pallet-bridge-grandpa/std",
"pallet-bridge-messages/std", "pallet-bridge-messages/std",
"pallet-grandpa/std", "pallet-grandpa/std",
"pallet-randomness-collective-flip/std",
"pallet-shift-session-manager/std", "pallet-shift-session-manager/std",
"pallet-sudo/std", "pallet-sudo/std",
"pallet-timestamp/std", "pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std", "pallet-transaction-payment/std",
"polkadot-primitives/std",
"polkadot-runtime-common/std",
"polkadot-runtime-parachains/std",
"scale-info/std",
"serde", "serde",
"sp-api/std", "sp-api/std",
"sp-authority-discovery/std",
"sp-block-builder/std", "sp-block-builder/std",
"sp-consensus-aura/std", "sp-consensus-babe/std",
"sp-core/std", "sp-core/std",
"sp-finality-grandpa/std", "sp-finality-grandpa/std",
"sp-inherents/std", "sp-inherents/std",
@@ -22,7 +22,8 @@ use pallet_bridge_eth_poa::{ValidatorsConfiguration, ValidatorsSource};
use sp_std::vec; use sp_std::vec;
pub use crate::kovan::{ pub use crate::kovan::{
genesis_header, genesis_validators, BridgeAuraConfiguration, FinalityVotesCachingInterval, PruningStrategy, genesis_header, genesis_validators, BridgeAuraConfiguration, FinalityVotesCachingInterval,
PruningStrategy,
}; };
frame_support::parameter_types! { frame_support::parameter_types! {
@@ -28,19 +28,21 @@
//! 5) receive tokens by providing proof-of-inclusion of PoA transaction. //! 5) receive tokens by providing proof-of-inclusion of PoA transaction.
use bp_currency_exchange::{ use bp_currency_exchange::{
Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, Result as ExchangeResult, Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction,
Result as ExchangeResult,
}; };
use bp_eth_poa::{transaction_decode_rlp, RawTransaction, RawTransactionReceipt}; use bp_eth_poa::{transaction_decode_rlp, RawTransaction, RawTransactionReceipt};
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_support::RuntimeDebug; use frame_support::RuntimeDebug;
use hex_literal::hex; use hex_literal::hex;
use scale_info::TypeInfo;
use sp_std::vec::Vec; use sp_std::vec::Vec;
/// Ethereum address where locked PoA funds must be sent to. /// Ethereum address where locked PoA funds must be sent to.
pub const LOCK_FUNDS_ADDRESS: [u8; 20] = hex!("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"); pub const LOCK_FUNDS_ADDRESS: [u8; 20] = hex!("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF");
/// Ethereum transaction inclusion proof. /// Ethereum transaction inclusion proof.
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
pub struct EthereumTransactionInclusionProof { pub struct EthereumTransactionInclusionProof {
/// Hash of the block with transaction. /// Hash of the block with transaction.
pub block: sp_core::H256, pub block: sp_core::H256,
@@ -55,9 +57,9 @@ pub struct EthereumTransactionInclusionProof {
/// ///
/// The assumption is that this pair will never appear more than once in /// The assumption is that this pair will never appear more than once in
/// transactions included into finalized blocks. This is obviously true /// transactions included into finalized blocks. This is obviously true
/// for any existing eth-like chain (that keep current transaction format), /// for any existing eth-like chain (that keep current TX format), because
/// because otherwise transaction can be replayed over and over. /// otherwise transaction can be replayed over and over.
#[derive(Encode, Decode, PartialEq, RuntimeDebug)] #[derive(Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
pub struct EthereumTransactionTag { pub struct EthereumTransactionTag {
/// Account that has locked funds. /// Account that has locked funds.
pub account: [u8; 20], pub account: [u8; 20],
@@ -65,7 +67,7 @@ pub struct EthereumTransactionTag {
pub nonce: sp_core::U256, pub nonce: sp_core::U256,
} }
/// Eth transaction from runtime perspective. /// Ethereum transaction from runtime perspective.
pub struct EthTransaction; pub struct EthTransaction;
impl MaybeLockFundsTransaction for EthTransaction { impl MaybeLockFundsTransaction for EthTransaction {
@@ -87,7 +89,7 @@ impl MaybeLockFundsTransaction for EthTransaction {
tx.unsigned.to, tx.unsigned.to,
); );
return Err(ExchangeError::InvalidTransaction); return Err(ExchangeError::InvalidTransaction)
} }
let mut recipient_raw = sp_core::H256::default(); let mut recipient_raw = sp_core::H256::default();
@@ -100,8 +102,8 @@ impl MaybeLockFundsTransaction for EthTransaction {
len, len,
); );
return Err(ExchangeError::InvalidRecipient); return Err(ExchangeError::InvalidRecipient)
} },
} }
let amount = tx.unsigned.value.low_u128(); let amount = tx.unsigned.value.low_u128();
@@ -112,7 +114,7 @@ impl MaybeLockFundsTransaction for EthTransaction {
tx.unsigned.value, tx.unsigned.value,
); );
return Err(ExchangeError::InvalidAmount); return Err(ExchangeError::InvalidAmount)
} }
Ok(LockFundsTransaction { Ok(LockFundsTransaction {
@@ -128,7 +130,7 @@ impl MaybeLockFundsTransaction for EthTransaction {
/// Prepares everything required to bench claim of funds locked by given transaction. /// Prepares everything required to bench claim of funds locked by given transaction.
#[cfg(feature = "runtime-benchmarks")] #[cfg(feature = "runtime-benchmarks")]
pub(crate) fn prepare_environment_for_claim<T: pallet_bridge_eth_poa::Config<I>, I: frame_support::traits::Instance>( pub(crate) fn prepare_environment_for_claim<T: pallet_bridge_eth_poa::Config<I>, I: 'static>(
transactions: &[(RawTransaction, RawTransactionReceipt)], transactions: &[(RawTransaction, RawTransactionReceipt)],
) -> bp_eth_poa::H256 { ) -> bp_eth_poa::H256 {
use bp_eth_poa::compute_merkle_root; use bp_eth_poa::compute_merkle_root;
@@ -161,7 +163,7 @@ pub(crate) fn prepare_ethereum_transaction(
// chain id is 0x11 // chain id is 0x11
// sender secret is 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7 // sender secret is 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7
let chain_id = 0x11; let chain_id = 0x11;
let signer = secp256k1::SecretKey::parse(&hex!( let signer = libsecp256k1::SecretKey::parse(&hex!(
"4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7" "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7"
)) ))
.unwrap(); .unwrap();
@@ -213,10 +215,7 @@ mod tests {
#[test] #[test]
fn invalid_transaction_rejected() { fn invalid_transaction_rejected() {
assert_eq!( assert_eq!(EthTransaction::parse(&Vec::new()), Err(ExchangeError::InvalidTransaction),);
EthTransaction::parse(&Vec::new()),
Err(ExchangeError::InvalidTransaction),
);
} }
#[test] #[test]
@@ -21,8 +21,8 @@ use bp_header_chain::InclusionProofVerifier;
use frame_support::RuntimeDebug; use frame_support::RuntimeDebug;
use hex_literal::hex; use hex_literal::hex;
use pallet_bridge_eth_poa::{ use pallet_bridge_eth_poa::{
AuraConfiguration, ChainTime as TChainTime, PruningStrategy as BridgePruningStrategy, ValidatorsConfiguration, AuraConfiguration, ChainTime as TChainTime, PruningStrategy as BridgePruningStrategy,
ValidatorsSource, ValidatorsConfiguration, ValidatorsSource,
}; };
use sp_std::prelude::*; use sp_std::prelude::*;
@@ -34,8 +34,8 @@ frame_support::parameter_types! {
kovan_validators_configuration(); kovan_validators_configuration();
} }
/// Max number of finalized headers to keep. It is equivalent of approximately /// Max number of finalized headers to keep. It is equivalent of around 24 hours of
/// 24 hours of finalized blocks on current Kovan chain. /// finalized blocks on current Kovan chain.
const FINALIZED_HEADERS_TO_KEEP: u64 = 20_000; const FINALIZED_HEADERS_TO_KEEP: u64 = 20_000;
/// Aura engine configuration for Kovan chain. /// Aura engine configuration for Kovan chain.
@@ -102,11 +102,14 @@ pub fn genesis_header() -> AuraHeader {
timestamp: 0, timestamp: 0,
number: 0, number: 0,
author: Default::default(), author: Default::default(),
transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), .into(),
uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
.into(),
extra_data: vec![], extra_data: vec![],
state_root: hex!("2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2").into(), state_root: hex!("2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2").into(),
receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
.into(),
log_bloom: Default::default(), log_bloom: Default::default(),
gas_used: Default::default(), gas_used: Default::default(),
gas_limit: 6000000.into(), gas_limit: 6000000.into(),
@@ -114,8 +117,9 @@ pub fn genesis_header() -> AuraHeader {
seal: vec![ seal: vec![
vec![128], vec![128],
vec![ vec![
184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
], ],
], ],
} }
@@ -153,12 +157,17 @@ impl InclusionProofVerifier for KovanBlockchain {
type Transaction = RawTransaction; type Transaction = RawTransaction;
type TransactionInclusionProof = EthereumTransactionInclusionProof; type TransactionInclusionProof = EthereumTransactionInclusionProof;
fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option<Self::Transaction> { fn verify_transaction_inclusion_proof(
let is_transaction_finalized = proof: &Self::TransactionInclusionProof,
crate::BridgeKovan::verify_transaction_finalized(proof.block, proof.index, &proof.proof); ) -> Option<Self::Transaction> {
let is_transaction_finalized = crate::BridgeKovan::verify_transaction_finalized(
proof.block,
proof.index,
&proof.proof,
);
if !is_transaction_finalized { if !is_transaction_finalized {
return None; return None
} }
proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone()) proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone())
+288 -82
View File
@@ -36,6 +36,7 @@ pub mod exchange;
pub mod benches; pub mod benches;
pub mod kovan; pub mod kovan;
pub mod millau_messages; pub mod millau_messages;
pub mod parachains;
pub mod rialto_poa; pub mod rialto_poa;
use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge};
@@ -43,21 +44,20 @@ use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge};
use bridge_runtime_common::messages::{ use bridge_runtime_common::messages::{
source::estimate_message_dispatch_and_delivery_fee, MessageBridge, source::estimate_message_dispatch_and_delivery_fee, MessageBridge,
}; };
use codec::Decode;
use pallet_grandpa::{ use pallet_grandpa::{
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
}; };
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo};
use sp_api::impl_runtime_apis; use sp_api::impl_runtime_apis;
use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{ use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys, create_runtime_str, generic, impl_opaque_keys,
traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys}, traits::{AccountIdLookup, Block as BlockT, NumberFor, OpaqueKeys},
transaction_validity::{TransactionSource, TransactionValidity}, transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, MultiSignature, MultiSigner, ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill,
}; };
use sp_std::prelude::*; use sp_std::{collections::btree_map::BTreeMap, prelude::*};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use sp_version::NativeVersion; use sp_version::NativeVersion;
use sp_version::RuntimeVersion; use sp_version::RuntimeVersion;
@@ -101,7 +101,7 @@ pub type AccountIndex = u32;
pub type Balance = bp_rialto::Balance; pub type Balance = bp_rialto::Balance;
/// Index of a transaction in the chain. /// Index of a transaction in the chain.
pub type Index = u32; pub type Index = bp_rialto::Index;
/// A hash of some data used by the chain. /// A hash of some data used by the chain.
pub type Hash = bp_rialto::Hash; pub type Hash = bp_rialto::Hash;
@@ -131,8 +131,11 @@ pub mod opaque {
impl_opaque_keys! { impl_opaque_keys! {
pub struct SessionKeys { pub struct SessionKeys {
pub aura: Aura, pub babe: Babe,
pub grandpa: Grandpa, pub grandpa: Grandpa,
pub para_validator: Initializer,
pub para_assignment: SessionInfo,
pub authority_discovery: AuthorityDiscovery,
} }
} }
@@ -171,7 +174,7 @@ impl frame_system::Config for Runtime {
/// The aggregated dispatch type that is available for extrinsics. /// The aggregated dispatch type that is available for extrinsics.
type Call = Call; type Call = Call;
/// The lookup mechanism to get account ID from whatever is passed in dispatchers. /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
type Lookup = IdentityLookup<AccountId>; type Lookup = AccountIdLookup<AccountId, ()>;
/// The index type for storing how many extrinsics an account has signed. /// The index type for storing how many extrinsics an account has signed.
type Index = Index; type Index = Index;
/// The index type for blocks. /// The index type for blocks.
@@ -213,15 +216,41 @@ impl frame_system::Config for Runtime {
type OnSetCode = (); type OnSetCode = ();
} }
impl pallet_randomness_collective_flip::Config for Runtime {} /// The BABE epoch configuration at genesis.
pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration =
sp_consensus_babe::BabeEpochConfiguration {
c: bp_rialto::time_units::PRIMARY_PROBABILITY,
allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryVRFSlots,
};
parameter_types! { parameter_types! {
pub const EpochDuration: u64 = bp_rialto::EPOCH_DURATION_IN_SLOTS as u64;
pub const ExpectedBlockTime: bp_rialto::Moment = bp_rialto::time_units::MILLISECS_PER_BLOCK;
pub const MaxAuthorities: u32 = 10; pub const MaxAuthorities: u32 = 10;
} }
impl pallet_aura::Config for Runtime { impl pallet_babe::Config for Runtime {
type AuthorityId = AuraId; type EpochDuration = EpochDuration;
type ExpectedBlockTime = ExpectedBlockTime;
type MaxAuthorities = MaxAuthorities; type MaxAuthorities = MaxAuthorities;
// session module is the trigger
type EpochChangeTrigger = pallet_babe::ExternalTrigger;
// equivocation related configuration - we don't expect any equivocations in our testnets
type KeyOwnerProofSystem = ();
type KeyOwnerProof = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(
KeyTypeId,
pallet_babe::AuthorityId,
)>>::Proof;
type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(
KeyTypeId,
pallet_babe::AuthorityId,
)>>::IdentificationTuple;
type HandleEquivocation = ();
type DisabledValidators = ();
type WeightInfo = ();
} }
type RialtoPoA = pallet_bridge_eth_poa::Instance1; type RialtoPoA = pallet_bridge_eth_poa::Instance1;
@@ -268,7 +297,7 @@ impl pallet_bridge_currency_exchange::Config<KovanCurrencyExchange> for Runtime
impl pallet_bridge_dispatch::Config for Runtime { impl pallet_bridge_dispatch::Config for Runtime {
type Event = Event; type Event = Event;
type MessageId = (bp_messages::LaneId, bp_messages::MessageNonce); type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce);
type Call = Call; type Call = Call;
type CallFilter = frame_support::traits::Everything; type CallFilter = frame_support::traits::Everything;
type EncodedCall = crate::millau_messages::FromMillauEncodedCall; type EncodedCall = crate::millau_messages::FromMillauEncodedCall;
@@ -288,14 +317,14 @@ impl bp_currency_exchange::DepositInto for DepositInto {
recipient: Self::Recipient, recipient: Self::Recipient,
amount: Self::Amount, amount: Self::Amount,
) -> bp_currency_exchange::Result<()> { ) -> bp_currency_exchange::Result<()> {
// let balances module make all checks for us (it won't allow depositing lower than existential // let balances module make all checks for us (it won't allow depositing lower than
// deposit, balance overflow, ...) // existential deposit, balance overflow, ...)
let deposited = <pallet_balances::Pallet<Runtime> as Currency<AccountId>>::deposit_creating( let deposited = <pallet_balances::Pallet<Runtime> as Currency<AccountId>>::deposit_creating(
&recipient, amount, &recipient, amount,
); );
// I'm dropping deposited here explicitly to illustrate the fact that it'll update `TotalIssuance` // I'm dropping deposited here explicitly to illustrate the fact that it'll update
// on drop // `TotalIssuance` on drop
let deposited_amount = deposited.peek(); let deposited_amount = deposited.peek();
drop(deposited); drop(deposited);
@@ -343,6 +372,7 @@ impl bp_currency_exchange::DepositInto for DepositInto {
impl pallet_grandpa::Config for Runtime { impl pallet_grandpa::Config for Runtime {
type Event = Event; type Event = Event;
type Call = Call; type Call = Call;
type MaxAuthorities = MaxAuthorities;
type KeyOwnerProofSystem = (); type KeyOwnerProofSystem = ();
type KeyOwnerProof = type KeyOwnerProof =
<Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof; <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;
@@ -361,9 +391,9 @@ parameter_types! {
} }
impl pallet_timestamp::Config for Runtime { impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the Unix epoch. /// A timestamp: milliseconds since the UNIX epoch.
type Moment = u64; type Moment = bp_rialto::Moment;
type OnTimestampSet = Aura; type OnTimestampSet = Babe;
type MinimumPeriod = MinimumPeriod; type MinimumPeriod = MinimumPeriod;
// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
type WeightInfo = (); type WeightInfo = ();
@@ -395,13 +425,25 @@ impl pallet_balances::Config for Runtime {
parameter_types! { parameter_types! {
pub const TransactionBaseFee: Balance = 0; pub const TransactionBaseFee: Balance = 0;
pub const TransactionByteFee: Balance = 1; pub const TransactionByteFee: Balance = 1;
pub const OperationalFeeMultiplier: u8 = 5;
// values for following parameters are copied from polkadot repo, but it is fine
// not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains
pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25);
pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000);
pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128);
} }
impl pallet_transaction_payment::Config for Runtime { impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, ()>; type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, ()>;
type TransactionByteFee = TransactionByteFee; type TransactionByteFee = TransactionByteFee;
type WeightToFee = IdentityFee<Balance>; type OperationalFeeMultiplier = OperationalFeeMultiplier;
type FeeMultiplierUpdate = (); type WeightToFee = bp_rialto::WeightToFee;
type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment<
Runtime,
TargetBlockFullness,
AdjustmentVariable,
MinimumMultiplier,
>;
} }
impl pallet_sudo::Config for Runtime { impl pallet_sudo::Config for Runtime {
@@ -409,17 +451,12 @@ impl pallet_sudo::Config for Runtime {
type Call = Call; type Call = Call;
} }
parameter_types! {
pub const Period: BlockNumber = bp_rialto::SESSION_LENGTH;
pub const Offset: BlockNumber = 0;
}
impl pallet_session::Config for Runtime { impl pallet_session::Config for Runtime {
type Event = Event; type Event = Event;
type ValidatorId = <Self as frame_system::Config>::AccountId; type ValidatorId = <Self as frame_system::Config>::AccountId;
type ValidatorIdOf = (); type ValidatorIdOf = ();
type ShouldEndSession = pallet_session::PeriodicSessions<Period, Offset>; type ShouldEndSession = Babe;
type NextSessionRotation = pallet_session::PeriodicSessions<Period, Offset>; type NextSessionRotation = Babe;
type SessionManager = pallet_shift_session_manager::Pallet<Runtime>; type SessionManager = pallet_shift_session_manager::Pallet<Runtime>;
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders; type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys; type Keys = SessionKeys;
@@ -427,6 +464,10 @@ impl pallet_session::Config for Runtime {
type WeightInfo = (); type WeightInfo = ();
} }
impl pallet_authority_discovery::Config for Runtime {
type MaxAuthorities = MaxAuthorities;
}
parameter_types! { parameter_types! {
/// This is a pretty unscientific cap. /// This is a pretty unscientific cap.
/// ///
@@ -475,10 +516,11 @@ parameter_types! {
pub const GetDeliveryConfirmationTransactionFee: Balance = pub const GetDeliveryConfirmationTransactionFee: Balance =
bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _;
pub const RootAccountForPayments: Option<AccountId> = None; pub const RootAccountForPayments: Option<AccountId> = None;
pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID;
} }
/// Instance of the messages pallet used to relay messages to/from Millau chain. /// Instance of the messages pallet used to relay messages to/from Millau chain.
pub type WithMillauMessagesInstance = pallet_bridge_messages::DefaultInstance; pub type WithMillauMessagesInstance = ();
impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime { impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
type Event = Event; type Event = Event;
@@ -502,14 +544,17 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
type MessageDeliveryAndDispatchPayment = type MessageDeliveryAndDispatchPayment =
pallet_bridge_messages::instant_payments::InstantCurrencyPayments< pallet_bridge_messages::instant_payments::InstantCurrencyPayments<
Runtime, Runtime,
(),
pallet_balances::Pallet<Runtime>, pallet_balances::Pallet<Runtime>,
GetDeliveryConfirmationTransactionFee, GetDeliveryConfirmationTransactionFee,
RootAccountForPayments, RootAccountForPayments,
>; >;
type OnMessageAccepted = ();
type OnDeliveryConfirmed = (); type OnDeliveryConfirmed = ();
type SourceHeaderChain = crate::millau_messages::Millau; type SourceHeaderChain = crate::millau_messages::Millau;
type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch;
type BridgedChainId = BridgedChainId;
} }
construct_runtime!( construct_runtime!(
@@ -518,28 +563,56 @@ construct_runtime!(
NodeBlock = opaque::Block, NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic UncheckedExtrinsic = UncheckedExtrinsic
{ {
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>},
// Must be before session.
Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
TransactionPayment: pallet_transaction_payment::{Pallet, Storage},
// Consensus support.
AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config},
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>},
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event},
ShiftSessionManager: pallet_shift_session_manager::{Pallet},
// Eth-PoA chains bridge modules.
BridgeRialtoPoa: pallet_bridge_eth_poa::<Instance1>::{Pallet, Call, Config, Storage, ValidateUnsigned}, BridgeRialtoPoa: pallet_bridge_eth_poa::<Instance1>::{Pallet, Call, Config, Storage, ValidateUnsigned},
BridgeKovan: pallet_bridge_eth_poa::<Instance2>::{Pallet, Call, Config, Storage, ValidateUnsigned}, BridgeKovan: pallet_bridge_eth_poa::<Instance2>::{Pallet, Call, Config, Storage, ValidateUnsigned},
BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::<Instance1>::{Pallet, Call}, BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::<Instance1>::{Pallet, Call},
BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::<Instance2>::{Pallet, Call}, BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::<Instance2>::{Pallet, Call},
// Millau bridge modules.
BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event<T>}, BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event<T>},
BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>}, BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>, Config<T>},
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, // Parachain modules.
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, ParachainsOrigin: polkadot_runtime_parachains::origin::{Pallet, Origin},
Aura: pallet_aura::{Pallet, Config<T>}, Configuration: polkadot_runtime_parachains::configuration::{Pallet, Call, Storage, Config<T>},
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, Shared: polkadot_runtime_parachains::shared::{Pallet, Call, Storage},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>}, Inclusion: polkadot_runtime_parachains::inclusion::{Pallet, Call, Storage, Event<T>},
TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, ParasInherent: polkadot_runtime_parachains::paras_inherent::{Pallet, Call, Storage, Inherent},
Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>}, Scheduler: polkadot_runtime_parachains::scheduler::{Pallet, Storage},
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>}, Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config},
ShiftSessionManager: pallet_shift_session_manager::{Pallet}, Initializer: polkadot_runtime_parachains::initializer::{Pallet, Call, Storage},
Dmp: polkadot_runtime_parachains::dmp::{Pallet, Call, Storage},
Ump: polkadot_runtime_parachains::ump::{Pallet, Call, Storage, Event},
Hrmp: polkadot_runtime_parachains::hrmp::{Pallet, Call, Storage, Event<T>, Config},
SessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage},
// Parachain Onboarding Pallets
Registrar: polkadot_runtime_common::paras_registrar::{Pallet, Call, Storage, Event<T>},
Slots: polkadot_runtime_common::slots::{Pallet, Call, Storage, Event<T>},
ParasSudoWrapper: polkadot_runtime_common::paras_sudo_wrapper::{Pallet, Call},
} }
); );
/// The address format for describing accounts. /// The address format for describing accounts.
pub type Address = AccountId; pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
/// Block header type as expected by this runtime. /// Block header type as expected by this runtime.
pub type Header = generic::Header<BlockNumber, Hashing>; pub type Header = generic::Header<BlockNumber, Hashing>;
/// Block type as expected by this runtime. /// Block type as expected by this runtime.
@@ -570,7 +643,7 @@ pub type Executive = frame_executive::Executive<
Block, Block,
frame_system::ChainContext<Runtime>, frame_system::ChainContext<Runtime>,
Runtime, Runtime,
AllPalletsWithSystem, AllPallets,
>; >;
impl_runtime_apis! { impl_runtime_apis! {
@@ -700,13 +773,145 @@ impl_runtime_apis! {
} }
} }
impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime { impl sp_consensus_babe::BabeApi<Block> for Runtime {
fn slot_duration() -> sp_consensus_aura::SlotDuration { fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration {
sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) // The choice of `c` parameter (where `1 - c` represents the
// probability of a slot being empty), is done in accordance to the
// slot duration and expected target block time, for safely
// resisting network delays of maximum two seconds.
// <https://research.web3.foundation/en/latest/polkadot/BABE/Babe/#6-practical-results>
sp_consensus_babe::BabeGenesisConfiguration {
slot_duration: Babe::slot_duration(),
epoch_length: EpochDuration::get(),
c: BABE_GENESIS_EPOCH_CONFIG.c,
genesis_authorities: Babe::authorities().to_vec(),
randomness: Babe::randomness(),
allowed_slots: BABE_GENESIS_EPOCH_CONFIG.allowed_slots,
}
} }
fn authorities() -> Vec<AuraId> { fn current_epoch_start() -> sp_consensus_babe::Slot {
Aura::authorities() Babe::current_epoch_start()
}
fn current_epoch() -> sp_consensus_babe::Epoch {
Babe::current_epoch()
}
fn next_epoch() -> sp_consensus_babe::Epoch {
Babe::next_epoch()
}
fn generate_key_ownership_proof(
_slot: sp_consensus_babe::Slot,
_authority_id: sp_consensus_babe::AuthorityId,
) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
None
}
fn submit_report_equivocation_unsigned_extrinsic(
equivocation_proof: sp_consensus_babe::EquivocationProof<<Block as BlockT>::Header>,
key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof,
) -> Option<()> {
let key_owner_proof = key_owner_proof.decode()?;
Babe::submit_unsigned_equivocation_report(
equivocation_proof,
key_owner_proof,
)
}
}
impl polkadot_primitives::v1::ParachainHost<Block, Hash, BlockNumber> for Runtime {
fn validators() -> Vec<polkadot_primitives::v1::ValidatorId> {
polkadot_runtime_parachains::runtime_api_impl::v1::validators::<Runtime>()
}
fn validator_groups() -> (
Vec<Vec<polkadot_primitives::v1::ValidatorIndex>>,
polkadot_primitives::v1::GroupRotationInfo<BlockNumber>,
) {
polkadot_runtime_parachains::runtime_api_impl::v1::validator_groups::<Runtime>()
}
fn availability_cores() -> Vec<polkadot_primitives::v1::CoreState<Hash, BlockNumber>> {
polkadot_runtime_parachains::runtime_api_impl::v1::availability_cores::<Runtime>()
}
fn persisted_validation_data(
para_id: polkadot_primitives::v1::Id,
assumption: polkadot_primitives::v1::OccupiedCoreAssumption,
)
-> Option<polkadot_primitives::v1::PersistedValidationData<Hash, BlockNumber>> {
polkadot_runtime_parachains::runtime_api_impl::v1::persisted_validation_data::<Runtime>(para_id, assumption)
}
fn check_validation_outputs(
para_id: polkadot_primitives::v1::Id,
outputs: polkadot_primitives::v1::CandidateCommitments,
) -> bool {
polkadot_runtime_parachains::runtime_api_impl::v1::check_validation_outputs::<Runtime>(para_id, outputs)
}
fn session_index_for_child() -> polkadot_primitives::v1::SessionIndex {
polkadot_runtime_parachains::runtime_api_impl::v1::session_index_for_child::<Runtime>()
}
fn validation_code(
para_id: polkadot_primitives::v1::Id,
assumption: polkadot_primitives::v1::OccupiedCoreAssumption,
)
-> Option<polkadot_primitives::v1::ValidationCode> {
polkadot_runtime_parachains::runtime_api_impl::v1::validation_code::<Runtime>(para_id, assumption)
}
fn candidate_pending_availability(
para_id: polkadot_primitives::v1::Id,
) -> Option<polkadot_primitives::v1::CommittedCandidateReceipt<Hash>> {
polkadot_runtime_parachains::runtime_api_impl::v1::candidate_pending_availability::<Runtime>(para_id)
}
fn candidate_events() -> Vec<polkadot_primitives::v1::CandidateEvent<Hash>> {
polkadot_runtime_parachains::runtime_api_impl::v1::candidate_events::<Runtime, _>(|ev| {
match ev {
Event::Inclusion(ev) => {
Some(ev)
}
_ => None,
}
})
}
fn session_info(index: polkadot_primitives::v1::SessionIndex) -> Option<polkadot_primitives::v1::SessionInfo> {
polkadot_runtime_parachains::runtime_api_impl::v1::session_info::<Runtime>(index)
}
fn dmq_contents(
recipient: polkadot_primitives::v1::Id,
) -> Vec<polkadot_primitives::v1::InboundDownwardMessage<BlockNumber>> {
polkadot_runtime_parachains::runtime_api_impl::v1::dmq_contents::<Runtime>(recipient)
}
fn inbound_hrmp_channels_contents(
recipient: polkadot_primitives::v1::Id
) -> BTreeMap<polkadot_primitives::v1::Id, Vec<polkadot_primitives::v1::InboundHrmpMessage<BlockNumber>>> {
polkadot_runtime_parachains::runtime_api_impl::v1::inbound_hrmp_channels_contents::<Runtime>(recipient)
}
fn validation_code_by_hash(
hash: polkadot_primitives::v1::ValidationCodeHash,
) -> Option<polkadot_primitives::v1::ValidationCode> {
polkadot_runtime_parachains::runtime_api_impl::v1::validation_code_by_hash::<Runtime>(hash)
}
fn on_chain_votes() -> Option<polkadot_primitives::v1::ScrapedOnChainVotes<Hash>> {
polkadot_runtime_parachains::runtime_api_impl::v1::on_chain_votes::<Runtime>()
}
}
impl sp_authority_discovery::AuthorityDiscoveryApi<Block> for Runtime {
fn authorities() -> Vec<AuthorityDiscoveryId> {
polkadot_runtime_parachains::runtime_api_impl::v1::relevant_authority_ids::<Runtime>()
} }
} }
@@ -735,6 +940,10 @@ impl_runtime_apis! {
} }
impl fg_primitives::GrandpaApi<Block> for Runtime { impl fg_primitives::GrandpaApi<Block> for Runtime {
fn current_set_id() -> fg_primitives::SetId {
Grandpa::current_set_id()
}
fn grandpa_authorities() -> GrandpaAuthorityList { fn grandpa_authorities() -> GrandpaAuthorityList {
Grandpa::grandpa_authorities() Grandpa::grandpa_authorities()
} }
@@ -781,20 +990,11 @@ impl_runtime_apis! {
begin: bp_messages::MessageNonce, begin: bp_messages::MessageNonce,
end: bp_messages::MessageNonce, end: bp_messages::MessageNonce,
) -> Vec<bp_messages::MessageDetails<Balance>> { ) -> Vec<bp_messages::MessageDetails<Balance>> {
(begin..=end).filter_map(|nonce| { bridge_runtime_common::messages_api::outbound_message_details::<
let message_data = BridgeMillauMessages::outbound_message_data(lane, nonce)?; Runtime,
let decoded_payload = millau_messages::ToMillauMessagePayload::decode( WithMillauMessagesInstance,
&mut &message_data.payload[..] WithMillauMessageBridge,
).ok()?; >(lane, begin, end)
Some(bp_messages::MessageDetails {
nonce,
dispatch_weight: decoded_payload.weight,
size: message_data.payload.len() as _,
delivery_and_dispatch_fee: message_data.fee,
dispatch_fee_payment: decoded_payload.dispatch_fee_payment,
})
})
.collect()
} }
fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce {
@@ -829,18 +1029,18 @@ impl_runtime_apis! {
use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};
use frame_support::traits::StorageInfoTrait; use frame_support::traits::StorageInfoTrait;
use pallet_bridge_currency_exchange::benchmarking::Pallet as BridgeCurrencyExchangeBench;
use pallet_bridge_messages::benchmarking::Pallet as MessagesBench;
let mut list = Vec::<BenchmarkList>::new();
list_benchmark!(list, extra, pallet_bridge_eth_poa, BridgeRialtoPoa);
list_benchmark!( list_benchmark!(
list, list,
extra, extra,
pallet_bridge_currency_exchange, pallet_bridge_currency_exchange, BridgeCurrencyExchangeBench::<Runtime, KovanCurrencyExchange>
BridgeCurrencyExchangeBench::<Runtime, KovanCurrencyExchange>
);
list_benchmark!(
list,
extra,
pallet_bridge_messages,
MessagesBench::<Runtime, WithMillauMessagesInstance>
); );
list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::<Runtime, WithMillauMessagesInstance>);
list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeMillauGrandpa); list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeMillauGrandpa);
let storage_info = AllPalletsWithSystem::storage_info(); let storage_info = AllPalletsWithSystem::storage_info();
@@ -981,7 +1181,7 @@ impl_runtime_apis! {
MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _], MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _],
_ => vec![], _ => vec![],
}; };
let call = Call::System(SystemCall::remark(remark)); let call = Call::System(SystemCall::remark { remark });
let call_weight = call.get_dispatch_info().weight; let call_weight = call.get_dispatch_info().weight;
let millau_account_id: bp_millau::AccountId = Default::default(); let millau_account_id: bp_millau::AccountId = Default::default();
@@ -1001,14 +1201,12 @@ impl_runtime_apis! {
Self::endow_account(&rialto_public.clone().into_account()); Self::endow_account(&rialto_public.clone().into_account());
} }
let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key::< let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key(
<WithMillauMessageBridge as MessageBridge>::BridgedMessagesInstance, <WithMillauMessageBridge as MessageBridge>::BRIDGED_MESSAGES_PALLET_NAME,
>(
&message_key.lane_id, message_key.nonce, &message_key.lane_id, message_key.nonce,
).0; ).0;
let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key::< let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key(
<WithMillauMessageBridge as MessageBridge>::BridgedMessagesInstance, <WithMillauMessageBridge as MessageBridge>::BRIDGED_MESSAGES_PALLET_NAME,
>(
&lane_id, &lane_id,
).0; ).0;
@@ -1054,9 +1252,8 @@ impl_runtime_apis! {
prepare_message_delivery_proof::<WithMillauMessageBridge, bp_millau::Hasher, Runtime, (), _, _>( prepare_message_delivery_proof::<WithMillauMessageBridge, bp_millau::Hasher, Runtime, (), _, _>(
params, params,
|lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key::< |lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key(
<WithMillauMessageBridge as MessageBridge>::BridgedMessagesInstance, <WithMillauMessageBridge as MessageBridge>::BRIDGED_MESSAGES_PALLET_NAME,
>(
&lane_id, &lane_id,
).0, ).0,
|state_root| bp_millau::Header::new( |state_root| bp_millau::Header::new(
@@ -1082,6 +1279,7 @@ impl_runtime_apis! {
} }
} }
add_benchmark!(params, batches, pallet_bridge_eth_poa, BridgeRialtoPoa);
add_benchmark!( add_benchmark!(
params, params,
batches, batches,
@@ -1105,8 +1303,8 @@ impl_runtime_apis! {
/// Millau account ownership digest from Rialto. /// Millau account ownership digest from Rialto.
/// ///
/// The byte vector returned by this function should be signed with a Millau account private key. /// The byte vector returned by this function should be signed with a Millau account private key.
/// This way, the owner of `rialto_account_id` on Rialto proves that the Millau account private key /// This way, the owner of `rialto_account_id` on Rialto proves that the 'millau' account private
/// is also under his control. /// key is also under his control.
pub fn rialto_to_millau_account_ownership_digest<Call, AccountId, SpecVersion>( pub fn rialto_to_millau_account_ownership_digest<Call, AccountId, SpecVersion>(
millau_call: &Call, millau_call: &Call,
rialto_account_id: AccountId, rialto_account_id: AccountId,
@@ -1180,6 +1378,7 @@ mod tests {
bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT,
bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT, bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT,
DbWeight::get(),
); );
let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add(
@@ -1207,6 +1406,7 @@ mod tests {
max_incoming_inbound_lane_data_proof_size, max_incoming_inbound_lane_data_proof_size,
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
DbWeight::get(),
); );
} }
@@ -1253,4 +1453,10 @@ mod tests {
additional_amount additional_amount
}); });
} }
#[test]
fn call_size() {
const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests
assert!(core::mem::size_of::<Call>() <= MAX_CALL_SIZE);
}
} }
@@ -31,25 +31,34 @@ use frame_support::{
weights::{DispatchClass, Weight}, weights::{DispatchClass, Weight},
RuntimeDebug, RuntimeDebug,
}; };
use sp_runtime::{traits::Zero, FixedPointNumber, FixedU128}; use scale_info::TypeInfo;
use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128};
use sp_std::{convert::TryFrom, ops::RangeInclusive}; use sp_std::{convert::TryFrom, ops::RangeInclusive};
/// Initial value of `MillauToRialtoConversionRate` parameter. /// Initial value of `MillauToRialtoConversionRate` parameter.
pub const INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV); pub const INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE: FixedU128 =
FixedU128::from_inner(FixedU128::DIV);
/// Initial value of `MillauFeeMultiplier` parameter.
pub const INITIAL_MILLAU_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV);
parameter_types! { parameter_types! {
/// Millau to Rialto conversion rate. Initially we treat both tokens as equal. /// Millau to Rialto conversion rate. Initially we treat both tokens as equal.
pub storage MillauToRialtoConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE; pub storage MillauToRialtoConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE;
/// Fee multiplier value at Millau chain.
pub storage MillauFeeMultiplier: FixedU128 = INITIAL_MILLAU_FEE_MULTIPLIER;
} }
/// Message payload for Rialto -> Millau messages. /// Message payload for Rialto -> Millau messages.
pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload<WithMillauMessageBridge>; pub type ToMillauMessagePayload =
messages::source::FromThisChainMessagePayload<WithMillauMessageBridge>;
/// Message verifier for Rialto -> Millau messages. /// Message verifier for Rialto -> Millau messages.
pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier<WithMillauMessageBridge>; pub type ToMillauMessageVerifier =
messages::source::FromThisChainMessageVerifier<WithMillauMessageBridge>;
/// Message payload for Millau -> Rialto messages. /// Message payload for Millau -> Rialto messages.
pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload<WithMillauMessageBridge>; pub type FromMillauMessagePayload =
messages::target::FromBridgedChainMessagePayload<WithMillauMessageBridge>;
/// Encoded Rialto Call as it comes from Millau. /// Encoded Rialto Call as it comes from Millau.
pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessageCall<crate::Call>; pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessageCall<crate::Call>;
@@ -59,14 +68,15 @@ pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDi
WithMillauMessageBridge, WithMillauMessageBridge,
crate::Runtime, crate::Runtime,
pallet_balances::Pallet<Runtime>, pallet_balances::Pallet<Runtime>,
pallet_bridge_dispatch::DefaultInstance, (),
>; >;
/// Messages proof for Millau -> Rialto messages. /// Messages proof for Millau -> Rialto messages.
pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_millau::Hash>; pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_millau::Hash>;
/// Messages delivery proof for Rialto -> Millau messages. /// Messages delivery proof for Rialto -> Millau messages.
pub type ToMillauMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof<bp_millau::Hash>; pub type ToMillauMessagesDeliveryProof =
messages::source::FromBridgedChainMessagesDeliveryProof<bp_millau::Hash>;
/// Millau <-> Rialto message bridge. /// Millau <-> Rialto message bridge.
#[derive(RuntimeDebug, Clone, Copy)] #[derive(RuntimeDebug, Clone, Copy)]
@@ -76,13 +86,15 @@ impl MessageBridge for WithMillauMessageBridge {
const RELAYER_FEE_PERCENT: u32 = 10; const RELAYER_FEE_PERCENT: u32 = 10;
const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID;
const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID;
const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME;
type ThisChain = Rialto; type ThisChain = Rialto;
type BridgedChain = Millau; type BridgedChain = Millau;
type BridgedMessagesInstance = crate::WithMillauMessagesInstance;
fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance { fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance {
bp_rialto::Balance::try_from(MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance)) bp_rialto::Balance::try_from(
MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance),
)
.unwrap_or(bp_rialto::Balance::MAX) .unwrap_or(bp_rialto::Balance::MAX)
} }
} }
@@ -128,11 +140,15 @@ impl messages::ThisChainWithMessages for Rialto {
} }
fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_rialto::Balance { fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_rialto::Balance {
// `transaction` may represent transaction from the future, when multiplier value will
// be larger, so let's use slightly increased value
let multiplier = FixedU128::saturating_from_rational(110, 100)
.saturating_mul(pallet_transaction_payment::Pallet::<Runtime>::next_fee_multiplier());
// in our testnets, both per-byte fee and weight-to-fee are 1:1 // in our testnets, both per-byte fee and weight-to-fee are 1:1
messages::transaction_payment( messages::transaction_payment(
bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic,
1, 1,
FixedU128::zero(), multiplier,
|weight| weight as _, |weight| weight as _,
transaction, transaction,
) )
@@ -159,12 +175,15 @@ impl messages::BridgedChainWithMessages for Millau {
fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive<Weight> { fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive<Weight> {
// we don't want to relay too large messages + keep reserve for future upgrades // we don't want to relay too large messages + keep reserve for future upgrades
let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_millau::max_extrinsic_weight()); let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(
bp_millau::max_extrinsic_weight(),
);
// we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment` function // we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment`
// function
// //
// this bridge may be used to deliver all kind of messages, so we're not making any assumptions about // this bridge may be used to deliver all kind of messages, so we're not making any
// minimal dispatch weight here // assumptions about minimal dispatch weight here
0..=upper_limit 0..=upper_limit
} }
@@ -195,11 +214,14 @@ impl messages::BridgedChainWithMessages for Millau {
} }
fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_millau::Balance { fn transaction_payment(transaction: MessageTransaction<Weight>) -> bp_millau::Balance {
// we don't have a direct access to the value of multiplier at Millau chain
// => it is a messages module parameter
let multiplier = MillauFeeMultiplier::get();
// in our testnets, both per-byte fee and weight-to-fee are 1:1 // in our testnets, both per-byte fee and weight-to-fee are 1:1
messages::transaction_payment( messages::transaction_payment(
bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic,
1, 1,
FixedU128::zero(), multiplier,
|weight| weight as _, |weight| weight as _,
transaction, transaction,
) )
@@ -221,9 +243,11 @@ impl TargetHeaderChain<ToMillauMessagePayload, bp_millau::AccountId> for Millau
fn verify_messages_delivery_proof( fn verify_messages_delivery_proof(
proof: Self::MessagesDeliveryProof, proof: Self::MessagesDeliveryProof,
) -> Result<(LaneId, InboundLaneData<bp_rialto::AccountId>), Self::Error> { ) -> Result<(LaneId, InboundLaneData<bp_rialto::AccountId>), Self::Error> {
messages::source::verify_messages_delivery_proof::<WithMillauMessageBridge, Runtime, crate::MillauGrandpaInstance>( messages::source::verify_messages_delivery_proof::<
proof, WithMillauMessageBridge,
) Runtime,
crate::MillauGrandpaInstance,
>(proof)
} }
} }
@@ -240,15 +264,16 @@ impl SourceHeaderChain<bp_millau::Balance> for Millau {
proof: Self::MessagesProof, proof: Self::MessagesProof,
messages_count: u32, messages_count: u32,
) -> Result<ProvedMessages<Message<bp_millau::Balance>>, Self::Error> { ) -> Result<ProvedMessages<Message<bp_millau::Balance>>, Self::Error> {
messages::target::verify_messages_proof::<WithMillauMessageBridge, Runtime, crate::MillauGrandpaInstance>( messages::target::verify_messages_proof::<
proof, WithMillauMessageBridge,
messages_count, Runtime,
) crate::MillauGrandpaInstance,
>(proof, messages_count)
} }
} }
/// Rialto -> Millau message lane pallet parameters. /// Rialto -> Millau message lane pallet parameters.
#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq)] #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)]
pub enum RialtoToMillauMessagesParameter { pub enum RialtoToMillauMessagesParameter {
/// The conversion formula we use is: `RialtoTokens = MillauTokens * conversion_rate`. /// The conversion formula we use is: `RialtoTokens = MillauTokens * conversion_rate`.
MillauToRialtoConversionRate(FixedU128), MillauToRialtoConversionRate(FixedU128),
@@ -257,9 +282,8 @@ pub enum RialtoToMillauMessagesParameter {
impl MessagesParameter for RialtoToMillauMessagesParameter { impl MessagesParameter for RialtoToMillauMessagesParameter {
fn save(&self) { fn save(&self) {
match *self { match *self {
RialtoToMillauMessagesParameter::MillauToRialtoConversionRate(ref conversion_rate) => { RialtoToMillauMessagesParameter::MillauToRialtoConversionRate(ref conversion_rate) =>
MillauToRialtoConversionRate::set(conversion_rate) MillauToRialtoConversionRate::set(conversion_rate),
}
} }
} }
} }
@@ -274,7 +298,9 @@ mod tests {
MessageKey, MessageKey,
}; };
use bp_runtime::{derive_account_id, messages::DispatchFeePayment, SourceAccount}; use bp_runtime::{derive_account_id, messages::DispatchFeePayment, SourceAccount};
use bridge_runtime_common::messages::target::{FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload}; use bridge_runtime_common::messages::target::{
FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload,
};
use frame_support::{ use frame_support::{
traits::Currency, traits::Currency,
weights::{GetDispatchInfo, WeightToFeePolynomial}, weights::{GetDispatchInfo, WeightToFeePolynomial},
@@ -286,12 +312,15 @@ mod tests {
// this test actually belongs to the `bridge-runtime-common` crate, but there we have no // this test actually belongs to the `bridge-runtime-common` crate, but there we have no
// mock runtime. Making another one there just for this test, given that both crates // mock runtime. Making another one there just for this test, given that both crates
// live n single repo is an overkill // live n single repo is an overkill
let mut ext: sp_io::TestExternalities = SystemConfig::default().build_storage::<Runtime>().unwrap().into(); let mut ext: sp_io::TestExternalities =
SystemConfig::default().build_storage::<Runtime>().unwrap().into();
ext.execute_with(|| { ext.execute_with(|| {
let bridge = MILLAU_CHAIN_ID; let bridge = MILLAU_CHAIN_ID;
let call: Call = SystemCall::remark(vec![]).into(); let call: Call = SystemCall::remark { remark: vec![] }.into();
let dispatch_weight = call.get_dispatch_info().weight; let dispatch_weight = call.get_dispatch_info().weight;
let dispatch_fee = <Runtime as pallet_transaction_payment::Config>::WeightToFee::calc(&dispatch_weight); let dispatch_fee = <Runtime as pallet_transaction_payment::Config>::WeightToFee::calc(
&dispatch_weight,
);
assert!(dispatch_fee > 0); assert!(dispatch_fee > 0);
// create relayer account with minimal balance // create relayer account with minimal balance
@@ -303,12 +332,13 @@ mod tests {
); );
// create dispatch account with minimal balance + dispatch fee // create dispatch account with minimal balance + dispatch fee
let dispatch_account = derive_account_id::<<Runtime as pallet_bridge_dispatch::Config>::SourceChainAccountId>( let dispatch_account = derive_account_id::<
bridge, <Runtime as pallet_bridge_dispatch::Config>::SourceChainAccountId,
SourceAccount::Root, >(bridge, SourceAccount::Root);
);
let dispatch_account = let dispatch_account =
<Runtime as pallet_bridge_dispatch::Config>::AccountIdConverter::convert(dispatch_account); <Runtime as pallet_bridge_dispatch::Config>::AccountIdConverter::convert(
dispatch_account,
);
let _ = <pallet_balances::Pallet<Runtime> as Currency<AccountId>>::deposit_creating( let _ = <pallet_balances::Pallet<Runtime> as Currency<AccountId>>::deposit_creating(
&dispatch_account, &dispatch_account,
initial_amount + dispatch_fee, initial_amount + dispatch_fee,
@@ -318,10 +348,7 @@ mod tests {
FromMillauMessageDispatch::dispatch( FromMillauMessageDispatch::dispatch(
&relayer_account, &relayer_account,
DispatchMessage { DispatchMessage {
key: MessageKey { key: MessageKey { lane_id: Default::default(), nonce: 0 },
lane_id: Default::default(),
nonce: 0,
},
data: DispatchMessageData { data: DispatchMessageData {
payload: Ok(FromBridgedChainMessagePayload::<WithMillauMessageBridge> { payload: Ok(FromBridgedChainMessagePayload::<WithMillauMessageBridge> {
spec_version: VERSION.spec_version, spec_version: VERSION.spec_version,
@@ -337,11 +364,15 @@ mod tests {
// ensure that fee has been transferred from dispatch to relayer account // ensure that fee has been transferred from dispatch to relayer account
assert_eq!( assert_eq!(
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(&relayer_account), <pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(
&relayer_account
),
initial_amount + dispatch_fee, initial_amount + dispatch_fee,
); );
assert_eq!( assert_eq!(
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(&dispatch_account), <pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(
&dispatch_account
),
initial_amount, initial_amount,
); );
}); });
@@ -0,0 +1,158 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Parachains support in Rialto runtime.
use crate::{AccountId, Balance, Balances, BlockNumber, Event, Origin, Registrar, Runtime, Slots};
use frame_support::{parameter_types, weights::Weight};
use frame_system::EnsureRoot;
use polkadot_primitives::v1::ValidatorIndex;
use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots};
use polkadot_runtime_parachains::{
configuration as parachains_configuration, dmp as parachains_dmp, hrmp as parachains_hrmp,
inclusion as parachains_inclusion, initializer as parachains_initializer,
origin as parachains_origin, paras as parachains_paras,
paras_inherent as parachains_paras_inherent, scheduler as parachains_scheduler,
session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump,
};
/// Special `RewardValidators` that does nothing ;)
pub struct RewardValidators;
impl polkadot_runtime_parachains::inclusion::RewardValidators for RewardValidators {
fn reward_backing(_: impl IntoIterator<Item = ValidatorIndex>) {}
fn reward_bitfields(_: impl IntoIterator<Item = ValidatorIndex>) {}
}
// all required parachain modules from `polkadot-runtime-parachains` crate
impl parachains_configuration::Config for Runtime {
type WeightInfo = parachains_configuration::TestWeightInfo;
}
impl parachains_dmp::Config for Runtime {}
impl parachains_hrmp::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Currency = Balances;
}
impl parachains_inclusion::Config for Runtime {
type Event = Event;
type RewardValidators = RewardValidators;
type DisputesHandler = ();
}
impl parachains_initializer::Config for Runtime {
type Randomness = pallet_babe::RandomnessFromOneEpochAgo<Runtime>;
type ForceOrigin = EnsureRoot<AccountId>;
type WeightInfo = ();
}
impl parachains_origin::Config for Runtime {}
impl parachains_paras::Config for Runtime {
type Origin = Origin;
type Event = Event;
type WeightInfo = parachains_paras::TestWeightInfo;
}
impl parachains_paras_inherent::Config for Runtime {}
impl parachains_scheduler::Config for Runtime {}
impl parachains_session_info::Config for Runtime {}
impl parachains_shared::Config for Runtime {}
parameter_types! {
pub const FirstMessageFactorPercent: u64 = 100;
}
impl parachains_ump::Config for Runtime {
type Event = Event;
type UmpSink = ();
type FirstMessageFactorPercent = FirstMessageFactorPercent;
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
}
// required onboarding pallets. We're not going to use auctions or crowdloans, so they're missing
parameter_types! {
pub const ParaDeposit: Balance = 0;
pub const DataDepositPerByte: Balance = 0;
}
impl paras_registrar::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Currency = Balances;
type OnSwap = Slots;
type ParaDeposit = ParaDeposit;
type DataDepositPerByte = DataDepositPerByte;
type WeightInfo = paras_registrar::TestWeightInfo;
}
parameter_types! {
pub const LeasePeriod: BlockNumber = 10 * bp_rialto::MINUTES;
}
impl slots::Config for Runtime {
type Event = Event;
type Currency = Balances;
type Registrar = Registrar;
type LeasePeriod = LeasePeriod;
type WeightInfo = slots::TestWeightInfo;
type LeaseOffset = ();
}
impl paras_sudo_wrapper::Config for Runtime {}
pub struct ZeroWeights;
impl polkadot_runtime_common::paras_registrar::WeightInfo for ZeroWeights {
fn reserve() -> Weight {
0
}
fn register() -> Weight {
0
}
fn force_register() -> Weight {
0
}
fn deregister() -> Weight {
0
}
fn swap() -> Weight {
0
}
}
impl polkadot_runtime_common::slots::WeightInfo for ZeroWeights {
fn force_lease() -> Weight {
0
}
fn manage_lease_period_start(_c: u32, _t: u32) -> Weight {
0
}
fn clear_all_leases() -> Weight {
0
}
fn trigger_onboard() -> Weight {
0
}
}
@@ -23,8 +23,8 @@ use bp_header_chain::InclusionProofVerifier;
use frame_support::RuntimeDebug; use frame_support::RuntimeDebug;
use hex_literal::hex; use hex_literal::hex;
use pallet_bridge_eth_poa::{ use pallet_bridge_eth_poa::{
AuraConfiguration, ChainTime as TChainTime, PruningStrategy as TPruningStrategy, ValidatorsConfiguration, AuraConfiguration, ChainTime as TChainTime, PruningStrategy as TPruningStrategy,
ValidatorsSource, ValidatorsConfiguration, ValidatorsSource,
}; };
use sp_std::prelude::*; use sp_std::prelude::*;
@@ -79,11 +79,14 @@ pub fn genesis_header() -> AuraHeader {
timestamp: 0, timestamp: 0,
number: 0, number: 0,
author: Default::default(), author: Default::default(),
transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), .into(),
uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
.into(),
extra_data: vec![], extra_data: vec![],
state_root: hex!("a992d04c791620ed7ed96555a80cf0568355bb4bee2656f46899a4372f25f248").into(), state_root: hex!("a992d04c791620ed7ed96555a80cf0568355bb4bee2656f46899a4372f25f248").into(),
receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
.into(),
log_bloom: Default::default(), log_bloom: Default::default(),
gas_used: Default::default(), gas_used: Default::default(),
gas_limit: 0x222222.into(), gas_limit: 0x222222.into(),
@@ -128,12 +131,17 @@ impl InclusionProofVerifier for RialtoBlockchain {
type Transaction = RawTransaction; type Transaction = RawTransaction;
type TransactionInclusionProof = EthereumTransactionInclusionProof; type TransactionInclusionProof = EthereumTransactionInclusionProof;
fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option<Self::Transaction> { fn verify_transaction_inclusion_proof(
let is_transaction_finalized = proof: &Self::TransactionInclusionProof,
crate::BridgeRialtoPoa::verify_transaction_finalized(proof.block, proof.index, &proof.proof); ) -> Option<Self::Transaction> {
let is_transaction_finalized = crate::BridgeRialtoPoa::verify_transaction_finalized(
proof.block,
proof.index,
&proof.proof,
);
if !is_transaction_finalized { if !is_transaction_finalized {
return None; return None
} }
proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone()) proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone())
@@ -8,7 +8,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0" license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies] [dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] }
ed25519-dalek = { version = "1.0", default-features = false, optional = true } ed25519-dalek = { version = "1.0", default-features = false, optional = true }
hash-db = { version = "0.15.2", default-features = false } hash-db = { version = "0.15.2", default-features = false }
scale-info = { version = "1.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] }
@@ -19,4 +19,5 @@
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
pub mod messages; pub mod messages;
pub mod messages_api;
pub mod messages_benchmarking; pub mod messages_benchmarking;
@@ -32,17 +32,20 @@ use bp_runtime::{
}; };
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_support::{ use frame_support::{
traits::{Currency, ExistenceRequirement, Instance}, traits::{Currency, ExistenceRequirement},
weights::{Weight, WeightToFeePolynomial}, weights::{Weight, WeightToFeePolynomial},
RuntimeDebug, RuntimeDebug,
}; };
use hash_db::Hasher; use hash_db::Hasher;
use scale_info::TypeInfo; use scale_info::TypeInfo;
use sp_runtime::{ use sp_runtime::{
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul}, traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Saturating, Zero},
FixedPointNumber, FixedPointOperand, FixedU128, FixedPointNumber, FixedPointOperand, FixedU128,
}; };
use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, ops::RangeInclusive, vec::Vec}; use sp_std::{
cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, ops::RangeInclusive,
vec::Vec,
};
use sp_trie::StorageProof; use sp_trie::StorageProof;
/// Bidirectional message bridge. /// Bidirectional message bridge.
@@ -54,16 +57,20 @@ pub trait MessageBridge {
const THIS_CHAIN_ID: ChainId; const THIS_CHAIN_ID: ChainId;
/// Identifier of the Bridged chain. /// Identifier of the Bridged chain.
const BRIDGED_CHAIN_ID: ChainId; const BRIDGED_CHAIN_ID: ChainId;
/// Name of the paired messages pallet instance at the Bridged chain.
///
/// Should be the name that is used in the `construct_runtime!()` macro.
const BRIDGED_MESSAGES_PALLET_NAME: &'static str;
/// This chain in context of message bridge. /// This chain in context of message bridge.
type ThisChain: ThisChainWithMessages; type ThisChain: ThisChainWithMessages;
/// Bridged chain in context of message bridge. /// Bridged chain in context of message bridge.
type BridgedChain: BridgedChainWithMessages; type BridgedChain: BridgedChainWithMessages;
/// Instance of the `pallet-bridge-messages` pallet at the Bridged chain.
type BridgedMessagesInstance: Instance;
/// Convert Bridged chain balance into This chain balance. /// Convert Bridged chain balance into This chain balance.
fn bridged_balance_to_this_balance(bridged_balance: BalanceOf<BridgedChain<Self>>) -> BalanceOf<ThisChain<Self>>; fn bridged_balance_to_this_balance(
bridged_balance: BalanceOf<BridgedChain<Self>>,
) -> BalanceOf<ThisChain<Self>>;
} }
/// Chain that has `pallet-bridge-messages` and `dispatch` modules. /// Chain that has `pallet-bridge-messages` and `dispatch` modules.
@@ -73,16 +80,23 @@ pub trait ChainWithMessages {
/// Accound id on the chain. /// Accound id on the chain.
type AccountId: Encode + Decode; type AccountId: Encode + Decode;
/// Public key of the chain account that may be used to verify signatures. /// Public key of the chain account that may be used to verify signatures.
type Signer: Decode; type Signer: Encode + Decode;
/// Signature type used on the chain. /// Signature type used on the chain.
type Signature: Decode; type Signature: Encode + Decode;
/// Type of weight that is used on the chain. This would almost always be a regular /// Type of weight that is used on the chain. This would almost always be a regular
/// `frame_support::weight::Weight`. But since the meaning of weight on different chains /// `frame_support::weight::Weight`. But since the meaning of weight on different chains
/// may be different, the `WeightOf<>` construct is used to avoid confusion between /// may be different, the `WeightOf<>` construct is used to avoid confusion between
/// different weights. /// different weights.
type Weight: From<frame_support::weights::Weight> + PartialOrd; type Weight: From<frame_support::weights::Weight> + PartialOrd;
/// Type of balances that is used on the chain. /// Type of balances that is used on the chain.
type Balance: Encode + Decode + CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From<u32> + Copy; type Balance: Encode
+ Decode
+ CheckedAdd
+ CheckedDiv
+ CheckedMul
+ PartialOrd
+ From<u32>
+ Copy;
} }
/// Message related transaction parameters estimation. /// Message related transaction parameters estimation.
@@ -137,30 +151,40 @@ pub trait BridgedChainWithMessages: ChainWithMessages {
message_dispatch_weight: WeightOf<Self>, message_dispatch_weight: WeightOf<Self>,
) -> MessageTransaction<WeightOf<Self>>; ) -> MessageTransaction<WeightOf<Self>>;
/// Returns minimal transaction fee that must be paid for given transaction at the Bridged chain. /// Returns minimal transaction fee that must be paid for given transaction at the Bridged
/// chain.
fn transaction_payment(transaction: MessageTransaction<WeightOf<Self>>) -> BalanceOf<Self>; fn transaction_payment(transaction: MessageTransaction<WeightOf<Self>>) -> BalanceOf<Self>;
} }
pub(crate) type ThisChain<B> = <B as MessageBridge>::ThisChain; /// This chain in context of message bridge.
pub(crate) type BridgedChain<B> = <B as MessageBridge>::BridgedChain; pub type ThisChain<B> = <B as MessageBridge>::ThisChain;
pub(crate) type HashOf<C> = <C as ChainWithMessages>::Hash; /// Bridged chain in context of message bridge.
pub(crate) type AccountIdOf<C> = <C as ChainWithMessages>::AccountId; pub type BridgedChain<B> = <B as MessageBridge>::BridgedChain;
pub(crate) type SignerOf<C> = <C as ChainWithMessages>::Signer; /// Hash used on the chain.
pub(crate) type SignatureOf<C> = <C as ChainWithMessages>::Signature; pub type HashOf<C> = <C as ChainWithMessages>::Hash;
pub(crate) type WeightOf<C> = <C as ChainWithMessages>::Weight; /// Account id used on the chain.
pub(crate) type BalanceOf<C> = <C as ChainWithMessages>::Balance; pub type AccountIdOf<C> = <C as ChainWithMessages>::AccountId;
/// Public key of the chain account that may be used to verify signature.
pub(crate) type CallOf<C> = <C as ThisChainWithMessages>::Call; pub type SignerOf<C> = <C as ChainWithMessages>::Signer;
/// Signature type used on the chain.
pub type SignatureOf<C> = <C as ChainWithMessages>::Signature;
/// Type of weight that used on the chain.
pub type WeightOf<C> = <C as ChainWithMessages>::Weight;
/// Type of balances that is used on the chain.
pub type BalanceOf<C> = <C as ChainWithMessages>::Balance;
/// Type of call that is used on this chain.
pub type CallOf<C> = <C as ThisChainWithMessages>::Call;
/// Raw storage proof type (just raw trie nodes). /// Raw storage proof type (just raw trie nodes).
type RawStorageProof = Vec<Vec<u8>>; type RawStorageProof = Vec<Vec<u8>>;
/// Compute fee of transaction at runtime where regular transaction payment pallet is being used. /// Compute fee of transaction at runtime where regular transaction payment pallet is being used.
/// ///
/// The value of `multiplier` parameter is the expected value of `pallet_transaction_payment::NextFeeMultiplier` /// The value of `multiplier` parameter is the expected value of
/// at the moment when transaction is submitted. If you're charging this payment in advance (and that's what /// `pallet_transaction_payment::NextFeeMultiplier` at the moment when transaction is submitted. If
/// happens with delivery and confirmation transaction in this crate), then there's a chance that the actual /// you're charging this payment in advance (and that's what happens with delivery and confirmation
/// fee will be larger than what is paid in advance. So the value must be chosen carefully. /// transaction in this crate), then there's a chance that the actual fee will be larger than what
/// is paid in advance. So the value must be chosen carefully.
pub fn transaction_payment<Balance: AtLeast32BitUnsigned + FixedPointOperand>( pub fn transaction_payment<Balance: AtLeast32BitUnsigned + FixedPointOperand>(
base_extrinsic_weight: Weight, base_extrinsic_weight: Weight,
per_byte_fee: Balance, per_byte_fee: Balance,
@@ -223,7 +247,8 @@ pub mod source {
} }
/// 'Parsed' message delivery proof - inbound lane id and its state. /// 'Parsed' message delivery proof - inbound lane id and its state.
pub type ParsedMessagesDeliveryProofFromBridgedChain<B> = (LaneId, InboundLaneData<AccountIdOf<ThisChain<B>>>); pub type ParsedMessagesDeliveryProofFromBridgedChain<B> =
(LaneId, InboundLaneData<AccountIdOf<ThisChain<B>>>);
/// Message verifier that is doing all basic checks. /// Message verifier that is doing all basic checks.
/// ///
@@ -235,19 +260,30 @@ pub mod source {
/// Following checks are made: /// Following checks are made:
/// ///
/// - message is rejected if its lane is currently blocked; /// - message is rejected if its lane is currently blocked;
/// - message is rejected if there are too many pending (undelivered) messages at the outbound lane; /// - message is rejected if there are too many pending (undelivered) messages at the outbound
/// - check that the sender has rights to dispatch the call on target chain using provided dispatch origin; /// lane;
/// - check that the sender has rights to dispatch the call on target chain using provided
/// dispatch origin;
/// - check that the sender has paid enough funds for both message delivery and dispatch. /// - check that the sender has paid enough funds for both message delivery and dispatch.
#[derive(RuntimeDebug)] #[derive(RuntimeDebug)]
pub struct FromThisChainMessageVerifier<B>(PhantomData<B>); pub struct FromThisChainMessageVerifier<B>(PhantomData<B>);
pub(crate) const OUTBOUND_LANE_DISABLED: &str = "The outbound message lane is disabled."; /// The error message returned from LaneMessageVerifier when outbound lane is disabled.
pub(crate) const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; pub const OUTBOUND_LANE_DISABLED: &str = "The outbound message lane is disabled.";
pub(crate) const BAD_ORIGIN: &str = "Unable to match the source origin to expected target origin."; /// The error message returned from LaneMessageVerifier when too many pending messages at the
pub(crate) const TOO_LOW_FEE: &str = "Provided fee is below minimal threshold required by the lane."; /// lane.
pub const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane.";
/// The error message returned from LaneMessageVerifier when call origin is mismatch.
pub const BAD_ORIGIN: &str = "Unable to match the source origin to expected target origin.";
/// The error message returned from LaneMessageVerifier when the message fee is too low.
pub const TOO_LOW_FEE: &str = "Provided fee is below minimal threshold required by the lane.";
impl<B> LaneMessageVerifier<AccountIdOf<ThisChain<B>>, FromThisChainMessagePayload<B>, BalanceOf<ThisChain<B>>> impl<B>
for FromThisChainMessageVerifier<B> LaneMessageVerifier<
AccountIdOf<ThisChain<B>>,
FromThisChainMessagePayload<B>,
BalanceOf<ThisChain<B>>,
> for FromThisChainMessageVerifier<B>
where where
B: MessageBridge, B: MessageBridge,
AccountIdOf<ThisChain<B>>: PartialEq + Clone, AccountIdOf<ThisChain<B>>: PartialEq + Clone,
@@ -263,7 +299,7 @@ pub mod source {
) -> Result<(), Self::Error> { ) -> Result<(), Self::Error> {
// reject message if lane is blocked // reject message if lane is blocked
if !ThisChain::<B>::is_outbound_lane_enabled(lane) { if !ThisChain::<B>::is_outbound_lane_enabled(lane) {
return Err(OUTBOUND_LANE_DISABLED); return Err(OUTBOUND_LANE_DISABLED)
} }
// reject message if there are too many pending messages at this lane // reject message if there are too many pending messages at this lane
@@ -272,19 +308,20 @@ pub mod source {
.latest_generated_nonce .latest_generated_nonce
.saturating_sub(lane_outbound_data.latest_received_nonce); .saturating_sub(lane_outbound_data.latest_received_nonce);
if pending_messages > max_pending_messages { if pending_messages > max_pending_messages {
return Err(TOO_MANY_PENDING_MESSAGES); return Err(TOO_MANY_PENDING_MESSAGES)
} }
// Do the dispatch-specific check. We assume that the target chain uses // Do the dispatch-specific check. We assume that the target chain uses
// `Dispatch`, so we verify the message accordingly. // `Dispatch`, so we verify the message accordingly.
pallet_bridge_dispatch::verify_message_origin(submitter, payload).map_err(|_| BAD_ORIGIN)?; pallet_bridge_dispatch::verify_message_origin(submitter, payload)
.map_err(|_| BAD_ORIGIN)?;
let minimal_fee_in_this_tokens = let minimal_fee_in_this_tokens =
estimate_message_dispatch_and_delivery_fee::<B>(payload, B::RELAYER_FEE_PERCENT)?; estimate_message_dispatch_and_delivery_fee::<B>(payload, B::RELAYER_FEE_PERCENT)?;
// compare with actual fee paid // compare with actual fee paid
if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens { if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens {
return Err(TOO_LOW_FEE); return Err(TOO_LOW_FEE)
} }
Ok(()) Ok(())
@@ -306,13 +343,13 @@ pub mod source {
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
let weight_limits = BridgedChain::<B>::message_weight_limits(&payload.call); let weight_limits = BridgedChain::<B>::message_weight_limits(&payload.call);
if !weight_limits.contains(&payload.weight.into()) { if !weight_limits.contains(&payload.weight.into()) {
return Err("Incorrect message weight declared"); return Err("Incorrect message weight declared")
} }
// The maximal size of extrinsic at Substrate-based chain depends on the // The maximal size of extrinsic at Substrate-based chain depends on the
// `frame_system::Config::MaximumBlockLength` and `frame_system::Config::AvailableBlockRatio` // `frame_system::Config::MaximumBlockLength` and
// constants. This check is here to be sure that the lane won't stuck because message is too // `frame_system::Config::AvailableBlockRatio` constants. This check is here to be sure that
// large to fit into delivery transaction. // the lane won't stuck because message is too large to fit into delivery transaction.
// //
// **IMPORTANT NOTE**: the delivery transaction contains storage proof of the message, not // **IMPORTANT NOTE**: the delivery transaction contains storage proof of the message, not
// the message itself. The proof is always larger than the message. But unless chain state // the message itself. The proof is always larger than the message. But unless chain state
@@ -320,16 +357,17 @@ pub mod source {
// transaction also contains signatures and signed extensions. Because of this, we reserve // transaction also contains signatures and signed extensions. Because of this, we reserve
// 1/3 of the the maximal extrinsic weight for this data. // 1/3 of the the maximal extrinsic weight for this data.
if payload.call.len() > maximal_message_size::<B>() as usize { if payload.call.len() > maximal_message_size::<B>() as usize {
return Err("The message is too large to be sent over the lane"); return Err("The message is too large to be sent over the lane")
} }
Ok(()) Ok(())
} }
/// Estimate delivery and dispatch fee that must be paid for delivering a message to the Bridged chain. /// Estimate delivery and dispatch fee that must be paid for delivering a message to the Bridged
/// chain.
/// ///
/// The fee is paid in This chain Balance, but we use Bridged chain balance to avoid additional conversions. /// The fee is paid in This chain Balance, but we use Bridged chain balance to avoid additional
/// Returns `None` if overflow has happened. /// conversions. Returns `None` if overflow has happened.
pub fn estimate_message_dispatch_and_delivery_fee<B: MessageBridge>( pub fn estimate_message_dispatch_and_delivery_fee<B: MessageBridge>(
payload: &FromThisChainMessagePayload<B>, payload: &FromThisChainMessagePayload<B>,
relayer_fee_percent: u32, relayer_fee_percent: u32,
@@ -338,25 +376,23 @@ pub mod source {
// //
// if we're going to pay dispatch fee at the target chain, then we don't include weight // if we're going to pay dispatch fee at the target chain, then we don't include weight
// of the message dispatch in the delivery transaction cost // of the message dispatch in the delivery transaction cost
let pay_dispatch_fee_at_target_chain = payload.dispatch_fee_payment == DispatchFeePayment::AtTargetChain; let pay_dispatch_fee_at_target_chain =
payload.dispatch_fee_payment == DispatchFeePayment::AtTargetChain;
let delivery_transaction = BridgedChain::<B>::estimate_delivery_transaction( let delivery_transaction = BridgedChain::<B>::estimate_delivery_transaction(
&payload.call, &payload.encode(),
pay_dispatch_fee_at_target_chain, pay_dispatch_fee_at_target_chain,
if pay_dispatch_fee_at_target_chain { if pay_dispatch_fee_at_target_chain { 0.into() } else { payload.weight.into() },
0.into()
} else {
payload.weight.into()
},
); );
let delivery_transaction_fee = BridgedChain::<B>::transaction_payment(delivery_transaction); let delivery_transaction_fee = BridgedChain::<B>::transaction_payment(delivery_transaction);
// the fee (in This tokens) of all transactions that are made on This chain // the fee (in This tokens) of all transactions that are made on This chain
let confirmation_transaction = ThisChain::<B>::estimate_delivery_confirmation_transaction(); let confirmation_transaction = ThisChain::<B>::estimate_delivery_confirmation_transaction();
let confirmation_transaction_fee = ThisChain::<B>::transaction_payment(confirmation_transaction); let confirmation_transaction_fee =
ThisChain::<B>::transaction_payment(confirmation_transaction);
// minimal fee (in This tokens) is a sum of all required fees // minimal fee (in This tokens) is a sum of all required fees
let minimal_fee = let minimal_fee = B::bridged_balance_to_this_balance(delivery_transaction_fee)
B::bridged_balance_to_this_balance(delivery_transaction_fee).checked_add(&confirmation_transaction_fee); .checked_add(&confirmation_transaction_fee);
// before returning, add extra fee that is paid to the relayer (relayer interest) // before returning, add extra fee that is paid to the relayer (relayer interest)
minimal_fee minimal_fee
@@ -377,14 +413,14 @@ pub mod source {
) -> Result<ParsedMessagesDeliveryProofFromBridgedChain<B>, &'static str> ) -> Result<ParsedMessagesDeliveryProofFromBridgedChain<B>, &'static str>
where where
ThisRuntime: pallet_bridge_grandpa::Config<GrandpaInstance>, ThisRuntime: pallet_bridge_grandpa::Config<GrandpaInstance>,
HashOf<BridgedChain<B>>: HashOf<BridgedChain<B>>: Into<
Into<bp_runtime::HashOf<<ThisRuntime as pallet_bridge_grandpa::Config<GrandpaInstance>>::BridgedChain>>, bp_runtime::HashOf<
<ThisRuntime as pallet_bridge_grandpa::Config<GrandpaInstance>>::BridgedChain,
>,
>,
{ {
let FromBridgedChainMessagesDeliveryProof { let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane } =
bridged_header_hash, proof;
storage_proof,
lane,
} = proof;
pallet_bridge_grandpa::Pallet::<ThisRuntime, GrandpaInstance>::parse_finalized_storage_proof( pallet_bridge_grandpa::Pallet::<ThisRuntime, GrandpaInstance>::parse_finalized_storage_proof(
bridged_header_hash.into(), bridged_header_hash.into(),
StorageProof::new(storage_proof), StorageProof::new(storage_proof),
@@ -392,7 +428,7 @@ pub mod source {
// Messages delivery proof is just proof of single storage key read => any error // Messages delivery proof is just proof of single storage key read => any error
// is fatal. // is fatal.
let storage_inbound_lane_data_key = let storage_inbound_lane_data_key =
pallet_bridge_messages::storage_keys::inbound_lane_data_key::<B::BridgedMessagesInstance>(&lane); pallet_bridge_messages::storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &lane);
let raw_inbound_lane_data = storage let raw_inbound_lane_data = storage
.read_value(storage_inbound_lane_data_key.0.as_ref()) .read_value(storage_inbound_lane_data_key.0.as_ref())
.map_err(|_| "Failed to read inbound lane state from storage proof")? .map_err(|_| "Failed to read inbound lane state from storage proof")?
@@ -469,14 +505,13 @@ pub mod target {
impl<DecodedCall> FromBridgedChainEncodedMessageCall<DecodedCall> { impl<DecodedCall> FromBridgedChainEncodedMessageCall<DecodedCall> {
/// Create encoded call. /// Create encoded call.
pub fn new(encoded_call: Vec<u8>) -> Self { pub fn new(encoded_call: Vec<u8>) -> Self {
FromBridgedChainEncodedMessageCall { FromBridgedChainEncodedMessageCall { encoded_call, _marker: PhantomData::default() }
encoded_call,
_marker: PhantomData::default(),
}
} }
} }
impl<DecodedCall: Decode> From<FromBridgedChainEncodedMessageCall<DecodedCall>> for Result<DecodedCall, ()> { impl<DecodedCall: Decode> From<FromBridgedChainEncodedMessageCall<DecodedCall>>
for Result<DecodedCall, ()>
{
fn from(encoded_call: FromBridgedChainEncodedMessageCall<DecodedCall>) -> Self { fn from(encoded_call: FromBridgedChainEncodedMessageCall<DecodedCall>) -> Self {
DecodedCall::decode(&mut &encoded_call.encoded_call[..]).map_err(drop) DecodedCall::decode(&mut &encoded_call.encoded_call[..]).map_err(drop)
} }
@@ -492,16 +527,20 @@ pub mod target {
MessageDispatch<AccountIdOf<ThisChain<B>>, BalanceOf<BridgedChain<B>>> MessageDispatch<AccountIdOf<ThisChain<B>>, BalanceOf<BridgedChain<B>>>
for FromBridgedChainMessageDispatch<B, ThisRuntime, ThisCurrency, ThisDispatchInstance> for FromBridgedChainMessageDispatch<B, ThisRuntime, ThisCurrency, ThisDispatchInstance>
where where
ThisDispatchInstance: frame_support::traits::Instance, BalanceOf<ThisChain<B>>: Saturating + FixedPointOperand,
ThisRuntime: pallet_bridge_dispatch::Config<ThisDispatchInstance, MessageId = (LaneId, MessageNonce)> ThisDispatchInstance: 'static,
+ pallet_transaction_payment::Config, ThisRuntime: pallet_bridge_dispatch::Config<
ThisDispatchInstance,
BridgeMessageId = (LaneId, MessageNonce),
> + pallet_transaction_payment::Config,
<ThisRuntime as pallet_transaction_payment::Config>::OnChargeTransaction: <ThisRuntime as pallet_transaction_payment::Config>::OnChargeTransaction:
pallet_transaction_payment::OnChargeTransaction<ThisRuntime, Balance = BalanceOf<ThisChain<B>>>, pallet_transaction_payment::OnChargeTransaction<
ThisCurrency: Currency<AccountIdOf<ThisChain<B>>, Balance = BalanceOf<ThisChain<B>>>, ThisRuntime,
<ThisRuntime as pallet_bridge_dispatch::Config<ThisDispatchInstance>>::Event: From< Balance = BalanceOf<ThisChain<B>>,
pallet_bridge_dispatch::RawEvent<(LaneId, MessageNonce), AccountIdOf<ThisChain<B>>, ThisDispatchInstance>,
>, >,
pallet_bridge_dispatch::Pallet<ThisRuntime, ThisDispatchInstance>: bp_message_dispatch::MessageDispatch< ThisCurrency: Currency<AccountIdOf<ThisChain<B>>, Balance = BalanceOf<ThisChain<B>>>,
pallet_bridge_dispatch::Pallet<ThisRuntime, ThisDispatchInstance>:
bp_message_dispatch::MessageDispatch<
AccountIdOf<ThisChain<B>>, AccountIdOf<ThisChain<B>>,
(LaneId, MessageNonce), (LaneId, MessageNonce),
Message = FromBridgedChainMessagePayload<B>, Message = FromBridgedChainMessagePayload<B>,
@@ -526,13 +565,22 @@ pub mod target {
message_id, message_id,
message.data.payload.map_err(drop), message.data.payload.map_err(drop),
|dispatch_origin, dispatch_weight| { |dispatch_origin, dispatch_weight| {
let unadjusted_weight_fee = ThisRuntime::WeightToFee::calc(&dispatch_weight);
let fee_multiplier =
pallet_transaction_payment::Pallet::<ThisRuntime>::next_fee_multiplier();
let adjusted_weight_fee =
fee_multiplier.saturating_mul_int(unadjusted_weight_fee);
if !adjusted_weight_fee.is_zero() {
ThisCurrency::transfer( ThisCurrency::transfer(
dispatch_origin, dispatch_origin,
relayer_account, relayer_account,
ThisRuntime::WeightToFee::calc(&dispatch_weight), adjusted_weight_fee,
ExistenceRequirement::AllowDeath, ExistenceRequirement::AllowDeath,
) )
.map_err(drop) .map_err(drop)
} else {
Ok(())
}
}, },
) )
} }
@@ -559,9 +607,11 @@ pub mod target {
) -> Result<ProvedMessages<Message<BalanceOf<BridgedChain<B>>>>, &'static str> ) -> Result<ProvedMessages<Message<BalanceOf<BridgedChain<B>>>>, &'static str>
where where
ThisRuntime: pallet_bridge_grandpa::Config<GrandpaInstance>, ThisRuntime: pallet_bridge_grandpa::Config<GrandpaInstance>,
ThisRuntime: pallet_bridge_messages::Config<B::BridgedMessagesInstance>, HashOf<BridgedChain<B>>: Into<
HashOf<BridgedChain<B>>: bp_runtime::HashOf<
Into<bp_runtime::HashOf<<ThisRuntime as pallet_bridge_grandpa::Config<GrandpaInstance>>::BridgedChain>>, <ThisRuntime as pallet_bridge_grandpa::Config<GrandpaInstance>>::BridgedChain,
>,
>,
{ {
verify_messages_proof_with_parser::<B, _, _>( verify_messages_proof_with_parser::<B, _, _>(
proof, proof,
@@ -596,12 +646,13 @@ pub mod target {
fn from(err: MessageProofError) -> &'static str { fn from(err: MessageProofError) -> &'static str {
match err { match err {
MessageProofError::Empty => "Messages proof is empty", MessageProofError::Empty => "Messages proof is empty",
MessageProofError::MessagesCountMismatch => "Declared messages count doesn't match actual value", MessageProofError::MessagesCountMismatch =>
"Declared messages count doesn't match actual value",
MessageProofError::MissingRequiredMessage => "Message is missing from the proof", MessageProofError::MissingRequiredMessage => "Message is missing from the proof",
MessageProofError::FailedToDecodeMessage => "Failed to decode message from the proof", MessageProofError::FailedToDecodeMessage =>
MessageProofError::FailedToDecodeOutboundLaneState => { "Failed to decode message from the proof",
"Failed to decode outbound lane data from the proof" MessageProofError::FailedToDecodeOutboundLaneState =>
} "Failed to decode outbound lane data from the proof",
MessageProofError::Custom(err) => err, MessageProofError::Custom(err) => err,
} }
} }
@@ -624,14 +675,16 @@ pub mod target {
{ {
fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option<Vec<u8>> { fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option<Vec<u8>> {
let storage_outbound_lane_data_key = let storage_outbound_lane_data_key =
pallet_bridge_messages::storage_keys::outbound_lane_data_key::<B::BridgedMessagesInstance>(lane_id); pallet_bridge_messages::storage_keys::outbound_lane_data_key(
self.storage B::BRIDGED_MESSAGES_PALLET_NAME,
.read_value(storage_outbound_lane_data_key.0.as_ref()) lane_id,
.ok()? );
self.storage.read_value(storage_outbound_lane_data_key.0.as_ref()).ok()?
} }
fn read_raw_message(&self, message_key: &MessageKey) -> Option<Vec<u8>> { fn read_raw_message(&self, message_key: &MessageKey) -> Option<Vec<u8>> {
let storage_message_key = pallet_bridge_messages::storage_keys::message_key::<B::BridgedMessagesInstance>( let storage_message_key = pallet_bridge_messages::storage_keys::message_key(
B::BRIDGED_MESSAGES_PALLET_NAME,
&message_key.lane_id, &message_key.lane_id,
message_key.nonce, message_key.nonce,
); );
@@ -646,7 +699,8 @@ pub mod target {
build_parser: BuildParser, build_parser: BuildParser,
) -> Result<ProvedMessages<Message<BalanceOf<BridgedChain<B>>>>, MessageProofError> ) -> Result<ProvedMessages<Message<BalanceOf<BridgedChain<B>>>>, MessageProofError>
where where
BuildParser: FnOnce(HashOf<BridgedChain<B>>, RawStorageProof) -> Result<Parser, MessageProofError>, BuildParser:
FnOnce(HashOf<BridgedChain<B>>, RawStorageProof) -> Result<Parser, MessageProofError>,
Parser: MessageProofParser, Parser: MessageProofParser,
{ {
let FromBridgedChainMessagesProof { let FromBridgedChainMessagesProof {
@@ -658,12 +712,13 @@ pub mod target {
} = proof; } = proof;
// receiving proofs where end < begin is ok (if proof includes outbound lane state) // receiving proofs where end < begin is ok (if proof includes outbound lane state)
let messages_in_the_proof = if let Some(nonces_difference) = nonces_end.checked_sub(nonces_start) { let messages_in_the_proof =
if let Some(nonces_difference) = nonces_end.checked_sub(nonces_start) {
// let's check that the user (relayer) has passed correct `messages_count` // let's check that the user (relayer) has passed correct `messages_count`
// (this bounds maximal capacity of messages vec below) // (this bounds maximal capacity of messages vec below)
let messages_in_the_proof = nonces_difference.saturating_add(1); let messages_in_the_proof = nonces_difference.saturating_add(1);
if messages_in_the_proof != MessageNonce::from(messages_count) { if messages_in_the_proof != MessageNonce::from(messages_count) {
return Err(MessageProofError::MessagesCountMismatch); return Err(MessageProofError::MessagesCountMismatch)
} }
messages_in_the_proof messages_in_the_proof
@@ -683,20 +738,15 @@ pub mod target {
let raw_message_data = parser let raw_message_data = parser
.read_raw_message(&message_key) .read_raw_message(&message_key)
.ok_or(MessageProofError::MissingRequiredMessage)?; .ok_or(MessageProofError::MissingRequiredMessage)?;
let message_data = MessageData::<BalanceOf<BridgedChain<B>>>::decode(&mut &raw_message_data[..]) let message_data =
MessageData::<BalanceOf<BridgedChain<B>>>::decode(&mut &raw_message_data[..])
.map_err(|_| MessageProofError::FailedToDecodeMessage)?; .map_err(|_| MessageProofError::FailedToDecodeMessage)?;
messages.push(Message { messages.push(Message { key: message_key, data: message_data });
key: message_key,
data: message_data,
});
} }
// Now let's check if proof contains outbound lane state proof. It is optional, so we // Now let's check if proof contains outbound lane state proof. It is optional, so we
// simply ignore `read_value` errors and missing value. // simply ignore `read_value` errors and missing value.
let mut proved_lane_messages = ProvedLaneMessages { let mut proved_lane_messages = ProvedLaneMessages { lane_state: None, messages };
lane_state: None,
messages,
};
let raw_outbound_lane_data = parser.read_raw_outbound_lane_data(&lane); let raw_outbound_lane_data = parser.read_raw_outbound_lane_data(&lane);
if let Some(raw_outbound_lane_data) = raw_outbound_lane_data { if let Some(raw_outbound_lane_data) = raw_outbound_lane_data {
proved_lane_messages.lane_state = Some( proved_lane_messages.lane_state = Some(
@@ -707,7 +757,7 @@ pub mod target {
// Now we may actually check if the proof is empty or not. // Now we may actually check if the proof is empty or not.
if proved_lane_messages.lane_state.is_none() && proved_lane_messages.messages.is_empty() { if proved_lane_messages.lane_state.is_none() && proved_lane_messages.messages.is_empty() {
return Err(MessageProofError::Empty); return Err(MessageProofError::Empty)
} }
// We only support single lane messages in this schema // We only support single lane messages in this schema
@@ -733,7 +783,8 @@ mod tests {
const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: Weight = 2048; const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: Weight = 2048;
const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024;
/// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from BridgedChain; /// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from
/// BridgedChain;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
struct OnThisChainBridge; struct OnThisChainBridge;
@@ -741,17 +792,20 @@ mod tests {
const RELAYER_FEE_PERCENT: u32 = 10; const RELAYER_FEE_PERCENT: u32 = 10;
const THIS_CHAIN_ID: ChainId = *b"this"; const THIS_CHAIN_ID: ChainId = *b"this";
const BRIDGED_CHAIN_ID: ChainId = *b"brdg"; const BRIDGED_CHAIN_ID: ChainId = *b"brdg";
const BRIDGED_MESSAGES_PALLET_NAME: &'static str = "";
type ThisChain = ThisChain; type ThisChain = ThisChain;
type BridgedChain = BridgedChain; type BridgedChain = BridgedChain;
type BridgedMessagesInstance = pallet_bridge_messages::DefaultInstance;
fn bridged_balance_to_this_balance(bridged_balance: BridgedChainBalance) -> ThisChainBalance { fn bridged_balance_to_this_balance(
bridged_balance: BridgedChainBalance,
) -> ThisChainBalance {
ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32) ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32)
} }
} }
/// Bridge that is deployed on BridgedChain and allows sending/receiving messages to/from ThisChain; /// Bridge that is deployed on BridgedChain and allows sending/receiving messages to/from
/// ThisChain;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
struct OnBridgedChainBridge; struct OnBridgedChainBridge;
@@ -759,10 +813,10 @@ mod tests {
const RELAYER_FEE_PERCENT: u32 = 20; const RELAYER_FEE_PERCENT: u32 = 20;
const THIS_CHAIN_ID: ChainId = *b"brdg"; const THIS_CHAIN_ID: ChainId = *b"brdg";
const BRIDGED_CHAIN_ID: ChainId = *b"this"; const BRIDGED_CHAIN_ID: ChainId = *b"this";
const BRIDGED_MESSAGES_PALLET_NAME: &'static str = "";
type ThisChain = BridgedChain; type ThisChain = BridgedChain;
type BridgedChain = ThisChain; type BridgedChain = ThisChain;
type BridgedMessagesInstance = pallet_bridge_messages::DefaultInstance;
fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance { fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance {
unreachable!() unreachable!()
@@ -886,7 +940,9 @@ mod tests {
} }
fn transaction_payment(transaction: MessageTransaction<WeightOf<Self>>) -> BalanceOf<Self> { fn transaction_payment(transaction: MessageTransaction<WeightOf<Self>>) -> BalanceOf<Self> {
ThisChainBalance(transaction.dispatch_weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) ThisChainBalance(
transaction.dispatch_weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32,
)
} }
} }
@@ -907,7 +963,9 @@ mod tests {
unreachable!() unreachable!()
} }
fn transaction_payment(_transaction: MessageTransaction<WeightOf<Self>>) -> BalanceOf<Self> { fn transaction_payment(
_transaction: MessageTransaction<WeightOf<Self>>,
) -> BalanceOf<Self> {
unreachable!() unreachable!()
} }
} }
@@ -938,7 +996,9 @@ mod tests {
unreachable!() unreachable!()
} }
fn transaction_payment(_transaction: MessageTransaction<WeightOf<Self>>) -> BalanceOf<Self> { fn transaction_payment(
_transaction: MessageTransaction<WeightOf<Self>>,
) -> BalanceOf<Self> {
unreachable!() unreachable!()
} }
} }
@@ -949,7 +1009,8 @@ mod tests {
} }
fn message_weight_limits(message_payload: &[u8]) -> RangeInclusive<Self::Weight> { fn message_weight_limits(message_payload: &[u8]) -> RangeInclusive<Self::Weight> {
let begin = std::cmp::min(BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, message_payload.len() as Weight); let begin =
std::cmp::min(BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, message_payload.len() as Weight);
begin..=BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT begin..=BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT
} }
@@ -965,7 +1026,9 @@ mod tests {
} }
fn transaction_payment(transaction: MessageTransaction<WeightOf<Self>>) -> BalanceOf<Self> { fn transaction_payment(transaction: MessageTransaction<WeightOf<Self>>) -> BalanceOf<Self> {
BridgedChainBalance(transaction.dispatch_weight as u32 * BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) BridgedChainBalance(
transaction.dispatch_weight as u32 * BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u32,
)
} }
} }
@@ -976,7 +1039,8 @@ mod tests {
#[test] #[test]
fn message_from_bridged_chain_is_decoded() { fn message_from_bridged_chain_is_decoded() {
// the message is encoded on the bridged chain // the message is encoded on the bridged chain
let message_on_bridged_chain = source::FromThisChainMessagePayload::<OnBridgedChainBridge> { let message_on_bridged_chain =
source::FromThisChainMessagePayload::<OnBridgedChainBridge> {
spec_version: 1, spec_version: 1,
weight: 100, weight: 100,
origin: bp_message_dispatch::CallOrigin::SourceRoot, origin: bp_message_dispatch::CallOrigin::SourceRoot,
@@ -987,7 +1051,9 @@ mod tests {
// and sent to this chain where it is decoded // and sent to this chain where it is decoded
let message_on_this_chain = let message_on_this_chain =
target::FromBridgedChainMessagePayload::<OnThisChainBridge>::decode(&mut &message_on_bridged_chain[..]) target::FromBridgedChainMessagePayload::<OnThisChainBridge>::decode(
&mut &message_on_bridged_chain[..],
)
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
message_on_this_chain, message_on_this_chain,
@@ -1007,7 +1073,8 @@ mod tests {
const TEST_LANE_ID: &LaneId = b"test"; const TEST_LANE_ID: &LaneId = b"test";
const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32; const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32;
fn regular_outbound_message_payload() -> source::FromThisChainMessagePayload<OnThisChainBridge> { fn regular_outbound_message_payload() -> source::FromThisChainMessagePayload<OnThisChainBridge>
{
source::FromThisChainMessagePayload::<OnThisChainBridge> { source::FromThisChainMessagePayload::<OnThisChainBridge> {
spec_version: 1, spec_version: 1,
weight: 100, weight: 100,
@@ -1036,11 +1103,14 @@ mod tests {
// let's check if estimation is less than hardcoded, if dispatch is paid at target chain // let's check if estimation is less than hardcoded, if dispatch is paid at target chain
let mut payload_with_pay_on_target = regular_outbound_message_payload(); let mut payload_with_pay_on_target = regular_outbound_message_payload();
payload_with_pay_on_target.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; payload_with_pay_on_target.dispatch_fee_payment = DispatchFeePayment::AtTargetChain;
let fee_at_source = source::estimate_message_dispatch_and_delivery_fee::<OnThisChainBridge>( let fee_at_source =
source::estimate_message_dispatch_and_delivery_fee::<OnThisChainBridge>(
&payload_with_pay_on_target, &payload_with_pay_on_target,
OnThisChainBridge::RELAYER_FEE_PERCENT, OnThisChainBridge::RELAYER_FEE_PERCENT,
) )
.expect("estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message"); .expect(
"estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message",
);
assert!( assert!(
fee_at_source < EXPECTED_MINIMAL_FEE.into(), fee_at_source < EXPECTED_MINIMAL_FEE.into(),
"Computed fee {:?} without prepaid dispatch must be less than the fee with prepaid dispatch {}", "Computed fee {:?} without prepaid dispatch must be less than the fee with prepaid dispatch {}",
@@ -1059,16 +1129,14 @@ mod tests {
), ),
Err(source::TOO_LOW_FEE) Err(source::TOO_LOW_FEE)
); );
assert!( assert!(source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
&Sender::Root, &Sender::Root,
&ThisChainBalance(1_000_000), &ThisChainBalance(1_000_000),
TEST_LANE_ID, TEST_LANE_ID,
&test_lane_outbound_data(), &test_lane_outbound_data(),
&payload, &payload,
) )
.is_ok(), .is_ok(),);
);
} }
#[test] #[test]
@@ -1103,16 +1171,14 @@ mod tests {
), ),
Err(source::BAD_ORIGIN) Err(source::BAD_ORIGIN)
); );
assert!( assert!(source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
&Sender::Root, &Sender::Root,
&ThisChainBalance(1_000_000), &ThisChainBalance(1_000_000),
TEST_LANE_ID, TEST_LANE_ID,
&test_lane_outbound_data(), &test_lane_outbound_data(),
&payload, &payload,
) )
.is_ok(), .is_ok(),);
);
} }
#[test] #[test]
@@ -1137,16 +1203,14 @@ mod tests {
), ),
Err(source::BAD_ORIGIN) Err(source::BAD_ORIGIN)
); );
assert!( assert!(source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
&Sender::Signed(ThisChainAccountId(1)), &Sender::Signed(ThisChainAccountId(1)),
&ThisChainBalance(1_000_000), &ThisChainBalance(1_000_000),
TEST_LANE_ID, TEST_LANE_ID,
&test_lane_outbound_data(), &test_lane_outbound_data(),
&payload, &payload,
) )
.is_ok(), .is_ok(),);
);
} }
#[test] #[test]
@@ -1183,64 +1247,58 @@ mod tests {
#[test] #[test]
fn verify_chain_message_rejects_message_with_too_small_declared_weight() { fn verify_chain_message_rejects_message_with_too_small_declared_weight() {
assert!( assert!(source::verify_chain_message::<OnThisChainBridge>(
source::verify_chain_message::<OnThisChainBridge>(&source::FromThisChainMessagePayload::< &source::FromThisChainMessagePayload::<OnThisChainBridge> {
OnThisChainBridge,
> {
spec_version: 1, spec_version: 1,
weight: 5, weight: 5,
origin: bp_message_dispatch::CallOrigin::SourceRoot, origin: bp_message_dispatch::CallOrigin::SourceRoot,
dispatch_fee_payment: DispatchFeePayment::AtSourceChain, dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
call: vec![1, 2, 3, 4, 5, 6], call: vec![1, 2, 3, 4, 5, 6],
},) },
.is_err() )
); .is_err());
} }
#[test] #[test]
fn verify_chain_message_rejects_message_with_too_large_declared_weight() { fn verify_chain_message_rejects_message_with_too_large_declared_weight() {
assert!( assert!(source::verify_chain_message::<OnThisChainBridge>(
source::verify_chain_message::<OnThisChainBridge>(&source::FromThisChainMessagePayload::< &source::FromThisChainMessagePayload::<OnThisChainBridge> {
OnThisChainBridge,
> {
spec_version: 1, spec_version: 1,
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1,
origin: bp_message_dispatch::CallOrigin::SourceRoot, origin: bp_message_dispatch::CallOrigin::SourceRoot,
dispatch_fee_payment: DispatchFeePayment::AtSourceChain, dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
call: vec![1, 2, 3, 4, 5, 6], call: vec![1, 2, 3, 4, 5, 6],
},) },
.is_err() )
); .is_err());
} }
#[test] #[test]
fn verify_chain_message_rejects_message_too_large_message() { fn verify_chain_message_rejects_message_too_large_message() {
assert!( assert!(source::verify_chain_message::<OnThisChainBridge>(
source::verify_chain_message::<OnThisChainBridge>(&source::FromThisChainMessagePayload::< &source::FromThisChainMessagePayload::<OnThisChainBridge> {
OnThisChainBridge,
> {
spec_version: 1, spec_version: 1,
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
origin: bp_message_dispatch::CallOrigin::SourceRoot, origin: bp_message_dispatch::CallOrigin::SourceRoot,
dispatch_fee_payment: DispatchFeePayment::AtSourceChain, dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as usize + 1], call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as usize + 1],
},) },
.is_err() )
); .is_err());
} }
#[test] #[test]
fn verify_chain_message_accepts_maximal_message() { fn verify_chain_message_accepts_maximal_message() {
assert_eq!( assert_eq!(
source::verify_chain_message::<OnThisChainBridge>(&source::FromThisChainMessagePayload::< source::verify_chain_message::<OnThisChainBridge>(
OnThisChainBridge, &source::FromThisChainMessagePayload::<OnThisChainBridge> {
> {
spec_version: 1, spec_version: 1,
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
origin: bp_message_dispatch::CallOrigin::SourceRoot, origin: bp_message_dispatch::CallOrigin::SourceRoot,
dispatch_fee_payment: DispatchFeePayment::AtSourceChain, dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as _], call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as _],
},), },
),
Ok(()), Ok(()),
); );
} }
@@ -1332,13 +1390,15 @@ mod tests {
#[test] #[test]
fn message_proof_is_rejected_if_required_message_is_missing() { fn message_proof_is_rejected_if_required_message_is_missing() {
assert_eq!( assert_eq!(
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(messages_proof(10), 10, |_, _| Ok( target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(
TestMessageProofParser { messages_proof(10),
10,
|_, _| Ok(TestMessageProofParser {
failing: false, failing: false,
messages: 1..=5, messages: 1..=5,
outbound_lane_data: None, outbound_lane_data: None,
} }),
),), ),
Err(target::MessageProofError::MissingRequiredMessage), Err(target::MessageProofError::MissingRequiredMessage),
); );
} }
@@ -1346,13 +1406,15 @@ mod tests {
#[test] #[test]
fn message_proof_is_rejected_if_message_decode_fails() { fn message_proof_is_rejected_if_message_decode_fails() {
assert_eq!( assert_eq!(
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(messages_proof(10), 10, |_, _| Ok( target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(
TestMessageProofParser { messages_proof(10),
10,
|_, _| Ok(TestMessageProofParser {
failing: true, failing: true,
messages: 1..=10, messages: 1..=10,
outbound_lane_data: None, outbound_lane_data: None,
} }),
),), ),
Err(target::MessageProofError::FailedToDecodeMessage), Err(target::MessageProofError::FailedToDecodeMessage),
); );
} }
@@ -1360,8 +1422,10 @@ mod tests {
#[test] #[test]
fn message_proof_is_rejected_if_outbound_lane_state_decode_fails() { fn message_proof_is_rejected_if_outbound_lane_state_decode_fails() {
assert_eq!( assert_eq!(
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(messages_proof(0), 0, |_, _| Ok( target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(
TestMessageProofParser { messages_proof(0),
0,
|_, _| Ok(TestMessageProofParser {
failing: true, failing: true,
messages: no_messages_range(), messages: no_messages_range(),
outbound_lane_data: Some(OutboundLaneData { outbound_lane_data: Some(OutboundLaneData {
@@ -1369,8 +1433,8 @@ mod tests {
latest_received_nonce: 1, latest_received_nonce: 1,
latest_generated_nonce: 1, latest_generated_nonce: 1,
}), }),
} }),
),), ),
Err(target::MessageProofError::FailedToDecodeOutboundLaneState), Err(target::MessageProofError::FailedToDecodeOutboundLaneState),
); );
} }
@@ -1378,13 +1442,15 @@ mod tests {
#[test] #[test]
fn message_proof_is_rejected_if_it_is_empty() { fn message_proof_is_rejected_if_it_is_empty() {
assert_eq!( assert_eq!(
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(messages_proof(0), 0, |_, _| Ok( target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(
TestMessageProofParser { messages_proof(0),
0,
|_, _| Ok(TestMessageProofParser {
failing: false, failing: false,
messages: no_messages_range(), messages: no_messages_range(),
outbound_lane_data: None, outbound_lane_data: None,
} }),
),), ),
Err(target::MessageProofError::Empty), Err(target::MessageProofError::Empty),
); );
} }
@@ -1392,8 +1458,10 @@ mod tests {
#[test] #[test]
fn non_empty_message_proof_without_messages_is_accepted() { fn non_empty_message_proof_without_messages_is_accepted() {
assert_eq!( assert_eq!(
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(messages_proof(0), 0, |_, _| Ok( target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(
TestMessageProofParser { messages_proof(0),
0,
|_, _| Ok(TestMessageProofParser {
failing: false, failing: false,
messages: no_messages_range(), messages: no_messages_range(),
outbound_lane_data: Some(OutboundLaneData { outbound_lane_data: Some(OutboundLaneData {
@@ -1401,8 +1469,8 @@ mod tests {
latest_received_nonce: 1, latest_received_nonce: 1,
latest_generated_nonce: 1, latest_generated_nonce: 1,
}), }),
} }),
),), ),
Ok(vec![( Ok(vec![(
Default::default(), Default::default(),
ProvedLaneMessages { ProvedLaneMessages {
@@ -1422,8 +1490,10 @@ mod tests {
#[test] #[test]
fn non_empty_message_proof_is_accepted() { fn non_empty_message_proof_is_accepted() {
assert_eq!( assert_eq!(
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(messages_proof(1), 1, |_, _| Ok( target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(
TestMessageProofParser { messages_proof(1),
1,
|_, _| Ok(TestMessageProofParser {
failing: false, failing: false,
messages: 1..=1, messages: 1..=1,
outbound_lane_data: Some(OutboundLaneData { outbound_lane_data: Some(OutboundLaneData {
@@ -1431,8 +1501,8 @@ mod tests {
latest_received_nonce: 1, latest_received_nonce: 1,
latest_generated_nonce: 1, latest_generated_nonce: 1,
}), }),
} }),
),), ),
Ok(vec![( Ok(vec![(
Default::default(), Default::default(),
ProvedLaneMessages { ProvedLaneMessages {
@@ -1442,14 +1512,8 @@ mod tests {
latest_generated_nonce: 1, latest_generated_nonce: 1,
}), }),
messages: vec![Message { messages: vec![Message {
key: MessageKey { key: MessageKey { lane_id: Default::default(), nonce: 1 },
lane_id: Default::default(), data: MessageData { payload: 1u64.encode(), fee: BridgedChainBalance(0) },
nonce: 1
},
data: MessageData {
payload: 1u64.encode(),
fee: BridgedChainBalance(0)
},
}], }],
}, },
)] )]
@@ -1488,10 +1552,7 @@ mod tests {
10, 10,
FixedU128::zero(), FixedU128::zero(),
|weight| weight, |weight| weight,
MessageTransaction { MessageTransaction { size: 50, dispatch_weight: 777 },
size: 50,
dispatch_weight: 777
},
), ),
100 + 50 * 10, 100 + 50 * 10,
); );
@@ -1507,10 +1568,7 @@ mod tests {
10, 10,
FixedU128::one(), FixedU128::one(),
|weight| weight, |weight| weight,
MessageTransaction { MessageTransaction { size: 50, dispatch_weight: 777 },
size: 50,
dispatch_weight: 777
},
), ),
100 + 50 * 10 + 777, 100 + 50 * 10 + 777,
); );
@@ -0,0 +1,51 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Helpers for implementing various message-related runtime API mthods.
use crate::messages::{source::FromThisChainMessagePayload, MessageBridge};
use bp_messages::{LaneId, MessageDetails, MessageNonce};
use codec::Decode;
use sp_std::vec::Vec;
/// Implementation of the `To*OutboundLaneApi::message_details`.
pub fn outbound_message_details<Runtime, MessagesPalletInstance, BridgeConfig>(
lane: LaneId,
begin: MessageNonce,
end: MessageNonce,
) -> Vec<MessageDetails<Runtime::OutboundMessageFee>>
where
Runtime: pallet_bridge_messages::Config<MessagesPalletInstance>,
MessagesPalletInstance: 'static,
BridgeConfig: MessageBridge,
{
(begin..=end)
.filter_map(|nonce| {
let message_data =
pallet_bridge_messages::Pallet::<Runtime, MessagesPalletInstance>::outbound_message_data(lane, nonce)?;
let decoded_payload =
FromThisChainMessagePayload::<BridgeConfig>::decode(&mut &message_data.payload[..]).ok()?;
Some(MessageDetails {
nonce,
dispatch_weight: decoded_payload.weight,
size: message_data.payload.len() as _,
delivery_and_dispatch_fee: message_data.fee,
dispatch_fee_payment: decoded_payload.dispatch_fee_payment,
})
})
.collect()
}
@@ -20,8 +20,8 @@
#![cfg(feature = "runtime-benchmarks")] #![cfg(feature = "runtime-benchmarks")]
use crate::messages::{ use crate::messages::{
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, AccountIdOf, BalanceOf, source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
BridgedChain, HashOf, MessageBridge, ThisChain, AccountIdOf, BalanceOf, BridgedChain, HashOf, MessageBridge, ThisChain,
}; };
use bp_messages::{LaneId, MessageData, MessageKey, MessagePayload}; use bp_messages::{LaneId, MessageData, MessageKey, MessagePayload};
@@ -29,13 +29,16 @@ use bp_runtime::ChainId;
use codec::Encode; use codec::Encode;
use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH}; use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH};
use frame_support::weights::Weight; use frame_support::weights::Weight;
use pallet_bridge_messages::benchmarking::{MessageDeliveryProofParams, MessageProofParams, ProofSize}; use pallet_bridge_messages::benchmarking::{
MessageDeliveryProofParams, MessageProofParams, ProofSize,
};
use sp_core::Hasher; use sp_core::Hasher;
use sp_runtime::traits::Header; use sp_runtime::traits::Header;
use sp_std::prelude::*; use sp_std::prelude::*;
use sp_trie::{record_all_keys, trie_types::TrieDBMut, Layout, MemoryDB, Recorder, TrieMut}; use sp_trie::{record_all_keys, trie_types::TrieDBMut, Layout, MemoryDB, Recorder, TrieMut};
/// Generate ed25519 signature to be used in `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`. /// Generate ed25519 signature to be used in
/// `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`.
/// ///
/// Returns public key of the signer and the signature itself. /// Returns public key of the signer and the signature itself.
pub fn ed25519_sign( pub fn ed25519_sign(
@@ -47,8 +50,8 @@ pub fn ed25519_sign(
) -> ([u8; 32], [u8; 64]) { ) -> ([u8; 32], [u8; 64]) {
// key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html) // key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html)
let target_secret = SecretKey::from_bytes(&[ let target_secret = SecretKey::from_bytes(&[
157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, 197, 105, 123, 050, 157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073,
105, 025, 112, 059, 172, 003, 028, 174, 127, 096, 197, 105, 123, 050, 105, 025, 112, 059, 172, 003, 028, 174, 127, 096,
]) ])
.expect("harcoded key is valid"); .expect("harcoded key is valid");
let target_public: PublicKey = (&target_secret).into(); let target_public: PublicKey = (&target_secret).into();
@@ -56,7 +59,8 @@ pub fn ed25519_sign(
let mut target_pair_bytes = [0u8; KEYPAIR_LENGTH]; let mut target_pair_bytes = [0u8; KEYPAIR_LENGTH];
target_pair_bytes[..SECRET_KEY_LENGTH].copy_from_slice(&target_secret.to_bytes()); target_pair_bytes[..SECRET_KEY_LENGTH].copy_from_slice(&target_secret.to_bytes());
target_pair_bytes[SECRET_KEY_LENGTH..].copy_from_slice(&target_public.to_bytes()); target_pair_bytes[SECRET_KEY_LENGTH..].copy_from_slice(&target_public.to_bytes());
let target_pair = ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid"); let target_pair =
ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid");
let signature_message = pallet_bridge_dispatch::account_ownership_digest( let signature_message = pallet_bridge_dispatch::account_ownership_digest(
target_call, target_call,
@@ -92,11 +96,8 @@ where
MH: Fn(H::Out) -> <R::BridgedChain as bp_runtime::Chain>::Header, MH: Fn(H::Out) -> <R::BridgedChain as bp_runtime::Chain>::Header,
{ {
// prepare Bridged chain storage with messages and (optionally) outbound lane state // prepare Bridged chain storage with messages and (optionally) outbound lane state
let message_count = params let message_count =
.message_nonces params.message_nonces.end().saturating_sub(*params.message_nonces.start()) + 1;
.end()
.saturating_sub(*params.message_nonces.start())
+ 1;
let mut storage_keys = Vec::with_capacity(message_count as usize + 1); let mut storage_keys = Vec::with_capacity(message_count as usize + 1);
let mut root = Default::default(); let mut root = Default::default();
let mut mdb = MemoryDB::default(); let mut mdb = MemoryDB::default();
@@ -105,10 +106,7 @@ where
// insert messages // insert messages
for nonce in params.message_nonces.clone() { for nonce in params.message_nonces.clone() {
let message_key = MessageKey { let message_key = MessageKey { lane_id: params.lane, nonce };
lane_id: params.lane,
nonce,
};
let message_data = MessageData { let message_data = MessageData {
fee: BalanceOf::<BridgedChain<B>>::from(0), fee: BalanceOf::<BridgedChain<B>>::from(0),
payload: message_payload.clone(), payload: message_payload.clone(),
@@ -220,7 +218,7 @@ fn grow_trie<H: Hasher>(mut root: H::Out, mdb: &mut MemoryDB<H>, trie_size: Proo
.expect("record_all_keys should not fail in benchmarks"); .expect("record_all_keys should not fail in benchmarks");
let size: usize = proof_recorder.drain().into_iter().map(|n| n.data.len()).sum(); let size: usize = proof_recorder.drain().into_iter().map(|n| n.data.len()).sum();
if size > minimal_trie_size as _ { if size > minimal_trie_size as _ {
return root; return root
} }
let mut trie = TrieDBMut::<H>::from_existing(mdb, &mut root) let mut trie = TrieDBMut::<H>::from_existing(mdb, &mut root)
+10 -16
View File
@@ -48,27 +48,21 @@ notice = "warn"
# A list of advisory IDs to ignore. Note that ignored advisories will still # A list of advisory IDs to ignore. Note that ignored advisories will still
# output a note when they are encountered. # output a note when they are encountered.
ignore = [ ignore = [
# generic-array lifetime errasure. If all upstream crates upgrade to >=0.14.0
# we can remove this.
"RUSTSEC-2020-0146",
# yaml-rust < clap. Not feasible to upgrade and also not possible to trigger in practice. # yaml-rust < clap. Not feasible to upgrade and also not possible to trigger in practice.
"RUSTSEC-2018-0006", "RUSTSEC-2018-0006",
# Comes from wasmtime via Substrate: 'cranelift-codegen'
"RUSTSEC-2021-0067",
# Comes from libp2p via Substrate: 'aes-soft', 'aesni', 'block-cipher', 'stream-cipher'
"RUSTSEC-2021-0060",
"RUSTSEC-2021-0059",
"RUSTSEC-2020-0057",
"RUSTSEC-2021-0064",
# Comes from jsonrpc via Substrate: 'failure', 'net2', 'lock_api'
"RUSTSEC-2020-0036",
"RUSTSEC-2020-0077",
"RUSTSEC-2019-0036",
"RUSTSEC-2020-0070", "RUSTSEC-2020-0070",
# Comes from honggfuzz via storage-proof-fuzzer: 'memmap' # Comes from honggfuzz via storage-proof-fuzzer: 'memmap'
"RUSTSEC-2020-0077", "RUSTSEC-2020-0077",
# Comes from time: 'stweb' (will be fixed in upcoming time 0.3) # Comes from time: 'stweb' (will be fixed in upcoming time 0.3)
"RUSTSEC-2020-0056" "RUSTSEC-2020-0056",
# net2 (origin: Substrate RPC crates)
"RUSTSEC-2020-0016",
# Wasmtime (origin: Substrate executor crates)
"RUSTSEC-2021-0110",
# time (origin: Substrate RPC + benchmarking crates)
"RUSTSEC-2020-0071",
# chrono (origin: Substrate benchmarking + cli + ...)
"RUSTSEC-2020-0159",
] ]
# Threshold for security vulnerabilities, any vulnerability with a CVSS score # Threshold for security vulnerabilities, any vulnerability with a CVSS score
# lower than the range specified will be ignored. Note that ignored advisories # lower than the range specified will be ignored. Note that ignored advisories
@@ -85,7 +79,7 @@ ignore = [
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html # https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
[licenses] [licenses]
# The lint level for crates which do not have a detectable license # The lint level for crates which do not have a detectable license
unlicensed = "deny" unlicensed = "allow"
# List of explictly allowed licenses # List of explictly allowed licenses
# See https://spdx.org/licenses/ for list of possible licenses # See https://spdx.org/licenses/ for list of possible licenses
# [possible values: any SPDX 3.7 short identifier (+ optional exception)]. # [possible values: any SPDX 3.7 short identifier (+ optional exception)].
+4 -2
View File
@@ -93,7 +93,7 @@ seeds for the `sr25519` keys. This seed may also be used in the signer argument
and PoA relays. Example: and PoA relays. Example:
```bash ```bash
./substrate-relay relay-headers RialtoToMillau \ ./substrate-relay relay-headers rialto-to-millau \
--source-host rialto-node-alice \ --source-host rialto-node-alice \
--source-port 9944 \ --source-port 9944 \
--target-host millau-node-alice \ --target-host millau-node-alice \
@@ -121,7 +121,9 @@ Following accounts are used when `rialto-millau` bridge is running:
- Millau's `Eve` signs relay transactions with message delivery confirmations (lane 00000001) from Rialto to Millau; - Millau's `Eve` signs relay transactions with message delivery confirmations (lane 00000001) from Rialto to Millau;
- Rialto's `Eve` signs relay transactions with messages (lane 00000001) from Millau to Rialto; - Rialto's `Eve` signs relay transactions with messages (lane 00000001) from Millau to Rialto;
- Millau's `Ferdie` signs relay transactions with messages (lane 00000001) from Rialto to Millau; - Millau's `Ferdie` signs relay transactions with messages (lane 00000001) from Rialto to Millau;
- Rialto's `Ferdie` signs relay transactions with message delivery confirmations (lane 00000001) from Millau to Rialto. - Rialto's `Ferdie` signs relay transactions with message delivery confirmations (lane 00000001) from Millau to Rialto;
- Millau's `RialtoMessagesOwner` signs relay transactions with updated Rialto -> Millau conversion rate;
- Rialto's `MillauMessagesOwner` signs relay transactions with updated Millau -> Rialto conversion rate.
Following accounts are used when `westend-millau` bridge is running: Following accounts are used when `westend-millau` bridge is running:
@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
set -xeu set -xeu
sleep 20 sleep 60
curl -v http://poa-node-arthur:8545/api/health curl -v http://poa-node-arthur:8545/api/health
curl -v http://poa-node-bertha:8545/api/health curl -v http://poa-node-bertha:8545/api/health
curl -v http://poa-node-carlos:8545/api/health curl -v http://poa-node-carlos:8545/api/health
@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
set -xeu set -xeu
sleep 20 sleep 60
curl -v http://rialto-node-bob:9933/health curl -v http://rialto-node-bob:9933/health
curl -v http://poa-node-bertha:8545/api/health curl -v http://poa-node-bertha:8545/api/health
@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
set -xeu set -xeu
sleep 20 sleep 60
curl -v http://poa-node-arthur:8545/api/health curl -v http://poa-node-arthur:8545/api/health
curl -v http://poa-node-bertha:8545/api/health curl -v http://poa-node-bertha:8545/api/health
curl -v http://poa-node-carlos:8545/api/health curl -v http://poa-node-carlos:8545/api/health
@@ -471,7 +471,7 @@
} }
], ],
"executionErrorState": "alerting", "executionErrorState": "alerting",
"for": "5m", "for": "7m",
"frequency": "1m", "frequency": "1m",
"handler": 1, "handler": 1,
"name": "Messages from Millau to Rialto are not being delivered", "name": "Messages from Millau to Rialto are not being delivered",
@@ -896,7 +896,7 @@
} }
], ],
"executionErrorState": "alerting", "executionErrorState": "alerting",
"for": "5m", "for": "7m",
"frequency": "1m", "frequency": "1m",
"handler": 1, "handler": 1,
"name": "Messages (00000001) from Millau to Rialto are not being delivered", "name": "Messages (00000001) from Millau to Rialto are not being delivered",
@@ -967,8 +967,7 @@
"fill": true, "fill": true,
"line": true, "line": true,
"op": "lt", "op": "lt",
"value": 1, "value": 1
"yaxis": "left"
} }
], ],
"timeFrom": null, "timeFrom": null,
@@ -1155,6 +1154,249 @@
"alignLevel": null "alignLevel": null
} }
}, },
{
"alert": {
"alertRuleTags": {},
"conditions": [
{
"evaluator": {
"params": [
1
],
"type": "lt"
},
"operator": {
"type": "and"
},
"query": {
"params": [
"B",
"1m",
"now"
]
},
"reducer": {
"params": [],
"type": "max"
},
"type": "query"
}
],
"executionErrorState": "alerting",
"for": "5m",
"frequency": "1m",
"handler": 1,
"name": "Token swap messages from Millau to Rialto are not being delivered",
"noDataState": "no_data",
"notifications": []
},
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"custom": {},
"links": []
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 11,
"w": 12,
"x": 0,
"y": 38
},
"hiddenSeries": false,
"id": 23,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"percentage": false,
"pluginVersion": "7.1.3",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "label_replace(label_replace(Millau_to_Rialto_MessageLane_73776170_lane_state_nonces{type=~\"source_latest_generated|target_latest_received\"}, \"type\", \"Latest message sent from Rialto\", \"type\", \"source_latest_generated\"), \"type\", \"Latest message received by Millau\", \"type\", \"target_latest_received\")",
"interval": "",
"legendFormat": "{{type}}",
"refId": "A"
},
{
"expr": "increase(Millau_to_Rialto_MessageLane_73776170_lane_state_nonces{type=\"target_latest_received\"}[20m])",
"hide": true,
"interval": "",
"legendFormat": "Messages generated in last 5 minutes",
"refId": "B"
}
],
"thresholds": [
{
"colorMode": "critical",
"fill": true,
"line": true,
"op": "lt",
"value": 1
}
],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Delivery race (73776170)",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"custom": {},
"links": []
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 11,
"w": 12,
"x": 12,
"y": 38
},
"hiddenSeries": false,
"id": 24,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"percentage": false,
"pluginVersion": "7.1.3",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "label_replace(label_replace(Millau_to_Rialto_MessageLane_73776170_lane_state_nonces{type=~\"source_latest_confirmed|target_latest_received\"}, \"type\", \"Latest message confirmed by Rialto to Millau\", \"type\", \"source_latest_confirmed\"), \"type\", \"Latest message received by Millau\", \"type\", \"target_latest_received\")",
"interval": "",
"legendFormat": "{{type}}",
"refId": "A"
},
{
"expr": "increase(Millau_to_Rialto_MessageLane_73776170_lane_state_nonces{type=\"source_latest_confirmed\"}[10m])",
"hide": true,
"interval": "",
"legendFormat": "",
"refId": "B"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Confirmations race (73776170)",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{ {
"datasource": "Prometheus", "datasource": "Prometheus",
"fieldConfig": { "fieldConfig": {
@@ -1181,7 +1423,7 @@
"h": 8, "h": 8,
"w": 8, "w": 8,
"x": 0, "x": 0,
"y": 38 "y": 49
}, },
"id": 16, "id": 16,
"options": { "options": {
@@ -1230,7 +1472,7 @@
"h": 8, "h": 8,
"w": 8, "w": 8,
"x": 8, "x": 8,
"y": 38 "y": 49
}, },
"hiddenSeries": false, "hiddenSeries": false,
"id": 18, "id": 18,
@@ -1323,7 +1565,7 @@
"h": 8, "h": 8,
"w": 8, "w": 8,
"x": 16, "x": 16,
"y": 38 "y": 49
}, },
"hiddenSeries": false, "hiddenSeries": false,
"id": 20, "id": 20,
@@ -462,7 +462,7 @@
} }
], ],
"executionErrorState": "alerting", "executionErrorState": "alerting",
"for": "5m", "for": "7m",
"frequency": "1m", "frequency": "1m",
"handler": 1, "handler": 1,
"name": "Messages from Rialto to Millau are not being delivered", "name": "Messages from Rialto to Millau are not being delivered",
@@ -887,7 +887,7 @@
} }
], ],
"executionErrorState": "alerting", "executionErrorState": "alerting",
"for": "5m", "for": "7m",
"frequency": "1m", "frequency": "1m",
"handler": 1, "handler": 1,
"name": "Messages (00000001) from Rialto to Millau are not being delivered", "name": "Messages (00000001) from Rialto to Millau are not being delivered",
@@ -1,4 +1,4 @@
# Exposed ports: 10016, 10116, 10216, 10316, 10416 # Exposed ports: 10016, 10116, 10216, 10316, 10416, 10516, 10716
version: '3.5' version: '3.5'
services: services:
@@ -52,6 +52,7 @@ services:
relay-messages-millau-to-rialto-generator: relay-messages-millau-to-rialto-generator:
<<: *sub-bridge-relay <<: *sub-bridge-relay
environment: environment:
RUST_LOG: bridge=trace
MSG_EXCHANGE_GEN_SECONDARY_LANE: "00000001" MSG_EXCHANGE_GEN_SECONDARY_LANE: "00000001"
entrypoint: /entrypoints/relay-messages-to-rialto-generator-entrypoint.sh entrypoint: /entrypoints/relay-messages-to-rialto-generator-entrypoint.sh
ports: ports:
@@ -59,13 +60,24 @@ services:
depends_on: depends_on:
- relay-millau-rialto - relay-millau-rialto
relay-messages-millau-to-rialto-resubmitter:
<<: *sub-bridge-relay
environment:
RUST_LOG: bridge=trace
entrypoint: /entrypoints/relay-messages-to-rialto-resubmitter-entrypoint.sh
ports:
- "10316:9616"
depends_on:
- relay-messages-millau-to-rialto-generator
relay-messages-rialto-to-millau-lane-00000001: relay-messages-rialto-to-millau-lane-00000001:
<<: *sub-bridge-relay <<: *sub-bridge-relay
environment: environment:
RUST_LOG: bridge=trace
MSG_EXCHANGE_GEN_LANE: "00000001" MSG_EXCHANGE_GEN_LANE: "00000001"
entrypoint: /entrypoints/relay-messages-rialto-to-millau-entrypoint.sh entrypoint: /entrypoints/relay-messages-rialto-to-millau-entrypoint.sh
ports: ports:
- "10316:9616" - "10416:9616"
depends_on: depends_on:
- relay-millau-rialto - relay-millau-rialto
@@ -75,7 +87,15 @@ services:
MSG_EXCHANGE_GEN_SECONDARY_LANE: "00000001" MSG_EXCHANGE_GEN_SECONDARY_LANE: "00000001"
entrypoint: /entrypoints/relay-messages-to-millau-generator-entrypoint.sh entrypoint: /entrypoints/relay-messages-to-millau-generator-entrypoint.sh
ports: ports:
- "10416:9616" - "10516:9616"
depends_on:
- relay-millau-rialto
relay-token-swap-generator:
<<: *sub-bridge-relay
entrypoint: /entrypoints/relay-token-swap-generator-entrypoint.sh
ports:
- "10716:9616"
depends_on: depends_on:
- relay-millau-rialto - relay-millau-rialto
@@ -1,13 +1,13 @@
#!/bin/bash #!/bin/bash
set -xeu set -xeu
sleep 20 sleep 60
curl -v http://millau-node-bob:9933/health curl -v http://millau-node-bob:9933/health
curl -v http://rialto-node-bob:9933/health curl -v http://rialto-node-bob:9933/health
MESSAGE_LANE=${MSG_EXCHANGE_GEN_LANE:-00000000} MESSAGE_LANE=${MSG_EXCHANGE_GEN_LANE:-00000000}
/home/user/substrate-relay relay-messages MillauToRialto \ /home/user/substrate-relay relay-messages millau-to-rialto \
--lane $MESSAGE_LANE \ --lane $MESSAGE_LANE \
--source-host millau-node-bob \ --source-host millau-node-bob \
--source-port 9944 \ --source-port 9944 \
@@ -1,13 +1,13 @@
#!/bin/bash #!/bin/bash
set -xeu set -xeu
sleep 20 sleep 60
curl -v http://millau-node-bob:9933/health curl -v http://millau-node-bob:9933/health
curl -v http://rialto-node-bob:9933/health curl -v http://rialto-node-bob:9933/health
MESSAGE_LANE=${MSG_EXCHANGE_GEN_LANE:-00000000} MESSAGE_LANE=${MSG_EXCHANGE_GEN_LANE:-00000000}
/home/user/substrate-relay relay-messages RialtoToMillau \ /home/user/substrate-relay relay-messages rialto-to-millau \
--lane $MESSAGE_LANE \ --lane $MESSAGE_LANE \
--source-host rialto-node-bob \ --source-host rialto-node-bob \
--source-port 9944 \ --source-port 9944 \
@@ -14,7 +14,7 @@ SECONDARY_MESSAGE_LANE=${MSG_EXCHANGE_GEN_SECONDARY_LANE}
MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE=1024 MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE=1024
FERDIE_ADDR=5oSLwptwgySxh5vz1HdvznQJjbQVgwYSvHEpYYeTXu1Ei8j7 FERDIE_ADDR=5oSLwptwgySxh5vz1HdvznQJjbQVgwYSvHEpYYeTXu1Ei8j7
SHARED_CMD="/home/user/substrate-relay send-message RialtoToMillau" SHARED_CMD="/home/user/substrate-relay send-message rialto-to-millau"
SHARED_HOST="--source-host rialto-node-bob --source-port 9944" SHARED_HOST="--source-host rialto-node-bob --source-port 9944"
DAVE_SIGNER="--source-signer //Dave --target-signer //Dave" DAVE_SIGNER="--source-signer //Dave --target-signer //Dave"
@@ -25,6 +25,8 @@ rand_sleep() {
SUBMIT_DELAY_S=`shuf -i 0-$MAX_SUBMIT_DELAY_S -n 1` SUBMIT_DELAY_S=`shuf -i 0-$MAX_SUBMIT_DELAY_S -n 1`
echo "Sleeping $SUBMIT_DELAY_S seconds..." echo "Sleeping $SUBMIT_DELAY_S seconds..."
sleep $SUBMIT_DELAY_S sleep $SUBMIT_DELAY_S
NOW=`date "+%Y-%m-%d %H:%M:%S"`
echo "Woke up at $NOW"
} }
# start sending large messages immediately # start sending large messages immediately
@@ -32,6 +34,10 @@ LARGE_MESSAGES_TIME=0
# start sending message packs in a hour # start sending message packs in a hour
BUNCH_OF_MESSAGES_TIME=3600 BUNCH_OF_MESSAGES_TIME=3600
# give conversion rate updater some time to update Millau->Rialto conversion rate in Rialto
# (initially rate=1 and rational relayer won't deliver any messages if it'll be changed to larger value)
sleep 180
while true while true
do do
rand_sleep rand_sleep
@@ -46,6 +52,7 @@ do
$SEND_MESSAGE \ $SEND_MESSAGE \
--lane $SECONDARY_MESSAGE_LANE \ --lane $SECONDARY_MESSAGE_LANE \
--origin Target \ --origin Target \
--dispatch-fee-payment at-target-chain \
remark remark
fi fi
@@ -14,7 +14,7 @@ SECONDARY_MESSAGE_LANE=${MSG_EXCHANGE_GEN_SECONDARY_LANE}
MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE=128 MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE=128
FERDIE_ADDR=6ztG3jPnJTwgZnnYsgCDXbbQVR82M96hBZtPvkN56A9668ZC FERDIE_ADDR=6ztG3jPnJTwgZnnYsgCDXbbQVR82M96hBZtPvkN56A9668ZC
SHARED_CMD=" /home/user/substrate-relay send-message MillauToRialto" SHARED_CMD=" /home/user/substrate-relay send-message millau-to-rialto"
SHARED_HOST="--source-host millau-node-bob --source-port 9944" SHARED_HOST="--source-host millau-node-bob --source-port 9944"
DAVE_SIGNER="--target-signer //Dave --source-signer //Dave" DAVE_SIGNER="--target-signer //Dave --source-signer //Dave"
@@ -25,6 +25,8 @@ rand_sleep() {
SUBMIT_DELAY_S=`shuf -i 0-$MAX_SUBMIT_DELAY_S -n 1` SUBMIT_DELAY_S=`shuf -i 0-$MAX_SUBMIT_DELAY_S -n 1`
echo "Sleeping $SUBMIT_DELAY_S seconds..." echo "Sleeping $SUBMIT_DELAY_S seconds..."
sleep $SUBMIT_DELAY_S sleep $SUBMIT_DELAY_S
NOW=`date "+%Y-%m-%d %H:%M:%S"`
echo "Woke up at $NOW"
} }
# start sending large messages immediately # start sending large messages immediately
@@ -32,6 +34,10 @@ LARGE_MESSAGES_TIME=0
# start sending message packs in a hour # start sending message packs in a hour
BUNCH_OF_MESSAGES_TIME=3600 BUNCH_OF_MESSAGES_TIME=3600
# give conversion rate updater some time to update Rialto->Millau conversion rate in Millau
# (initially rate=1 and rational relayer won't deliver any messages if it'll be changed to larger value)
sleep 180
while true while true
do do
rand_sleep rand_sleep
@@ -46,6 +52,7 @@ do
$SEND_MESSAGE \ $SEND_MESSAGE \
--lane $SECONDARY_MESSAGE_LANE \ --lane $SECONDARY_MESSAGE_LANE \
--origin Target \ --origin Target \
--dispatch-fee-payment at-target-chain \
remark remark
fi fi
@@ -0,0 +1,26 @@
#!/bin/bash
set -xeu
sleep 20
curl -v http://millau-node-alice:9933/health
# //Dave is signing Millau -> Rialto message-send transactions, which are causing problems.
#
# When large message is being sent from Millau to Rialto AND other transactions are
# blocking it from being mined, we'll see something like this in logs:
#
# Millau transaction priority with tip=0: 17800827994. Target priority:
# 526186677695
#
# So since fee multiplier in Millau is `1` and `WeightToFee` is `IdentityFee`, then
# we need tip around `526186677695 - 17800827994 = 508_385_849_701`. Let's round it
# up to `1_000_000_000_000`.
/home/user/substrate-relay resubmit-transactions millau \
--target-host millau-node-alice \
--target-port 9944 \
--target-signer //Dave \
--stalled-blocks 5 \
--tip-limit 1000000000000 \
--tip-step 1000000000 \
make-it-best-transaction
@@ -1,18 +1,18 @@
#!/bin/bash #!/bin/bash
set -xeu set -xeu
sleep 20 sleep 60
curl -v http://millau-node-alice:9933/health curl -v http://millau-node-alice:9933/health
curl -v http://rialto-node-alice:9933/health curl -v http://rialto-node-alice:9933/health
/home/user/substrate-relay init-bridge MillauToRialto \ /home/user/substrate-relay init-bridge millau-to-rialto \
--source-host millau-node-alice \ --source-host millau-node-alice \
--source-port 9944 \ --source-port 9944 \
--target-host rialto-node-alice \ --target-host rialto-node-alice \
--target-port 9944 \ --target-port 9944 \
--target-signer //Alice --target-signer //Alice
/home/user/substrate-relay init-bridge RialtoToMillau \ /home/user/substrate-relay init-bridge rialto-to-millau \
--source-host rialto-node-alice \ --source-host rialto-node-alice \
--source-port 9944 \ --source-port 9944 \
--target-host millau-node-alice \ --target-host millau-node-alice \
@@ -26,8 +26,11 @@ sleep 6
--millau-host millau-node-alice \ --millau-host millau-node-alice \
--millau-port 9944 \ --millau-port 9944 \
--millau-signer //Charlie \ --millau-signer //Charlie \
--millau-messages-pallet-owner=//RialtoMessagesOwner \
--rialto-host rialto-node-alice \ --rialto-host rialto-node-alice \
--rialto-port 9944 \ --rialto-port 9944 \
--rialto-signer //Charlie \ --rialto-signer //Charlie \
--rialto-messages-pallet-owner=//MillauMessagesOwner \
--lane=00000000 \ --lane=00000000 \
--lane=73776170 \
--prometheus-host=0.0.0.0 --prometheus-host=0.0.0.0
@@ -0,0 +1,47 @@
#!/bin/bash
# THIS SCRIPT IS NOT INTENDED FOR USE IN PRODUCTION ENVIRONMENT
#
# This scripts periodically calls the Substrate relay binary to generate messages. These messages
# are sent from the Millau network to the Rialto network.
set -eu
# Max delay before submitting transactions (s)
MAX_SUBMIT_DELAY_S=60
SOURCE_HOST=millau-node-charlie
SOURCE_PORT=9944
TARGET_HOST=rialto-node-charlie
TARGET_PORT=9944
# Sleep a bit between messages
rand_sleep() {
SUBMIT_DELAY_S=`shuf -i 0-$MAX_SUBMIT_DELAY_S -n 1`
echo "Sleeping $SUBMIT_DELAY_S seconds..."
sleep $SUBMIT_DELAY_S
NOW=`date "+%Y-%m-%d %H:%M:%S"`
echo "Woke up at $NOW"
}
# give conversion rate updater some time to update Rialto->Millau conversion rate in Millau
# (initially rate=1 and rational relayer won't deliver any messages if it'll be changed to larger value)
sleep 180
while true
do
rand_sleep
echo "Initiating token-swap between Rialto and Millau"
/home/user/substrate-relay \
swap-tokens \
millau-to-rialto \
--source-host $SOURCE_HOST \
--source-port $SOURCE_PORT \
--source-signer //WithRialtoTokenSwap \
--source-balance 100000 \
--target-host $TARGET_HOST \
--target-port $TARGET_PORT \
--target-signer //WithMillauTokenSwap \
--target-balance 200000 \
lock-until-block \
--blocks-before-expire 32
done
@@ -24,7 +24,7 @@
{ {
"evaluator": { "evaluator": {
"params": [ "params": [
5 32
], ],
"type": "gt" "type": "gt"
}, },
@@ -46,11 +46,11 @@
} }
], ],
"executionErrorState": "alerting", "executionErrorState": "alerting",
"for": "5m", "for": "60m",
"frequency": "5m", "frequency": "5m",
"handler": 1, "handler": 1,
"message": "", "message": "",
"name": "Synced Header Difference is Over 5 (Westend to Millau)", "name": "Synced Header Difference is Over 32 (Westend to Millau)",
"noDataState": "no_data", "noDataState": "no_data",
"notifications": [] "notifications": []
}, },
@@ -163,7 +163,7 @@
{ {
"evaluator": { "evaluator": {
"params": [ "params": [
5 32
], ],
"type": "lt" "type": "lt"
}, },
@@ -185,7 +185,7 @@
} }
], ],
"executionErrorState": "alerting", "executionErrorState": "alerting",
"for": "3m", "for": "60m",
"frequency": "5m", "frequency": "5m",
"handler": 1, "handler": 1,
"name": "No New Headers (Westend to Millau)", "name": "No New Headers (Westend to Millau)",
@@ -237,9 +237,9 @@
"steppedLine": false, "steppedLine": false,
"targets": [ "targets": [
{ {
"expr": "max_over_time(Westend_to_Millau_Sync_best_block_numbers{node=\"source\"}[2m])-min_over_time(Westend_to_Millau_Sync_best_block_numbers{node=\"source\"}[2m])", "expr": "max_over_time(Westend_to_Millau_Sync_best_block_numbers{node=\"source\"}[10m])-min_over_time(Westend_to_Millau_Sync_best_block_numbers{node=\"source\"}[10m])",
"interval": "", "interval": "",
"legendFormat": "Number of new Headers on Westend (Last 2 Mins)", "legendFormat": "Number of new Headers on Westend (Last 10 Mins)",
"refId": "A" "refId": "A"
} }
], ],
@@ -1,11 +1,11 @@
#!/bin/bash #!/bin/bash
set -xeu set -xeu
sleep 20 sleep 60
curl -v http://millau-node-alice:9933/health curl -v http://millau-node-alice:9933/health
curl -v https://westend-rpc.polkadot.io:443/health curl -v https://westend-rpc.polkadot.io:443/health
/home/user/substrate-relay init-bridge WestendToMillau \ /home/user/substrate-relay init-bridge westend-to-millau \
--source-host westend-rpc.polkadot.io \ --source-host westend-rpc.polkadot.io \
--source-port 443 \ --source-port 443 \
--source-secure \ --source-secure \
@@ -15,11 +15,12 @@ curl -v https://westend-rpc.polkadot.io:443/health
# Give chain a little bit of time to process initialization transaction # Give chain a little bit of time to process initialization transaction
sleep 6 sleep 6
/home/user/substrate-relay relay-headers WestendToMillau \ /home/user/substrate-relay relay-headers westend-to-millau \
--source-host westend-rpc.polkadot.io \ --source-host westend-rpc.polkadot.io \
--source-port 443 \ --source-port 443 \
--source-secure \ --source-secure \
--target-host millau-node-alice \ --target-host millau-node-alice \
--target-port 9944 \ --target-port 9944 \
--target-signer //George \ --target-signer //George \
--target-transactions-mortality=4\
--prometheus-host=0.0.0.0 --prometheus-host=0.0.0.0
@@ -8,14 +8,14 @@
set -xeu set -xeu
RUST_LOG=rpc=trace,bridge=trace ./target/debug/substrate-relay init-bridge RococoToWococo \ RUST_LOG=rpc=trace,bridge=trace ./target/debug/substrate-relay init-bridge rococo-to-wococo \
--source-host 127.0.0.1 \ --source-host 127.0.0.1 \
--source-port 9955 \ --source-port 9955 \
--target-host 127.0.0.1 \ --target-host 127.0.0.1 \
--target-port 9944 \ --target-port 9944 \
--target-signer //Alice --target-signer //Alice
RUST_LOG=rpc=trace,bridge=trace ./target/debug/substrate-relay relay-headers RococoToWococo \ RUST_LOG=rpc=trace,bridge=trace ./target/debug/substrate-relay relay-headers rococo-to-wococo \
--source-host 127.0.0.1 \ --source-host 127.0.0.1 \
--source-port 9955 \ --source-port 9955 \
--target-host 127.0.0.1 \ --target-host 127.0.0.1 \
@@ -8,14 +8,14 @@
set -xeu set -xeu
RUST_LOG=rpc=trace,bridge=trace ./target/debug/substrate-relay init-bridge WococoToRococo \ RUST_LOG=rpc=trace,bridge=trace ./target/debug/substrate-relay init-bridge wococo-to-rococo \
--source-host 127.0.0.1 \ --source-host 127.0.0.1 \
--source-port 9944 \ --source-port 9944 \
--target-host 127.0.0.1 \ --target-host 127.0.0.1 \
--target-port 9955 \ --target-port 9955 \
--target-signer //Alice --target-signer //Alice
RUST_LOG=rpc=trace,bridge=trace ./target/debug/substrate-relay relay-headers WococoToRococo \ RUST_LOG=rpc=trace,bridge=trace ./target/debug/substrate-relay relay-headers wococo-to-rococo \
--source-host 127.0.0.1 \ --source-host 127.0.0.1 \
--source-port 9944 \ --source-port 9944 \
--target-host 127.0.0.1 \ --target-host 127.0.0.1 \
@@ -9,7 +9,7 @@ MILLAU_PORT="${MILLAU_PORT:-9945}"
RIALTO_PORT="${RIALTO_PORT:-9944}" RIALTO_PORT="${RIALTO_PORT:-9944}"
RUST_LOG=bridge=debug \ RUST_LOG=bridge=debug \
./target/debug/substrate-relay relay-messages MillauToRialto \ ./target/debug/substrate-relay relay-messages millau-to-rialto \
--lane 00000000 \ --lane 00000000 \
--source-host localhost \ --source-host localhost \
--source-port $MILLAU_PORT \ --source-port $MILLAU_PORT \
@@ -9,7 +9,7 @@ MILLAU_PORT="${MILLAU_PORT:-9945}"
RIALTO_PORT="${RIALTO_PORT:-9944}" RIALTO_PORT="${RIALTO_PORT:-9944}"
RUST_LOG=bridge=debug \ RUST_LOG=bridge=debug \
./target/debug/substrate-relay relay-messages RialtoToMillau \ ./target/debug/substrate-relay relay-messages rialto-to-millau \
--lane 00000000 \ --lane 00000000 \
--source-host localhost \ --source-host localhost \
--source-port $RIALTO_PORT \ --source-port $RIALTO_PORT \
@@ -9,7 +9,7 @@ MILLAU_PORT="${MILLAU_PORT:-9945}"
RIALTO_PORT="${RIALTO_PORT:-9944}" RIALTO_PORT="${RIALTO_PORT:-9944}"
RUST_LOG=bridge=debug \ RUST_LOG=bridge=debug \
./target/debug/substrate-relay init-bridge MillauToRialto \ ./target/debug/substrate-relay init-bridge millau-to-rialto \
--source-host localhost \ --source-host localhost \
--source-port $MILLAU_PORT \ --source-port $MILLAU_PORT \
--target-host localhost \ --target-host localhost \
@@ -18,7 +18,7 @@ RUST_LOG=bridge=debug \
sleep 5 sleep 5
RUST_LOG=bridge=debug \ RUST_LOG=bridge=debug \
./target/debug/substrate-relay relay-headers MillauToRialto \ ./target/debug/substrate-relay relay-headers millau-to-rialto \
--source-host localhost \ --source-host localhost \
--source-port $MILLAU_PORT \ --source-port $MILLAU_PORT \
--target-host localhost \ --target-host localhost \
@@ -9,7 +9,7 @@ MILLAU_PORT="${MILLAU_PORT:-9945}"
RIALTO_PORT="${RIALTO_PORT:-9944}" RIALTO_PORT="${RIALTO_PORT:-9944}"
RUST_LOG=bridge=debug \ RUST_LOG=bridge=debug \
./target/debug/substrate-relay init-bridge RialtoToMillau \ ./target/debug/substrate-relay init-bridge rialto-to-millau \
--target-host localhost \ --target-host localhost \
--target-port $MILLAU_PORT \ --target-port $MILLAU_PORT \
--source-host localhost \ --source-host localhost \
@@ -18,7 +18,7 @@ RUST_LOG=bridge=debug \
sleep 5 sleep 5
RUST_LOG=bridge=debug \ RUST_LOG=bridge=debug \
./target/debug/substrate-relay relay-headers RialtoToMillau \ ./target/debug/substrate-relay relay-headers rialto-to-millau \
--target-host localhost \ --target-host localhost \
--target-port $MILLAU_PORT \ --target-port $MILLAU_PORT \
--source-host localhost \ --source-host localhost \
@@ -0,0 +1,14 @@
#!/bin/bash
set -xeu
/home/user/rialto-bridge-node build-spec \
--chain local \
--raw \
--disable-default-bootnode \
> /rialto-share/rialto-relaychain-spec-raw.json
# we're using local driver + tmpfs for shared `/rialto-share` volume, which is populated
# by the container running this script. If this script ends, the volume will be detached
# and our chain spec will be lost when it'll go online again. Hence the never-ending
# script which keeps volume online until container is stopped.
tail -f /dev/null
@@ -0,0 +1,13 @@
#!/bin/bash
set -xeu
sleep 60
curl -v http://rialto-node-alice:9933/health
curl -v http://rialto-parachain-collator-alice:9933/health
/home/user/substrate-relay register-parachain rialto-parachain \
--parachain-host rialto-parachain-collator-alice \
--parachain-port 9944 \
--relaychain-host rialto-node-alice \
--relaychain-port 9944 \
--relaychain-signer //Alice
@@ -20,7 +20,7 @@ services:
- --unsafe-rpc-external - --unsafe-rpc-external
- --unsafe-ws-external - --unsafe-ws-external
environment: environment:
RUST_LOG: runtime=trace,rpc=debug,txpool=trace,runtime::bridge=trace RUST_LOG: runtime=trace,rpc=debug,txpool=trace,runtime::bridge=trace,sc_basic_authorship=trace
ports: ports:
- "19933:9933" - "19933:9933"
- "19944:9944" - "19944:9944"
@@ -0,0 +1,90 @@
# Compose file for quickly spinning up a local instance of the Rialto Parachain network.
#
# Since Rialto Parachain is unusable without Rialto, this file depends on some Rialto
# network nodes.
version: '3.5'
services:
rialto-parachain-collator-alice: &rialto-parachain-collator
image: paritytech/rialto-parachain-collator
entrypoint: >
/home/user/rialto-parachain-collator
--alice
--collator
--force-authoring
--parachain-id 2000
--rpc-port 9933
--ws-port 9944
--rpc-cors=all
--unsafe-rpc-external
--unsafe-ws-external
--
--execution wasm
--chain /rialto-share/rialto-relaychain-spec-raw.json
--rpc-port 9934
--ws-port 9945
volumes:
- rialto-share:/rialto-share:z
environment:
RUST_LOG: runtime=trace,rpc=trace,txpool=trace,parachain=trace,parity_ws=trace
depends_on:
- rialto-chainspec-exporter
ports:
- "20433:9933"
- "20444:9944"
rialto-parachain-collator-bob:
<<: *rialto-parachain-collator
entrypoint: >
/home/user/rialto-parachain-collator
--bob
--collator
--force-authoring
--parachain-id 2000
--rpc-port 9933
--ws-port 9944
--rpc-cors=all
--unsafe-rpc-external
--unsafe-ws-external
--
--execution wasm
--chain /rialto-share/rialto-relaychain-spec-raw.json
--rpc-port 9934
--ws-port 9945
ports:
- "20533:9933"
- "20544:9944"
rialto-parachain-collator-charlie:
<<: *rialto-parachain-collator
entrypoint: >
/home/user/rialto-parachain-collator
--charlie
--collator
--force-authoring
--parachain-id 2000
--rpc-port 9933
--ws-port 9944
--rpc-cors=all
--unsafe-rpc-external
--unsafe-ws-external
--
--execution wasm
--chain /rialto-share/rialto-relaychain-spec-raw.json
--rpc-port 9934
--ws-port 9945
ports:
- "20633:9933"
- "20644:9944"
rialto-parachain-registrar:
image: paritytech/substrate-relay
entrypoint: /entrypoints/rialto-parachain-registrar-entrypoint.sh
volumes:
- ./networks/entrypoints:/entrypoints
- rialto-share:/rialto-share:z
environment:
RUST_LOG: bridge=trace
depends_on:
- rialto-node-alice
- rialto-parachain-collator-alice
@@ -85,3 +85,20 @@ services:
ports: ports:
- "10333:9933" - "10333:9933"
- "10344:9944" - "10344:9944"
rialto-chainspec-exporter:
image: paritytech/rialto-bridge-node
entrypoint: /entrypoints/rialto-chainspec-exporter-entrypoint.sh
volumes:
- ./networks/entrypoints:/entrypoints
- rialto-share:/rialto-share:z
# we're using `/rialto-share` to expose Rialto chain spec to those who are interested. Right
# now it is Rialto Parachain collator nodes. Local + tmpfs combination allows sharing writable
# in-memory volumes, which are dropped when containers are stopped.
volumes:
rialto-share:
driver: local
driver_opts:
type: "tmpfs"
device: "tmpfs"
+9 -2
View File
@@ -36,16 +36,18 @@ function show_help () {
echo " " echo " "
echo "Options:" echo "Options:"
echo " --no-monitoring Disable monitoring" echo " --no-monitoring Disable monitoring"
echo " --no-ui Disable UI"
echo " " echo " "
echo "You can start multiple bridges at once by passing several bridge names:" echo "You can start multiple bridges at once by passing several bridge names:"
echo " ./run.sh poa-rialto rialto-millau westend-millau [stop|update]" echo " ./run.sh poa-rialto rialto-millau westend-millau [stop|update]"
exit 1 exit 1
} }
RIALTO=' -f ./networks/rialto.yml' RIALTO=' -f ./networks/rialto.yml -f ./networks/rialto-parachain.yml'
MILLAU=' -f ./networks/millau.yml' MILLAU=' -f ./networks/millau.yml'
ETH_POA=' -f ./networks/eth-poa.yml' ETH_POA=' -f ./networks/eth-poa.yml'
MONITORING=' -f ./monitoring/docker-compose.yml' MONITORING=' -f ./monitoring/docker-compose.yml'
UI=' -f ./ui/docker-compose.yml'
BRIDGES=() BRIDGES=()
NETWORKS='' NETWORKS=''
@@ -58,6 +60,11 @@ do
shift shift
continue continue
;; ;;
--no-ui)
UI=""
shift
continue
;;
poa-rialto) poa-rialto)
BRIDGES+=($i) BRIDGES+=($i)
NETWORKS+=${RIALTO} NETWORKS+=${RIALTO}
@@ -94,7 +101,7 @@ if [ ${#BRIDGES[@]} -eq 0 ]; then
show_help "Missing bridge name." show_help "Missing bridge name."
fi fi
COMPOSE_FILES=$NETWORKS$MONITORING COMPOSE_FILES=$NETWORKS$MONITORING$UI
# Compose looks for .env files in the the current directory by default, we don't want that # Compose looks for .env files in the the current directory by default, we don't want that
COMPOSE_ARGS="--project-directory ." COMPOSE_ARGS="--project-directory ."
@@ -1,5 +1,7 @@
{ {
"--1": "Millau Types", "--1": "Millau Types",
"MillauAddress": "AccountId",
"MillauLookupSource": "AccountId",
"MillauBalance": "u64", "MillauBalance": "u64",
"MillauBlockHash": "H512", "MillauBlockHash": "H512",
"MillauBlockNumber": "u64", "MillauBlockNumber": "u64",
@@ -25,6 +27,8 @@
} }
}, },
"--2": "Rialto Types", "--2": "Rialto Types",
"RialtoAddress": "MultiAddress",
"RialtoLookupSource": "MultiAddress",
"RialtoBalance": "u128", "RialtoBalance": "u128",
"RialtoBlockHash": "H256", "RialtoBlockHash": "H256",
"RialtoBlockNumber": "u32", "RialtoBlockNumber": "u32",
@@ -50,8 +54,6 @@
} }
}, },
"--3": "Common types", "--3": "Common types",
"Address": "AccountId",
"LookupSource": "AccountId",
"AccountSigner": "MultiSigner", "AccountSigner": "MultiSigner",
"SpecVersion": "u32", "SpecVersion": "u32",
"RelayerId": "AccountId", "RelayerId": "AccountId",
@@ -70,7 +72,7 @@
"ChainId": "Id", "ChainId": "Id",
"LaneId": "Id", "LaneId": "Id",
"MessageNonce": "u64", "MessageNonce": "u64",
"MessageId": "(Id, u64)", "BridgeMessageId": "(Id, u64)",
"MessageKey": { "MessageKey": {
"lane_id": "LaneId", "lane_id": "LaneId",
"nonce:": "MessageNonce" "nonce:": "MessageNonce"
@@ -90,9 +92,9 @@
"dispatch_results": "BitVec" "dispatch_results": "BitVec"
}, },
"OutboundLaneData": { "OutboundLaneData": {
"latest_generated_nonce": "MessageNonce", "oldest_unpruned_nonce": "MessageNonce",
"latest_received_nonce": "MessageNonce", "latest_received_nonce": "MessageNonce",
"oldest_unpruned_nonce": "MessageNonce" "latest_generated_nonce": "MessageNonce"
}, },
"MessageData": { "MessageData": {
"payload": "MessagePayload", "payload": "MessagePayload",
@@ -172,6 +174,8 @@
"commit": "Commit", "commit": "Commit",
"votes_ancestries": "Vec<BridgedHeader>" "votes_ancestries": "Vec<BridgedHeader>"
}, },
"Address": "MillauAddress",
"LookupSource": "MillauLookupSource",
"Fee": "MillauBalance", "Fee": "MillauBalance",
"Balance": "MillauBalance", "Balance": "MillauBalance",
"Hash": "MillauBlockHash", "Hash": "MillauBlockHash",
+11 -6
View File
@@ -1,5 +1,7 @@
{ {
"--1": "Millau Types", "--1": "Millau Types",
"MillauAddress": "AccountId",
"MillauLookupSource": "AccountId",
"MillauBalance": "u64", "MillauBalance": "u64",
"MillauBlockHash": "H512", "MillauBlockHash": "H512",
"MillauBlockNumber": "u64", "MillauBlockNumber": "u64",
@@ -25,6 +27,8 @@
} }
}, },
"--2": "Rialto Types", "--2": "Rialto Types",
"RialtoAddress": "MultiAddress",
"RialtoLookupSource": "MultiAddress",
"RialtoBalance": "u128", "RialtoBalance": "u128",
"RialtoBlockHash": "H256", "RialtoBlockHash": "H256",
"RialtoBlockNumber": "u32", "RialtoBlockNumber": "u32",
@@ -50,8 +54,6 @@
} }
}, },
"--3": "Common types", "--3": "Common types",
"Address": "AccountId",
"LookupSource": "AccountId",
"AccountSigner": "MultiSigner", "AccountSigner": "MultiSigner",
"SpecVersion": "u32", "SpecVersion": "u32",
"RelayerId": "AccountId", "RelayerId": "AccountId",
@@ -70,7 +72,7 @@
"ChainId": "Id", "ChainId": "Id",
"LaneId": "Id", "LaneId": "Id",
"MessageNonce": "u64", "MessageNonce": "u64",
"MessageId": "(Id, u64)", "BridgeMessageId": "(Id, u64)",
"MessageKey": { "MessageKey": {
"lane_id": "LaneId", "lane_id": "LaneId",
"nonce:": "MessageNonce" "nonce:": "MessageNonce"
@@ -90,9 +92,9 @@
"dispatch_results": "BitVec" "dispatch_results": "BitVec"
}, },
"OutboundLaneData": { "OutboundLaneData": {
"latest_generated_nonce": "MessageNonce", "oldest_unpruned_nonce": "MessageNonce",
"latest_received_nonce": "MessageNonce", "latest_received_nonce": "MessageNonce",
"oldest_unpruned_nonce": "MessageNonce" "latest_generated_nonce": "MessageNonce"
}, },
"MessageData": { "MessageData": {
"payload": "MessagePayload", "payload": "MessagePayload",
@@ -172,6 +174,8 @@
"commit": "Commit", "commit": "Commit",
"votes_ancestries": "Vec<BridgedHeader>" "votes_ancestries": "Vec<BridgedHeader>"
}, },
"Address": "RialtoAddress",
"LookupSource": "RialtoLookupSource",
"Fee": "RialtoBalance", "Fee": "RialtoBalance",
"Balance": "RialtoBalance", "Balance": "RialtoBalance",
"BlockHash": "RialtoBlockHash", "BlockHash": "RialtoBlockHash",
@@ -183,5 +187,6 @@
"_enum": { "_enum": {
"RialtoToMillauConversionRate": "u128" "RialtoToMillauConversionRate": "u128"
} }
} },
"ValidationCodeHash": "H256"
} }
@@ -1,17 +1,19 @@
{ {
"--1": "Rococo Types", "--1": "Rococo Types",
"RococoAddress": "AccountId",
"RococoLookupSource": "AccountId",
"RococoBalance": "u128", "RococoBalance": "u128",
"RococoBlockHash": "H256", "RococoBlockHash": "H256",
"RococoBlockNumber": "u32", "RococoBlockNumber": "u32",
"RococoHeader": "Header", "RococoHeader": "Header",
"--2": "Wococo Types", "--2": "Wococo Types",
"WococoAddress": "AccountId",
"WococoLookupSource": "AccountId",
"WococoBalance": "RococoBalance", "WococoBalance": "RococoBalance",
"WococoBlockHash": "RococoBlockHash", "WococoBlockHash": "RococoBlockHash",
"WococoBlockNumber": "RococoBlockNumber", "WococoBlockNumber": "RococoBlockNumber",
"WococoHeader": "RococoHeader", "WococoHeader": "RococoHeader",
"--3": "Common types", "--3": "Common types",
"Address": "AccountId",
"LookupSource": "AccountId",
"AccountSigner": "MultiSigner", "AccountSigner": "MultiSigner",
"SpecVersion": "u32", "SpecVersion": "u32",
"RelayerId": "AccountId", "RelayerId": "AccountId",
@@ -30,7 +32,7 @@
"ChainId": "Id", "ChainId": "Id",
"LaneId": "Id", "LaneId": "Id",
"MessageNonce": "u64", "MessageNonce": "u64",
"MessageId": "(Id, u64)", "BridgeMessageId": "(Id, u64)",
"MessageKey": { "MessageKey": {
"lane_id": "LaneId", "lane_id": "LaneId",
"nonce:": "MessageNonce" "nonce:": "MessageNonce"
@@ -50,9 +52,9 @@
"dispatch_results": "BitVec" "dispatch_results": "BitVec"
}, },
"OutboundLaneData": { "OutboundLaneData": {
"latest_generated_nonce": "MessageNonce", "oldest_unpruned_nonce": "MessageNonce",
"latest_received_nonce": "MessageNonce", "latest_received_nonce": "MessageNonce",
"oldest_unpruned_nonce": "MessageNonce" "latest_generated_nonce": "MessageNonce"
}, },
"MessageData": { "MessageData": {
"payload": "MessagePayload", "payload": "MessagePayload",
@@ -132,6 +134,8 @@
"commit": "Commit", "commit": "Commit",
"votes_ancestries": "Vec<BridgedHeader>" "votes_ancestries": "Vec<BridgedHeader>"
}, },
"Address": "RococoAddress",
"LookupSource": "RococoLookupSource",
"Fee": "RococoBalance", "Fee": "RococoBalance",
"Balance": "RococoBalance", "Balance": "RococoBalance",
"BlockHash": "RococoBlockHash", "BlockHash": "RococoBlockHash",
@@ -1,17 +1,19 @@
{ {
"--1": "Rococo Types", "--1": "Rococo Types",
"RococoAddress": "AccountId",
"RococoLookupSource": "AccountId",
"RococoBalance": "u128", "RococoBalance": "u128",
"RococoBlockHash": "H256", "RococoBlockHash": "H256",
"RococoBlockNumber": "u32", "RococoBlockNumber": "u32",
"RococoHeader": "Header", "RococoHeader": "Header",
"--2": "Wococo Types", "--2": "Wococo Types",
"WococoAddress": "AccountId",
"WococoLookupSource": "AccountId",
"WococoBalance": "RococoBalance", "WococoBalance": "RococoBalance",
"WococoBlockHash": "RococoBlockHash", "WococoBlockHash": "RococoBlockHash",
"WococoBlockNumber": "RococoBlockNumber", "WococoBlockNumber": "RococoBlockNumber",
"WococoHeader": "RococoHeader", "WococoHeader": "RococoHeader",
"--3": "Common types", "--3": "Common types",
"Address": "AccountId",
"LookupSource": "AccountId",
"AccountSigner": "MultiSigner", "AccountSigner": "MultiSigner",
"SpecVersion": "u32", "SpecVersion": "u32",
"RelayerId": "AccountId", "RelayerId": "AccountId",
@@ -30,7 +32,7 @@
"ChainId": "Id", "ChainId": "Id",
"LaneId": "Id", "LaneId": "Id",
"MessageNonce": "u64", "MessageNonce": "u64",
"MessageId": "(Id, u64)", "BridgeMessageId": "(Id, u64)",
"MessageKey": { "MessageKey": {
"lane_id": "LaneId", "lane_id": "LaneId",
"nonce:": "MessageNonce" "nonce:": "MessageNonce"
@@ -50,9 +52,9 @@
"dispatch_results": "BitVec" "dispatch_results": "BitVec"
}, },
"OutboundLaneData": { "OutboundLaneData": {
"latest_generated_nonce": "MessageNonce", "oldest_unpruned_nonce": "MessageNonce",
"latest_received_nonce": "MessageNonce", "latest_received_nonce": "MessageNonce",
"oldest_unpruned_nonce": "MessageNonce" "latest_generated_nonce": "MessageNonce"
}, },
"MessageData": { "MessageData": {
"payload": "MessagePayload", "payload": "MessagePayload",
@@ -132,6 +134,8 @@
"commit": "Commit", "commit": "Commit",
"votes_ancestries": "Vec<BridgedHeader>" "votes_ancestries": "Vec<BridgedHeader>"
}, },
"Address": "WococoAddress",
"LookupSource": "WococoLookupSource",
"Fee": "WococoBalance", "Fee": "WococoBalance",
"Balance": "WococoBalance", "Balance": "WococoBalance",
"Hash": "WococoBlockHash", "Hash": "WococoBlockHash",
@@ -1,7 +1,5 @@
{ {
"--3": "Common types", "--3": "Common types",
"Address": "AccountId",
"LookupSource": "AccountId",
"AccountSigner": "MultiSigner", "AccountSigner": "MultiSigner",
"SpecVersion": "u32", "SpecVersion": "u32",
"RelayerId": "AccountId", "RelayerId": "AccountId",
@@ -20,7 +18,7 @@
"ChainId": "Id", "ChainId": "Id",
"LaneId": "Id", "LaneId": "Id",
"MessageNonce": "u64", "MessageNonce": "u64",
"MessageId": "(Id, u64)", "BridgeMessageId": "(Id, u64)",
"MessageKey": { "MessageKey": {
"lane_id": "LaneId", "lane_id": "LaneId",
"nonce:": "MessageNonce" "nonce:": "MessageNonce"
@@ -40,9 +38,10 @@
"dispatch_results": "BitVec" "dispatch_results": "BitVec"
}, },
"OutboundLaneData": { "OutboundLaneData": {
"latest_generated_nonce": "MessageNonce", "oldest_unpruned_nonce": "MessageNonce",
"latest_received_nonce": "MessageNonce", "latest_received_nonce": "MessageNonce",
"oldest_unpruned_nonce": "MessageNonce" "latest_generated_nonce": "MessageNonce"
}, },
"MessageData": { "MessageData": {
"payload": "MessagePayload", "payload": "MessagePayload",
@@ -1,4 +1,6 @@
{ {
"Address": "MillauAddress",
"LookupSource": "MillauLookupSource",
"Fee": "MillauBalance", "Fee": "MillauBalance",
"Balance": "MillauBalance", "Balance": "MillauBalance",
"Hash": "MillauBlockHash", "Hash": "MillauBlockHash",
@@ -1,5 +1,7 @@
{ {
"--1": "Millau Types", "--1": "Millau Types",
"MillauAddress": "AccountId",
"MillauLookupSource": "AccountId",
"MillauBalance": "u64", "MillauBalance": "u64",
"MillauBlockHash": "H512", "MillauBlockHash": "H512",
"MillauBlockNumber": "u64", "MillauBlockNumber": "u64",
@@ -25,6 +27,8 @@
} }
}, },
"--2": "Rialto Types", "--2": "Rialto Types",
"RialtoAddress": "MultiAddress",
"RialtoLookupSource": "MultiAddress",
"RialtoBalance": "u128", "RialtoBalance": "u128",
"RialtoBlockHash": "H256", "RialtoBlockHash": "H256",
"RialtoBlockNumber": "u32", "RialtoBlockNumber": "u32",
@@ -1,4 +1,6 @@
{ {
"Address": "RialtoAddress",
"LookupSource": "RialtoLookupSource",
"Fee": "RialtoBalance", "Fee": "RialtoBalance",
"Balance": "RialtoBalance", "Balance": "RialtoBalance",
"BlockHash": "RialtoBlockHash", "BlockHash": "RialtoBlockHash",
@@ -10,5 +12,6 @@
"_enum": { "_enum": {
"RialtoToMillauConversionRate": "u128" "RialtoToMillauConversionRate": "u128"
} }
} },
"ValidationCodeHash": "H256"
} }
@@ -1,10 +1,14 @@
{ {
"--1": "Rococo Types", "--1": "Rococo Types",
"RococoAddress": "AccountId",
"RococoLookupSource": "AccountId",
"RococoBalance": "u128", "RococoBalance": "u128",
"RococoBlockHash": "H256", "RococoBlockHash": "H256",
"RococoBlockNumber": "u32", "RococoBlockNumber": "u32",
"RococoHeader": "Header", "RococoHeader": "Header",
"--2": "Wococo Types", "--2": "Wococo Types",
"WococoAddress": "AccountId",
"WococoLookupSource": "AccountId",
"WococoBalance": "RococoBalance", "WococoBalance": "RococoBalance",
"WococoBlockHash": "RococoBlockHash", "WococoBlockHash": "RococoBlockHash",
"WococoBlockNumber": "RococoBlockNumber", "WococoBlockNumber": "RococoBlockNumber",
@@ -1,4 +1,6 @@
{ {
"Address": "RococoAddress",
"LookupSource": "RococoLookupSource",
"Fee": "RococoBalance", "Fee": "RococoBalance",
"Balance": "RococoBalance", "Balance": "RococoBalance",
"BlockHash": "RococoBlockHash", "BlockHash": "RococoBlockHash",
@@ -1,4 +1,6 @@
{ {
"Address": "WococoAddress",
"LookupSource": "WococoLookupSource",
"Fee": "WococoBalance", "Fee": "WococoBalance",
"Balance": "WococoBalance", "Balance": "WococoBalance",
"Hash": "WococoBlockHash", "Hash": "WococoBlockHash",
+23
View File
@@ -0,0 +1,23 @@
# bridges-ui
This is a Bridges UI docker configuration file. The source of the Bridges UI code
can be found in [the repository](https://github.com/paritytech/parity-bridges-ui).
The CI should create and publish a docker image that is used by this configuration
file, so that the code is always using the latest version.
The UI is configured to point to local Rialto and Millau nodes to retrieve the require
data.
This image can be used together with `nginx-proxy` to expose the UI externally. See
`VIRTUAL_*` and `LETSENCRYPT_*` environment variables.
After start the UI is available at `http://localhost:8080`
## How to?
In current directory:
```bash
docker-compose up -d
```
Then start `rialto` & `millau` networks with the same command (one folder up) or
run the full setup by using `../run.sh` script.
@@ -0,0 +1,13 @@
version: '3.5'
services:
bridges-ui:
image: paritytech/parity-bridges-ui
environment:
VIRTUAL_HOST: ui.brucke.link
VIRTUAL_PORT: 80
LETSENCRYPT_HOST: ui.brucke.link
LETSENCRYPT_EMAIL: admin@parity.io
CHAIN_1_SUBSTRATE_PROVIDER: ws://localhost:9944
CHAIN_2_SUBSTRATE_PROVIDER: ws://localhost:19944
ports:
- "8080:80"
+8 -20
View File
@@ -48,33 +48,21 @@ High level sequence charts of the process can be found in [a separate document](
### Substrate (GRANDPA) Header Sync ### Substrate (GRANDPA) Header Sync
The header sync pallet (`pallet-substrate-bridge`) is an on-chain light client for chains which use The header sync pallet (`pallet-bridge-grandpa`) is an on-chain light client for chains which use
GRANDPA finality. It is part of the target chain's runtime, and accepts headers from the source GRANDPA finality. It is part of the target chain's runtime, and accepts finality proofs from the source
chain. Its main goals are to accept valid headers, track GRANDPA finality set changes, and verify chain. Verify GRANDPA finality proofs (a.k.a justifications) and track GRANDPA finality set changes.
GRANDPA finality proofs (a.k.a justifications).
The pallet does not care about what block production mechanism is used for the source chain The pallet does not care about what block production mechanism is used for the source chain
(e.g Aura or BABE) as long as it uses the GRANDPA finality gadget. Due to this it is possible for (e.g Aura or BABE) as long as it uses the GRANDPA finality gadget. In fact the pallet does not
the pallet to import (but not necessarily finalize) headers which are _not_ valid according to the necessarily store all produced headers, we only import headers with valid GRANDPA justifications.
source chain's block production mechanism.
The pallet has support for tracking forks and uses the longest chain rule to determine what the Referer to the [pallet documentation](../modules/grandpa/src/lib.rs) for more details.
canonical chain is. The pallet allows headers to be imported on a different fork from the canonical
one as long as the headers being imported don't conflict with already finalized headers (for
example, it will not allow importing a header at a lower height than the best finalized header).
When tracking authority set changes, the pallet - unlike the full GRANDPA protocol - does not
support tracking multiple authority set changes across forks. Each fork can have at most one pending
authority set change. This is done to prevent DoS attacks if GRANDPA on the source chain were to
stall for a long time (the pallet would have to do a lot of expensive ancestry checks to catch up).
Referer to the [pallet documentation](../modules/substrate/src/lib.rs) for more details.
#### Header Relayer strategy #### Header Relayer strategy
There is currently no reward strategy for the relayers at all. They also are not required to be There is currently no reward strategy for the relayers at all. They also are not required to be
staked or registered on-chain, unlike in other bridge designs. We consider the header sync to be staked or registered on-chain, unlike in other bridge designs. We consider the header sync to be
an essential part of the bridge and the incentivisation should be happening on the higher layers. an essential part of the bridge and the incentivization should be happening on the higher layers.
At the moment, signed transactions are the only way to submit headers to the header sync pallet. At the moment, signed transactions are the only way to submit headers to the header sync pallet.
However, in the future we would like to use unsigned transactions for headers delivery. This will However, in the future we would like to use unsigned transactions for headers delivery. This will
@@ -110,7 +98,7 @@ Users of the pallet add their messages to an "outbound lane" on the source chain
finalized message relayers are responsible for reading the current queue of messages and submitting finalized message relayers are responsible for reading the current queue of messages and submitting
some (or all) of them to the "inbound lane" of the target chain. Each message has a `nonce` some (or all) of them to the "inbound lane" of the target chain. Each message has a `nonce`
associated with it, which serves as the ordering of messages. The inbound lane stores the last associated with it, which serves as the ordering of messages. The inbound lane stores the last
delivered nonce to prevent replaying messages. To succesfuly deliver the message to the inbound lane delivered nonce to prevent replaying messages. To successfully deliver the message to the inbound lane
on target chain the relayer has to present present a storage proof which shows that the message was on target chain the relayer has to present present a storage proof which shows that the message was
part of the outbound lane on the source chain. part of the outbound lane on the source chain.
+6 -6
View File
@@ -46,22 +46,22 @@ FLAGS:
SUBCOMMANDS: SUBCOMMANDS:
help Prints this message or the help of the given subcommand(s) help Prints this message or the help of the given subcommand(s)
MillauToRialto Submit message to given Millau -> Rialto lane millau-to-rialto Submit message to given Millau -> Rialto lane
RialtoToMillau Submit message to given Rialto -> Millau lane rialto-to-millau Submit message to given Rialto -> Millau lane
``` ```
Messages are send from a source chain to a target chain using a so called `message lane`. Message lanes handle Messages are send from a source chain to a target chain using a so called `message lane`. Message lanes handle
both, message transport and message dispatch. There is one command for submitting a message to each of the two both, message transport and message dispatch. There is one command for submitting a message to each of the two
available bridges, namely `MillauToRialto` and `RialtoToMillau`. available bridges, namely `millau-to-rialto` and `rialto-to-millau`.
Submitting a message requires a number of arguments to be provided. Those arguments are essentially the same Submitting a message requires a number of arguments to be provided. Those arguments are essentially the same
for both submit message commands, hence only the output for `MillauToRialto` is shown below. for both submit message commands, hence only the output for `millau-to-rialto` is shown below.
``` ```
Submit message to given Millau -> Rialto lane Submit message to given Millau -> Rialto lane
USAGE: USAGE:
substrate-relay send-message MillauToRialto [OPTIONS] --lane <lane> --source-host <source-host> --source-port <source-port> --source-signer <source-signer> --origin <origin> --target-signer <target-signer> <SUBCOMMAND> substrate-relay send-message millau-to-rialto [OPTIONS] --lane <lane> --source-host <source-host> --source-port <source-port> --source-signer <source-signer> --origin <origin> --target-signer <target-signer> <SUBCOMMAND>
FLAGS: FLAGS:
-h, --help Prints help information -h, --help Prints help information
@@ -104,7 +104,7 @@ Usage of the arguments is best explained with an example. Below you can see, how
would look like: would look like:
``` ```
substrate-relay send-message MillauToRialto \ substrate-relay send-message millau-to-rialto \
--source-host=127.0.0.1 \ --source-host=127.0.0.1 \
--source-port=10946 \ --source-port=10946 \
--source-signer=//Dave \ --source-signer=//Dave \
@@ -8,27 +8,17 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0" }
finality-grandpa = "0.14.4"
hash-db = "0.15.2"
honggfuzz = "0.5.54" honggfuzz = "0.5.54"
log = "0.4.0" log = "0.4.0"
env_logger = "0.8.3" env_logger = "0.8.3"
# Bridge Dependencies # Bridge Dependencies
bp-header-chain = { path = "../../primitives/header-chain" }
bp-runtime = { path = "../../primitives/runtime" } bp-runtime = { path = "../../primitives/runtime" }
bp-test-utils = { path = "../../primitives/test-utils" }
# Substrate Dependencies # Substrate Dependencies
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-io = { 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" } sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -6,7 +6,10 @@ Install dependencies:
``` ```
$ sudo apt install build-essential binutils-dev libunwind-dev $ sudo apt install build-essential binutils-dev libunwind-dev
``` ```
or on nix:
```
$ nix-shell -p honggfuzz
```
Install `cargo hfuzz` plugin: Install `cargo hfuzz` plugin:
``` ```
@@ -29,4 +32,3 @@ HFUZZ_RUN_ARGS="-t 1 -n 12 -v -N 1000000 --exit_upon_crash" cargo hfuzz run exam
``` ```
More details in the [official documentation](https://docs.rs/honggfuzz/0.5.52/honggfuzz/#about-honggfuzz). More details in the [official documentation](https://docs.rs/honggfuzz/0.5.52/honggfuzz/#about-honggfuzz).
@@ -28,10 +28,8 @@ use sp_trie::StorageProof;
use std::collections::HashMap; use std::collections::HashMap;
fn craft_known_storage_proof(input_vec: Vec<(Vec<u8>, Vec<u8>)>) -> (H256, StorageProof) { fn craft_known_storage_proof(input_vec: Vec<(Vec<u8>, Vec<u8>)>) -> (H256, StorageProof) {
let storage_proof_vec = vec![( let storage_proof_vec =
None, vec![(None, input_vec.iter().map(|x| (x.0.clone(), Some(x.1.clone()))).collect())];
input_vec.iter().map(|x| (x.0.clone(), Some(x.1.clone()))).collect(),
)];
log::info!("Storage proof vec {:?}", storage_proof_vec); log::info!("Storage proof vec {:?}", storage_proof_vec);
let backend = <InMemoryBackend<Blake2Hasher>>::from(storage_proof_vec); let backend = <InMemoryBackend<Blake2Hasher>>::from(storage_proof_vec);
let root = backend.storage_root(std::iter::empty()).0; let root = backend.storage_root(std::iter::empty()).0;
@@ -47,7 +45,7 @@ fn craft_known_storage_proof(input_vec: Vec<(Vec<u8>, Vec<u8>)>) -> (H256, Stora
fn transform_into_unique(input_vec: Vec<(Vec<u8>, Vec<u8>)>) -> Vec<(Vec<u8>, Vec<u8>)> { fn transform_into_unique(input_vec: Vec<(Vec<u8>, Vec<u8>)>) -> Vec<(Vec<u8>, Vec<u8>)> {
let mut output_hashmap = HashMap::new(); let mut output_hashmap = HashMap::new();
let mut output_vec = Vec::new(); let mut output_vec = Vec::new();
for key_value_pair in input_vec.clone() { for key_value_pair in input_vec {
output_hashmap.insert(key_value_pair.0, key_value_pair.1); //Only 1 value per key output_hashmap.insert(key_value_pair.0, key_value_pair.1); //Only 1 value per key
} }
for (key, val) in output_hashmap.iter() { for (key, val) in output_hashmap.iter() {
@@ -59,18 +57,16 @@ fn transform_into_unique(input_vec: Vec<(Vec<u8>, Vec<u8>)>) -> Vec<(Vec<u8>, Ve
fn run_fuzzer() { fn run_fuzzer() {
fuzz!(|input_vec: Vec<(Vec<u8>, Vec<u8>)>| { fuzz!(|input_vec: Vec<(Vec<u8>, Vec<u8>)>| {
if input_vec.is_empty() { if input_vec.is_empty() {
return; return
} }
let unique_input_vec = transform_into_unique(input_vec); let unique_input_vec = transform_into_unique(input_vec);
let (root, craft_known_storage_proof) = craft_known_storage_proof(unique_input_vec.clone()); let (root, craft_known_storage_proof) = craft_known_storage_proof(unique_input_vec.clone());
let checker = <bp_runtime::StorageProofChecker<Blake2Hasher>>::new(root, craft_known_storage_proof) let checker =
<bp_runtime::StorageProofChecker<Blake2Hasher>>::new(root, craft_known_storage_proof)
.expect("Valid proof passed; qed"); .expect("Valid proof passed; qed");
for key_value_pair in unique_input_vec { for key_value_pair in unique_input_vec {
log::info!("Reading value for pair {:?}", key_value_pair); log::info!("Reading value for pair {:?}", key_value_pair);
assert_eq!( assert_eq!(checker.read_value(&key_value_pair.0), Ok(Some(key_value_pair.1.clone())));
checker.read_value(&key_value_pair.0),
Ok(Some(key_value_pair.1.clone()))
);
} }
}) })
} }
@@ -7,8 +7,9 @@ edition = "2018"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0" license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies] [dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false }
log = { version = "0.4.14", default-features = false } log = { version = "0.4.14", default-features = false }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
serde = { version = "1.0", optional = true } serde = { version = "1.0", optional = true }
# Bridge dependencies # Bridge dependencies
@@ -38,6 +39,7 @@ std = [
"frame-support/std", "frame-support/std",
"frame-system/std", "frame-system/std",
"log/std", "log/std",
"scale-info/std",
"serde", "serde",
"sp-runtime/std", "sp-runtime/std",
"sp-std/std", "sp-std/std",
@@ -19,11 +19,12 @@
//! before invoking module calls. //! before invoking module calls.
use super::{ use super::{
Call, Config as CurrencyExchangeConfig, InclusionProofVerifier, Instance, Pallet as CurrencyExchangePallet, Call, Config as CurrencyExchangeConfig, InclusionProofVerifier,
Pallet as CurrencyExchangePallet,
}; };
use sp_std::prelude::*; use sp_std::prelude::*;
use frame_benchmarking::{account, benchmarks_instance}; use frame_benchmarking::{account, benchmarks_instance_pallet};
use frame_system::RawOrigin; use frame_system::RawOrigin;
const SEED: u32 = 0; const SEED: u32 = 0;
@@ -31,7 +32,7 @@ const WORST_TX_SIZE_FACTOR: u32 = 1000;
const WORST_PROOF_SIZE_FACTOR: u32 = 1000; const WORST_PROOF_SIZE_FACTOR: u32 = 1000;
/// Pallet we're benchmarking here. /// Pallet we're benchmarking here.
pub struct Pallet<T: Config<I>, I: Instance>(CurrencyExchangePallet<T, I>); pub struct Pallet<T: Config<I>, I: 'static>(CurrencyExchangePallet<T, I>);
/// Proof benchmarking parameters. /// Proof benchmarking parameters.
pub struct ProofParams<Recipient> { pub struct ProofParams<Recipient> {
@@ -39,8 +40,8 @@ pub struct ProofParams<Recipient> {
pub recipient: Recipient, pub recipient: Recipient,
/// When true, recipient must exists before import. /// When true, recipient must exists before import.
pub recipient_exists: bool, pub recipient_exists: bool,
/// When 0, transaction should have minimal possible size. When this value has non-zero value n, /// When 0, transaction should have minimal possible size. When this value has non-zero value
/// transaction size should be (if possible) near to `MIN_SIZE + n * SIZE_FACTOR`. /// n, transaction size should be (if possible) near to MIN_SIZE + n * SIZE_FACTOR.
pub transaction_size_factor: u32, pub transaction_size_factor: u32,
/// When 0, proof should have minimal possible size. When this value has non-zero value n, /// When 0, proof should have minimal possible size. When this value has non-zero value n,
/// proof size should be (if possible) near to `MIN_SIZE + n * SIZE_FACTOR`. /// proof size should be (if possible) near to `MIN_SIZE + n * SIZE_FACTOR`.
@@ -48,14 +49,14 @@ pub struct ProofParams<Recipient> {
} }
/// Config that must be implemented by runtime. /// Config that must be implemented by runtime.
pub trait Config<I: Instance>: CurrencyExchangeConfig<I> { pub trait Config<I: 'static>: CurrencyExchangeConfig<I> {
/// Prepare proof for importing exchange transaction. /// Prepare proof for importing exchange transaction.
fn make_proof( fn make_proof(
proof_params: ProofParams<Self::AccountId>, proof_params: ProofParams<Self::AccountId>,
) -> <<Self as CurrencyExchangeConfig<I>>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof; ) -> <<Self as CurrencyExchangeConfig<I>>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof;
} }
benchmarks_instance! { benchmarks_instance_pallet! {
// Benchmark `import_peer_transaction` extrinsic with the best possible conditions: // Benchmark `import_peer_transaction` extrinsic with the best possible conditions:
// * Proof is the transaction itself. // * Proof is the transaction itself.
// * Transaction has minimal size. // * Transaction has minimal size.
@@ -19,11 +19,11 @@
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
use bp_currency_exchange::{ use bp_currency_exchange::{
CurrencyConverter, DepositInto, Error as ExchangeError, MaybeLockFundsTransaction, RecipientsMap, CurrencyConverter, DepositInto, Error as ExchangeError, MaybeLockFundsTransaction,
RecipientsMap,
}; };
use bp_header_chain::InclusionProofVerifier; use bp_header_chain::InclusionProofVerifier;
use frame_support::{decl_error, decl_module, decl_storage, ensure}; use frame_support::ensure;
use sp_runtime::DispatchResult;
#[cfg(feature = "runtime-benchmarks")] #[cfg(feature = "runtime-benchmarks")]
pub mod benchmarking; pub mod benchmarking;
@@ -34,8 +34,16 @@ pub trait OnTransactionSubmitted<AccountId> {
fn on_valid_transaction_submitted(submitter: AccountId); fn on_valid_transaction_submitted(submitter: AccountId);
} }
/// The module configuration trait pub use pallet::*;
pub trait Config<I = DefaultInstance>: frame_system::Config {
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
#[pallet::config]
pub trait Config<I: 'static = ()>: frame_system::Config {
/// Handler for transaction submission result. /// Handler for transaction submission result.
type OnTransactionSubmitted: OnTransactionSubmitted<Self::AccountId>; type OnTransactionSubmitted: OnTransactionSubmitted<Self::AccountId>;
/// Represents the blockchain that we'll be exchanging currency with. /// Represents the blockchain that we'll be exchanging currency with.
@@ -60,35 +68,19 @@ pub trait Config<I = DefaultInstance>: frame_system::Config {
type DepositInto: DepositInto<Recipient = Self::AccountId, Amount = Self::Amount>; type DepositInto: DepositInto<Recipient = Self::AccountId, Amount = Self::Amount>;
} }
decl_error! { #[pallet::pallet]
pub enum Error for Pallet<T: Config<I>, I: Instance> { #[pallet::generate_store(pub(super) trait Store)]
/// Invalid peer blockchain transaction provided. pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
InvalidTransaction,
/// Peer transaction has invalid amount.
InvalidAmount,
/// Peer transaction has invalid recipient.
InvalidRecipient,
/// Cannot map from peer recipient to this blockchain recipient.
FailedToMapRecipients,
/// Failed to convert from peer blockchain currency to this blockchain currency.
FailedToConvertCurrency,
/// Deposit has failed.
DepositFailed,
/// Deposit has partially failed (changes to recipient account were made).
DepositPartiallyFailed,
/// Transaction is not finalized.
UnfinalizedTransaction,
/// Transaction funds are already claimed.
AlreadyClaimed,
}
}
decl_module! { #[pallet::hooks]
pub struct Module<T: Config<I>, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> {}
#[pallet::call]
impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// Imports lock fund transaction of the peer blockchain. /// Imports lock fund transaction of the peer blockchain.
#[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) #[pallet::weight(0)] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
pub fn import_peer_transaction( pub fn import_peer_transaction(
origin, origin: OriginFor<T>,
proof: <<T as Config<I>>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof, proof: <<T as Config<I>>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof,
) -> DispatchResult { ) -> DispatchResult {
let submitter = frame_system::ensure_signed(origin)?; let submitter = frame_system::ensure_signed(origin)?;
@@ -101,7 +93,8 @@ decl_module! {
{ {
// if any changes were made to the storage, we can't just return error here, because // if any changes were made to the storage, we can't just return error here, because
// otherwise the same proof may be imported again // otherwise the same proof may be imported again
let deposit_result = T::DepositInto::deposit_into(deposit.recipient, deposit.amount); let deposit_result =
T::DepositInto::deposit_into(deposit.recipient, deposit.amount);
match deposit_result { match deposit_result {
Ok(_) => (), Ok(_) => (),
Err(ExchangeError::DepositPartiallyFailed) => (), Err(ExchangeError::DepositPartiallyFailed) => (),
@@ -122,16 +115,41 @@ decl_module! {
Ok(()) Ok(())
} }
} }
#[pallet::error]
pub enum Error<T, I = ()> {
/// Invalid peer blockchain transaction provided.
InvalidTransaction,
/// Peer transaction has invalid amount.
InvalidAmount,
/// Peer transaction has invalid recipient.
InvalidRecipient,
/// Cannot map from peer recipient to this blockchain recipient.
FailedToMapRecipients,
/// Failed to convert from peer blockchain currency to this blockchain currency.
FailedToConvertCurrency,
/// Deposit has failed.
DepositFailed,
/// Deposit has partially failed (changes to recipient account were made).
DepositPartiallyFailed,
/// Transaction is not finalized.
UnfinalizedTransaction,
/// Transaction funds are already claimed.
AlreadyClaimed,
} }
decl_storage! {
trait Store for Pallet<T: Config<I>, I: Instance = DefaultInstance> as Bridge {
/// All transfers that have already been claimed. /// All transfers that have already been claimed.
Transfers: map hasher(blake2_128_concat) <T::PeerMaybeLockFundsTransaction as MaybeLockFundsTransaction>::Id => (); #[pallet::storage]
} pub(super) type Transfers<T: Config<I>, I: 'static = ()> = StorageMap<
_,
Blake2_128Concat,
<T::PeerMaybeLockFundsTransaction as MaybeLockFundsTransaction>::Id,
(),
ValueQuery,
>;
} }
impl<T: Config<I>, I: Instance> Pallet<T, I> { impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// Returns true if currency exchange module is able to import given transaction proof in /// Returns true if currency exchange module is able to import given transaction proof in
/// its current state. /// its current state.
pub fn filter_transaction_proof( pub fn filter_transaction_proof(
@@ -144,14 +162,14 @@ impl<T: Config<I>, I: Instance> Pallet<T, I> {
err, err,
); );
return false; return false
} }
true true
} }
} }
impl<T: Config<I>, I: Instance> From<ExchangeError> for Error<T, I> { impl<T: Config<I>, I: 'static> From<ExchangeError> for Error<T, I> {
fn from(error: ExchangeError) -> Self { fn from(error: ExchangeError) -> Self {
match error { match error {
ExchangeError::InvalidTransaction => Error::InvalidTransaction, ExchangeError::InvalidTransaction => Error::InvalidTransaction,
@@ -170,7 +188,7 @@ impl<AccountId> OnTransactionSubmitted<AccountId> for () {
} }
/// Exchange deposit details. /// Exchange deposit details.
struct DepositDetails<T: Config<I>, I: Instance> { struct DepositDetails<T: Config<I>, I: 'static> {
/// Transfer id. /// Transfer id.
pub transfer_id: <T::PeerMaybeLockFundsTransaction as MaybeLockFundsTransaction>::Id, pub transfer_id: <T::PeerMaybeLockFundsTransaction as MaybeLockFundsTransaction>::Id,
/// Transfer recipient. /// Transfer recipient.
@@ -181,7 +199,7 @@ struct DepositDetails<T: Config<I>, I: Instance> {
/// Verify and parse transaction proof, preparing everything required for importing /// Verify and parse transaction proof, preparing everything required for importing
/// this transaction proof. /// this transaction proof.
fn prepare_deposit_details<T: Config<I>, I: Instance>( fn prepare_deposit_details<T: Config<I>, I: 'static>(
proof: &<<T as Config<I>>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof, proof: &<<T as Config<I>>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof,
) -> Result<DepositDetails<T, I>, Error<T, I>> { ) -> Result<DepositDetails<T, I>, Error<T, I>> {
// ensure that transaction is included in finalized block that we know of // ensure that transaction is included in finalized block that we know of
@@ -189,23 +207,16 @@ fn prepare_deposit_details<T: Config<I>, I: Instance>(
.ok_or(Error::<T, I>::UnfinalizedTransaction)?; .ok_or(Error::<T, I>::UnfinalizedTransaction)?;
// parse transaction // parse transaction
let transaction = let transaction = <T as Config<I>>::PeerMaybeLockFundsTransaction::parse(&transaction)
<T as Config<I>>::PeerMaybeLockFundsTransaction::parse(&transaction).map_err(Error::<T, I>::from)?; .map_err(Error::<T, I>::from)?;
let transfer_id = transaction.id; let transfer_id = transaction.id;
ensure!( ensure!(!Transfers::<T, I>::contains_key(&transfer_id), Error::<T, I>::AlreadyClaimed);
!Transfers::<T, I>::contains_key(&transfer_id),
Error::<T, I>::AlreadyClaimed
);
// grant recipient // grant recipient
let recipient = T::RecipientsMap::map(transaction.recipient).map_err(Error::<T, I>::from)?; let recipient = T::RecipientsMap::map(transaction.recipient).map_err(Error::<T, I>::from)?;
let amount = T::CurrencyConverter::convert(transaction.amount).map_err(Error::<T, I>::from)?; let amount = T::CurrencyConverter::convert(transaction.amount).map_err(Error::<T, I>::from)?;
Ok(DepositDetails { Ok(DepositDetails { transfer_id, recipient, amount })
transfer_id,
recipient,
amount,
})
} }
#[cfg(test)] #[cfg(test)]
@@ -215,7 +226,9 @@ mod tests {
use super::*; use super::*;
use bp_currency_exchange::LockFundsTransaction; use bp_currency_exchange::LockFundsTransaction;
use frame_support::{assert_noop, assert_ok, construct_runtime, parameter_types, weights::Weight}; use frame_support::{
assert_noop, assert_ok, construct_runtime, parameter_types, weights::Weight,
};
use sp_core::H256; use sp_core::H256;
use sp_runtime::{ use sp_runtime::{
testing::Header, testing::Header,
@@ -238,7 +251,7 @@ mod tests {
impl OnTransactionSubmitted<AccountId> for DummyTransactionSubmissionHandler { impl OnTransactionSubmitted<AccountId> for DummyTransactionSubmissionHandler {
fn on_valid_transaction_submitted(submitter: AccountId) { fn on_valid_transaction_submitted(submitter: AccountId) {
Transfers::<TestRuntime, DefaultInstance>::insert(submitter, ()); Transfers::<TestRuntime, ()>::insert(submitter, ());
} }
} }
@@ -248,7 +261,9 @@ mod tests {
type Transaction = RawTransaction; type Transaction = RawTransaction;
type TransactionInclusionProof = (bool, RawTransaction); type TransactionInclusionProof = (bool, RawTransaction);
fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option<RawTransaction> { fn verify_transaction_inclusion_proof(
proof: &Self::TransactionInclusionProof,
) -> Option<RawTransaction> {
if proof.0 { if proof.0 {
Some(proof.1.clone()) Some(proof.1.clone())
} else { } else {
@@ -279,7 +294,9 @@ mod tests {
type PeerRecipient = AccountId; type PeerRecipient = AccountId;
type Recipient = AccountId; type Recipient = AccountId;
fn map(peer_recipient: Self::PeerRecipient) -> bp_currency_exchange::Result<Self::Recipient> { fn map(
peer_recipient: Self::PeerRecipient,
) -> bp_currency_exchange::Result<Self::Recipient> {
match peer_recipient { match peer_recipient {
UNKNOWN_RECIPIENT_ID => Err(ExchangeError::FailedToMapRecipients), UNKNOWN_RECIPIENT_ID => Err(ExchangeError::FailedToMapRecipients),
_ => Ok(peer_recipient * 10), _ => Ok(peer_recipient * 10),
@@ -307,10 +324,14 @@ mod tests {
type Recipient = AccountId; type Recipient = AccountId;
type Amount = u64; type Amount = u64;
fn deposit_into(_recipient: Self::Recipient, amount: Self::Amount) -> bp_currency_exchange::Result<()> { fn deposit_into(
_recipient: Self::Recipient,
amount: Self::Amount,
) -> bp_currency_exchange::Result<()> {
match amount { match amount {
amount if amount < MAX_DEPOSIT_AMOUNT * 10 => Ok(()), amount if amount < MAX_DEPOSIT_AMOUNT * 10 => Ok(()),
amount if amount == MAX_DEPOSIT_AMOUNT * 10 => Err(ExchangeError::DepositPartiallyFailed), amount if amount == MAX_DEPOSIT_AMOUNT * 10 =>
Err(ExchangeError::DepositPartiallyFailed),
_ => Err(ExchangeError::DepositFailed), _ => Err(ExchangeError::DepositFailed),
} }
} }
@@ -375,26 +396,23 @@ mod tests {
} }
fn new_test_ext() -> sp_io::TestExternalities { fn new_test_ext() -> sp_io::TestExternalities {
let t = frame_system::GenesisConfig::default() let t = frame_system::GenesisConfig::default().build_storage::<TestRuntime>().unwrap();
.build_storage::<TestRuntime>()
.unwrap();
sp_io::TestExternalities::new(t) sp_io::TestExternalities::new(t)
} }
fn transaction(id: u64) -> RawTransaction { fn transaction(id: u64) -> RawTransaction {
RawTransaction { RawTransaction { id, recipient: 1, amount: 2 }
id,
recipient: 1,
amount: 2,
}
} }
#[test] #[test]
fn unfinalized_transaction_rejected() { fn unfinalized_transaction_rejected() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
assert_noop!( assert_noop!(
Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (false, transaction(0))), Exchange::import_peer_transaction(
Error::<TestRuntime, DefaultInstance>::UnfinalizedTransaction, Origin::signed(SUBMITTER),
(false, transaction(0))
),
Error::<TestRuntime, ()>::UnfinalizedTransaction,
); );
}); });
} }
@@ -407,7 +425,7 @@ mod tests {
Origin::signed(SUBMITTER), Origin::signed(SUBMITTER),
(true, transaction(INVALID_TRANSACTION_ID)), (true, transaction(INVALID_TRANSACTION_ID)),
), ),
Error::<TestRuntime, DefaultInstance>::InvalidTransaction, Error::<TestRuntime, ()>::InvalidTransaction,
); );
}); });
} }
@@ -421,7 +439,7 @@ mod tests {
Origin::signed(SUBMITTER), Origin::signed(SUBMITTER),
(true, transaction(ALREADY_CLAIMED_TRANSACTION_ID)), (true, transaction(ALREADY_CLAIMED_TRANSACTION_ID)),
), ),
Error::<TestRuntime, DefaultInstance>::AlreadyClaimed, Error::<TestRuntime, ()>::AlreadyClaimed,
); );
}); });
} }
@@ -433,7 +451,7 @@ mod tests {
transaction.recipient = UNKNOWN_RECIPIENT_ID; transaction.recipient = UNKNOWN_RECIPIENT_ID;
assert_noop!( assert_noop!(
Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)),
Error::<TestRuntime, DefaultInstance>::FailedToMapRecipients, Error::<TestRuntime, ()>::FailedToMapRecipients,
); );
}); });
} }
@@ -445,7 +463,7 @@ mod tests {
transaction.amount = INVALID_AMOUNT; transaction.amount = INVALID_AMOUNT;
assert_noop!( assert_noop!(
Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)),
Error::<TestRuntime, DefaultInstance>::FailedToConvertCurrency, Error::<TestRuntime, ()>::FailedToConvertCurrency,
); );
}); });
} }
@@ -457,7 +475,7 @@ mod tests {
transaction.amount = MAX_DEPOSIT_AMOUNT + 1; transaction.amount = MAX_DEPOSIT_AMOUNT + 1;
assert_noop!( assert_noop!(
Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)),
Error::<TestRuntime, DefaultInstance>::DepositFailed, Error::<TestRuntime, ()>::DepositFailed,
); );
}); });
} }
+2 -3
View File
@@ -7,9 +7,9 @@ edition = "2018"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0" license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies] [dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
log = { version = "0.4.14", default-features = false } log = { version = "0.4.14", default-features = false }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
# Bridge dependencies # Bridge dependencies
@@ -26,7 +26,6 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master
[dev-dependencies] [dev-dependencies]
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" }
serde = "1.0"
[features] [features]
default = ["std"] default = ["std"]

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