Merge pull request #4427 from paritytech/update-bridges-subtree-r/w

Update bridges subtree r/w
This commit is contained in:
Tomasz Drwięga
2021-12-02 11:20:45 +01:00
committed by GitHub
366 changed files with 21556 additions and 36681 deletions
+2 -16
View File
@@ -743,20 +743,6 @@ dependencies = [
"sp-version",
]
[[package]]
name = "bp-rialto"
version = "0.1.0"
dependencies = [
"bp-messages",
"bp-runtime",
"frame-support",
"frame-system",
"sp-api",
"sp-core",
"sp-runtime",
"sp-std",
]
[[package]]
name = "bp-rococo"
version = "0.1.0"
@@ -779,6 +765,7 @@ version = "0.1.0"
dependencies = [
"frame-support",
"hash-db",
"hex-literal",
"num-traits",
"parity-scale-codec",
"scale-info",
@@ -4749,7 +4736,6 @@ dependencies = [
"log",
"parity-scale-codec",
"scale-info",
"serde",
"sp-core",
"sp-io",
"sp-runtime",
@@ -4772,6 +4758,7 @@ dependencies = [
"parity-scale-codec",
"scale-info",
"serde",
"sp-core",
"sp-finality-grandpa",
"sp-io",
"sp-runtime",
@@ -4786,7 +4773,6 @@ dependencies = [
"bitvec",
"bp-message-dispatch",
"bp-messages",
"bp-rialto",
"bp-runtime",
"frame-benchmarking",
"frame-support",
+156 -96
View File
@@ -1,33 +1,111 @@
90
annualised/MS
Apache-2.0/M
AccountId/MS
api/SM
auth
auths/SM
&&
1KB
1MB
5MB
=
API/SM
APIs
arg
args
aren
async
Best/MS
benchmarking/MS
BlockId
AccountId/MS
Apache-2.0/M
Autogenerated
BFT/M
bitfield/MS
blake2/MS
blockchain/MS
boolean
borked
BridgeStorage
BlockNumber
BTC/S
Best/MS
BlockId
BlockNumber
BridgeStorage
CLI/MS
Chain1
Chain2
ChainSpec
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
choosen
config/MS
@@ -36,146 +114,128 @@ crypto/MS
customizable/B
Debian/M
decodable/MS
DOT/S
doesn
delivery_and_dispatch_fee
dev
dispatchable
dispatchables
doesn
ed25519
enum/MS
ERC-20
entrypoint/MS
ethereum/MS
externality/MS
extrinsic/MS
extrinsics
fedora/M
FN
FinalizationError
GiB/S
GPL/M
GPLv3/M
Handler/MS
HeaderA
HeaderId
functor
fuzzer
hasher
hardcoded
https
implementers
include/BG
inherent/MS
initialize/RG
instantiate/B
intrinsic/MS
intrinsics
InitiateChange
isn
invariant/MS
invariants
io
isn
isolate/BG
js
keccak256/M
keypair/MS
KSM/S
Lane1
Lane2
Lane3
LaneId
kusama/S
KYC/M
jsonrpsee
keccak
Kovan
keccak256/M
keyring
keystore/MS
kusama/S
lane
malus
max_value
merkle/MS
MessageNonce
MessageNonces
Merklized
MaybeOrphan
MaybeExtra
MetricsParams
MessagePayload
metadata
millau
misbehavior/SM
misbehaviors
MIN_SIZE
MIT/M
max_value
multivalidator/SM
natively
OldHeader
no_std
nonces
number
no_std
ok
oneshot/MS
others'
OutboundMessages
pallet_bridge_grandpa
pallet_bridge_messages
pallet_message_lane
parablock/MS
parachain/MS
param/MS
parameterize/D
pallet_message_lane
plancks
polkadot/MS
pov-block/MS
PoA
PoV/MS
precommit
prometheus
proxying
prune_end
prune_depth
provisioner/MS
probabilistically
prune_depth
prune_end
receival
reconnection
redhat/M
repo/MS
receival
RPC/MS
RLP
runtime/MS
Runtime1
Runtime2
rustc/MS
ServiceFactory/MS
SignedExtension
SIZE_FACTOR
relayer/MS
shouldn
source_at_target
source_latest_confirmed
source_latest_generated
sp_finality_grandpa
spawner
sr25519
SS58
SS58Prefix
src
S|N
SURI
source
stringified
struct/MS
Submitter1
submitters/MS
subsystem/MS
subsystems'
shouldn
subcommand/MS
synchronizer
target_at_source
target_latest_confirmed
target_latest_received
taskmanager/MS
teleport/RG
teleportation/SM
teleporter/SM
teleporters
testnet/MS
timeframe
tokio
timestamp
trie/MS
trustless/Y
ThisChain
TCP
tuple
u32
ubuntu/M
union/MSG
undeliverable
unfinalized
union/MSG
unpruned
unservable/B
unsynced
updatable
validator/SM
ve
vec
Vec
validator/SM
verifier
w3f/MS
wakeup
wasm/M
WND/S
XCM/S
XCMP/M
include/BG
isolate/BG
Instance1
Instance2
Instance42
Pre
Rialto
stringified
Stringified
millau
Millau
websocket
x2
~
+3
View File
@@ -14,3 +14,6 @@ indent_style=space
indent_size=2
tab_width=8
end_of_line=lf
[*.md]
max_line_length=80
+1
View File
@@ -18,6 +18,7 @@ hfuzz_workspace
.DS_Store
.cargo
.idea
.vscode
*.iml
+36 -21
View File
@@ -15,7 +15,7 @@ variables: &default-vars
GIT_DEPTH: 100
CARGO_INCREMENTAL: 0
ARCH: "x86_64"
CI_IMAGE: "paritytech/bridges-ci:production"
CI_IMAGE: "paritytech/bridges-ci:staging"
RUST_BACKTRACE: full
default:
@@ -76,6 +76,7 @@ default:
- if: $CI_PIPELINE_SOURCE == "pipeline"
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]{4}-[0-9]{2}-[0-9]{2}.*$/ # i.e. v2021-09-27, v2021-09-27-1
# there are two types of nightly pipelines:
# 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
@@ -93,26 +94,22 @@ clippy-nightly:
stage: lint
<<: *docker-env
<<: *test-refs
variables:
RUSTFLAGS: "-D warnings"
script:
- cargo +nightly clippy --all-targets
# FIXME: remove when all the warns are fixed
allow_failure: true
- SKIP_WASM_BUILD=1 cargo +nightly clippy --all-targets -- -A clippy::redundant_closure
fmt:
stage: lint
<<: *docker-env
<<: *test-refs
script:
- cargo fmt --all -- --check
- cargo +nightly fmt --all -- --check
spellcheck:
stage: lint
<<: *docker-env
<<: *test-refs
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
@@ -121,11 +118,11 @@ check:
<<: *docker-env
<<: *test-refs
script: &check-script
- time cargo check --verbose --workspace
- SKIP_WASM_BUILD=1 time cargo check --locked --verbose --workspace
# 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
- 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:
stage: check
@@ -141,8 +138,13 @@ test:
stage: test
<<: *docker-env
<<: *test-refs
# variables:
# RUSTFLAGS: "-D warnings"
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:
stage: test
@@ -189,16 +191,19 @@ build:
<<: *collect-artifacts
# master
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:
# Prepare artifacts
- mkdir -p ./artifacts
- strip ./target/release/rialto-bridge-node
- 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
- mv -v ./target/release/millau-bridge-node ./artifacts/
- strip ./target/release/ethereum-poa-relay
- mv -v ./target/release/ethereum-poa-relay ./artifacts/
- strip ./target/release/substrate-relay
- mv -v ./target/release/substrate-relay ./artifacts/
- mv -v ./deployments/local-scripts/bridge-entrypoint.sh ./artifacts/
@@ -223,6 +228,9 @@ build-nightly:
GIT_STRATEGY: none
DOCKERFILE: ci.Dockerfile
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:
- job: build
artifacts: true
@@ -233,8 +241,15 @@ build-nightly:
VERSION=$(echo ${CI_COMMIT_REF_NAME} | sed -r 's#/+#-#g');
fi
- 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:
- 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 )
- cd ./artifacts
- buildah bud
@@ -248,24 +263,24 @@ build-nightly:
--tag "${IMAGE_NAME}:latest"
--file "${DOCKERFILE}" .
# The job will success only on the protected branch
- echo "$Docker_Hub_Pass_Parity" |
buildah login --username "$Docker_Hub_User_Parity" --password-stdin docker.io
- echo "${DOCKER_HUB_PASS}" |
buildah login --username "${DOCKER_HUB_USER}" --password-stdin docker.io
- buildah info
- buildah push --format=v2s2 "${IMAGE_NAME}:${VERSION}"
- buildah push --format=v2s2 "${IMAGE_NAME}:sha-${CI_COMMIT_SHORT_SHA}"
- buildah push --format=v2s2 "${IMAGE_NAME}:latest"
after_script:
- env REGISTRY_AUTH_FILE= buildah logout "$IMAGE_NAME"
- env REGISTRY_AUTH_FILE= buildah logout --all
rialto-bridge-node:
stage: publish
<<: *build-push-image
millau-bridge-node:
rialto-parachain-collator:
stage: publish
<<: *build-push-image
ethereum-poa-relay:
millau-bridge-node:
stage: publish
<<: *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}}
}
@@ -8,13 +8,14 @@
// 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
// 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/>.
// 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}}
//! DATE: {{date}}, STEPS: {{cmd.steps}}, REPEAT: {{cmd.repeat}}
@@ -34,70 +35,74 @@
use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use sp_std::marker::PhantomData;
/// Weight functions needed for {{pallet}}.
/// 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}}
{{~#each benchmarks as |benchmark|}}
fn {{benchmark.name~}}
(
{{~#each benchmark.components as |c| ~}}
{{c.name}}: u32, {{/each~}}
) -> Weight;
{{~/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>);
impl<T: frame_system::Config> WeightInfo for RialtoWeight<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}}
}
impl<T: frame_system::Config> WeightInfo for RialtoWeight<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}}
}
// 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}}
}
+21
View File
@@ -0,0 +1,21 @@
# Lists some code owners.
#
# A codeowner just oversees some part of the codebase. If an owned file is changed then the
# corresponding codeowner receives a review request. An approval of the codeowner might be
# required for merging a PR (depends on repository settings).
#
# For details about syntax, see:
# https://help.github.com/en/articles/about-code-owners
# But here are some important notes:
#
# - Glob syntax is git-like, e.g. `/core` means the core directory in the root, unlike `core`
# which can be everywhere.
# - Multiple owners are supported.
# - Either handle (e.g, @github_user or @github_org/team) or email can be used. Keep in mind,
# that handles might work better because they are more recognizable on GitHub,
# eyou can use them for mentioning unlike an email.
# - The latest matching rule, if multiple, takes precedence.
# CI
/.github/ @paritytech/ci
/.gitlab-ci.yml @paritytech/ci
-10202
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -13,7 +13,7 @@ WORKDIR /parity-bridges-common
COPY . .
ARG PROJECT=ethereum-poa-relay
ARG PROJECT=substrate-relay
RUN cargo build --release --verbose -p ${PROJECT} && \
strip ./target/release/${PROJECT}
@@ -42,7 +42,7 @@ USER user
WORKDIR /home/user
ARG PROJECT=ethereum-poa-relay
ARG PROJECT=substrate-relay
COPY --chown=user:user --from=builder /parity-bridges-common/target/release/${PROJECT} ./
COPY --chown=user:user --from=builder /parity-bridges-common/deployments/local-scripts/bridge-entrypoint.sh ./
+89 -58
View File
@@ -6,7 +6,7 @@ These components include Substrate pallets for syncing headers, passing arbitrar
as libraries for building relayers to provide cross-chain communication capabilities.
Three bridge nodes are also available. The nodes can be used to run test networks which bridge other
Substrate chains or Ethereum Proof-of-Authority chains.
Substrate chains.
🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧
@@ -38,6 +38,25 @@ cargo build --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
[Getting Started](https://substrate.dev/docs/en/knowledgebase/getting-started/) page is a good
resource.
@@ -85,7 +104,6 @@ the `relays` which are used to pass messages between chains.
├── diagrams // Pretty pictures of the project architecture
│ └── ...
├── modules // Substrate Runtime Modules (a.k.a Pallets)
│ ├── ethereum // Ethereum PoA Header Sync Module
│ ├── grandpa // On-Chain GRANDPA Light Client
│ ├── messages // Cross Chain Message Passing
│ ├── dispatch // Target Chain Message Execution
@@ -102,10 +120,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
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 or using Docker images for each individual component,
- building & running from source
- running a Docker Compose setup (recommended).
### Using the Source
@@ -119,88 +136,102 @@ cargo build -p millau-bridge-node
cargo build -p substrate-relay
```
### Running
### Running a Dev network
To run a simple dev network you'll can use the scripts located in
[the `deployments/local-scripts` folder](./deployments/local-scripts). Since the relayer connects to
both Substrate chains it must be run last.
We will launch a dev network to demonstrate how to relay a message between two Substrate based
chains (named Rialto and Millau).
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
# In `parity-bridges-common` folder
./deployments/local-scripts/run-rialto-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-rialto-to-millau.sh
```
At this point you should see the relayer submitting headers from the Millau Substrate chain to the
Rialto Substrate chain.
### Local Docker Setup
To get up and running quickly you can use published Docker images for the bridge nodes and relayer.
The images are published on [Docker Hub](https://hub.docker.com/u/paritytech).
To run the dev network we first run the two bridge nodes:
```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
```
# Header Relayer Logs
[Millau_to_Rialto_Sync] [date] DEBUG bridge Going to submit finality proof of Millau header #147 to Rialto
[...] [date] INFO bridge Synced 147 of 147 headers
[...] [date] DEBUG bridge Going to submit finality proof of Millau header #148 to Rialto
[...] [date] INFO bridge Synced 148 of 149 headers
```
Notice that the `docker run` command will accept all the normal Substrate flags. For local
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:
Finally, we can run the message relayers.
```bash
docker run --network=host -it \
paritytech/substrate-relay init-bridge RialtoToMillau \
--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 \
./deployments/local-scripts/relay-messages-millau-to-rialto.sh
./deployments/local-scripts/relay-messages-rialto-to-millau.sh
```
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.
```bash
# In `parity-bridges-common` folder
docker build . -t local/rialto-bridge-node --build-arg PROJECT=rialto-bridge-node
docker build . -t local/millau-bridge-node --build-arg PROJECT=millau-bridge-node
docker build . -t local/substrate-relay --build-arg PROJECT=substrate-relay
```
# Message Relayer Logs
[Millau_to_Rialto_MessageLane_00000000] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about best message nonces
[...] [date] INFO bridge Synced Some(2) of Some(3) nonces in Millau::MessagesDelivery -> Rialto::MessagesDelivery race
[...] [date] DEBUG bridge Asking Millau::MessagesDelivery about message nonces
[...] [date] DEBUG bridge Received best nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { latest_nonce: 0, nonces_data: () }
[...] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about finalized message nonces
[...] [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._
Once you have the images built you can use them in the previous commands by replacing
`paritytech/<component_name>` with `local/<component_name>` everywhere.
To send a message see the ["How to send a message" section](#how-to-send-a-message).
### Full Network Docker Compose Setup
For a more sophisticated deployment which includes bidirectional header sync, message passing,
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
A straightforward way to interact with and test the bridge is sending messages. This is explained
in the [send message](./docs/send-message.md) document.
In this section we'll show you how to quickly send a bridge message, if you want to
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
+7 -8
View File
@@ -10,23 +10,26 @@ repository = "https://github.com/paritytech/parity-bridges-common/"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies]
jsonrpc-core = "15.1.0"
jsonrpc-core = "18.0"
structopt = "0.3.21"
serde_json = "1.0.59"
# Bridge dependencies
bp-messages = { path = "../../../primitives/messages" }
bp-millau= { path = "../../../primitives/chain-millau" }
bp-millau = { path = "../../../primitives/chain-millau" }
bp-runtime = { path = "../../../primitives/runtime" }
millau-runtime = { path = "../runtime" }
pallet-bridge-messages = { path = "../../../modules/messages" }
# Substrate Dependencies
beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "master" }
beefy-gadget-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
beefy-primitives = { 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" }
node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment-rpc = { 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"] }
@@ -45,7 +48,6 @@ sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "mast
sp-consensus-aura = { 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-inherents = { 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" }
substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -56,9 +58,6 @@ frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", bran
[features]
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 = [
# "millau-runtime/runtime-benchmarks",
"millau-runtime/runtime-benchmarks",
]
@@ -14,10 +14,12 @@
// 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 beefy_primitives::crypto::AuthorityId as BeefyId;
use bp_millau::derive_account_from_rialto_id;
use millau_runtime::{
AccountId, AuraConfig, BalancesConfig, BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, SessionConfig,
SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY,
AccountId, AuraConfig, BalancesConfig, BeefyConfig, BridgeRialtoMessagesConfig,
BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys,
Signature, SudoConfig, SystemConfig, WASM_BINARY,
};
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{sr25519, Pair, Public};
@@ -56,10 +58,11 @@ where
}
/// Helper function to generate an authority key for Aura
pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) {
pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, BeefyId, GrandpaId) {
(
get_account_id_from_seed::<sr25519::Public>(s),
get_from_seed::<AuraId>(s),
get_from_seed::<BeefyId>(s),
get_from_seed::<GrandpaId>(s),
)
}
@@ -70,10 +73,7 @@ impl Alternative {
let properties = Some(
serde_json::json!({
"tokenDecimals": 9,
"tokenSymbol": "MLAU",
"bridgeIds": {
"Rialto": bp_runtime::RIALTO_CHAIN_ID,
}
"tokenSymbol": "MLAU"
})
.as_object()
.expect("Map given; qed")
@@ -81,8 +81,8 @@ impl Alternative {
);
match self {
Alternative::Development => ChainSpec::from_genesis(
"Development",
"dev",
"Millau Development",
"millau_dev",
sc_service::ChainType::Development,
|| {
testnet_genesis(
@@ -107,8 +107,8 @@ impl Alternative {
None,
),
Alternative::LocalTestnet => ChainSpec::from_genesis(
"Local Testnet",
"local_testnet",
"Millau Local",
"millau_local",
sc_service::ChainType::Local,
|| {
testnet_genesis(
@@ -137,10 +137,12 @@ impl Alternative {
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>("Harry//stash"),
pallet_bridge_messages::Pallet::<
millau_runtime::Runtime,
pallet_bridge_messages::DefaultInstance,
>::relayer_fund_account_id(),
get_account_id_from_seed::<sr25519::Public>("RialtoMessagesOwner"),
get_account_id_from_seed::<sr25519::Public>("WithRialtoTokenSwap"),
pallet_bridge_messages::relayer_fund_account_id::<
bp_millau::AccountId,
bp_millau::AccountIdConverter,
>(),
derive_account_from_rialto_id(bp_runtime::SourceAccount::Account(
get_account_id_from_seed::<sr25519::Public>("Alice"),
)),
@@ -173,12 +175,12 @@ impl Alternative {
}
}
fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys {
SessionKeys { aura, grandpa }
fn session_keys(aura: AuraId, beefy: BeefyId, grandpa: GrandpaId) -> SessionKeys {
SessionKeys { aura, beefy, grandpa }
}
fn testnet_genesis(
initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>,
initial_authorities: Vec<(AccountId, AuraId, BeefyId, GrandpaId)>,
root_key: AccountId,
endowed_accounts: Vec<AccountId>,
_enable_println: bool,
@@ -186,22 +188,20 @@ fn testnet_genesis(
GenesisConfig {
system: SystemConfig {
code: WASM_BINARY.expect("Millau development WASM not available").to_vec(),
changes_trie_config: Default::default(),
},
balances: BalancesConfig {
balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(),
},
aura: AuraConfig {
authorities: Vec::new(),
},
grandpa: GrandpaConfig {
authorities: Vec::new(),
},
aura: AuraConfig { authorities: Vec::new() },
beefy: BeefyConfig { authorities: Vec::new() },
grandpa: GrandpaConfig { authorities: Vec::new() },
sudo: SudoConfig { key: root_key },
session: SessionConfig {
keys: initial_authorities
.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()))
})
.collect::<Vec<_>>(),
},
bridge_westend_grandpa: BridgeWestendGrandpaConfig {
@@ -211,15 +211,17 @@ fn testnet_genesis(
owner: Some(get_account_id_from_seed::<sr25519::Public>("George")),
..Default::default()
},
bridge_rialto_messages: BridgeRialtoMessagesConfig {
owner: Some(get_account_id_from_seed::<sr25519::Public>("RialtoMessagesOwner")),
..Default::default()
},
}
}
#[test]
fn derived_dave_account_is_as_expected() {
let dave = get_account_id_from_seed::<sr25519::Public>("Dave");
let derived: AccountId = derive_account_from_rialto_id(bp_runtime::SourceAccount::Account(dave));
assert_eq!(
derived.to_string(),
"5DNW6UVnb7TN6wX5KwXtDYR3Eccecbdzuw89HqjyNfkzce6J".to_string()
);
let derived: AccountId =
derive_account_from_rialto_id(bp_runtime::SourceAccount::Account(dave));
assert_eq!(derived.to_string(), "5DNW6UVnb7TN6wX5KwXtDYR3Eccecbdzuw89HqjyNfkzce6J".to_string());
}
+2 -2
View File
@@ -29,10 +29,10 @@ pub struct Cli {
/// Possible subcommands of the main binary.
#[derive(Debug, StructOpt)]
pub enum Subcommand {
/// Key management cli utilities
/// Key management CLI utilities
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),
/// Generate a seed that provides a vanity address.
+29 -48
View File
@@ -14,11 +14,13 @@
// 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::cli::{Cli, Subcommand};
use crate::service;
use crate::service::new_partial;
use crate::{
cli::{Cli, Subcommand},
service,
service::new_partial,
};
use millau_runtime::{Block, RuntimeApi};
use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli};
use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli};
use sc_service::PartialComponents;
impl SubstrateCli for Cli {
@@ -70,24 +72,23 @@ impl SubstrateCli for Cli {
pub fn run() -> sc_cli::Result<()> {
let cli = Cli::from_args();
// make sure to set correct crypto version.
sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::Custom(
sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::custom(
millau_runtime::SS58Prefix::get() as u16,
));
match &cli.subcommand {
Some(Subcommand::Benchmark(cmd)) => {
Some(Subcommand::Benchmark(cmd)) =>
if cfg!(feature = "runtime-benchmarks") {
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 {
println!(
"Benchmarking wasn't enabled when building the node. \
You can enable it with `--features runtime-benchmarks`."
);
Ok(())
}
}
},
Some(Subcommand::Key(cmd)) => cmd.run(&cli),
Some(Subcommand::Sign(cmd)) => cmd.run(),
Some(Subcommand::Verify(cmd)) => cmd.run(),
@@ -95,78 +96,58 @@ pub fn run() -> sc_cli::Result<()> {
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)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client,
task_manager,
import_queue,
..
} = new_partial(&config)?;
let PartialComponents { client, task_manager, import_queue, .. } =
new_partial(&config)?;
Ok((cmd.run(client, import_queue), task_manager))
})
}
},
Some(Subcommand::ExportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client, task_manager, ..
} = new_partial(&config)?;
let PartialComponents { client, task_manager, .. } = new_partial(&config)?;
Ok((cmd.run(client, config.database), task_manager))
})
}
},
Some(Subcommand::ExportState(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client, task_manager, ..
} = new_partial(&config)?;
let PartialComponents { client, task_manager, .. } = new_partial(&config)?;
Ok((cmd.run(client, config.chain_spec), task_manager))
})
}
},
Some(Subcommand::ImportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client,
task_manager,
import_queue,
..
} = new_partial(&config)?;
let PartialComponents { client, task_manager, import_queue, .. } =
new_partial(&config)?;
Ok((cmd.run(client, import_queue), task_manager))
})
}
},
Some(Subcommand::PurgeChain(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.database))
}
},
Some(Subcommand::Revert(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client,
task_manager,
backend,
..
} = new_partial(&config)?;
let PartialComponents { client, task_manager, backend, .. } = new_partial(&config)?;
Ok((cmd.run(client, backend), task_manager))
})
}
},
Some(Subcommand::Inspect(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 => {
let runner = cli.create_runner(&cli.run)?;
runner.run_node_until_exit(|config| async move {
match config.role {
Role::Light => service::new_light(config),
_ => service::new_full(config),
}
.map_err(sc_cli::Error::Service)
service::new_full(config).map_err(sc_cli::Error::Service)
})
}
},
}
}
+154 -212
View File
@@ -21,18 +21,19 @@
// =====================================================================================
// UPDATE GUIDE:
// 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;
// 3) fix compilation errors;
// 4) test :)
// 2) from old code keep `rpc_extensions_builder` - we use our own custom RPCs;
// 3) from old code keep the Beefy gadget;
// 4) fix compilation errors;
// 5) test :)
// =====================================================================================
// =====================================================================================
// =====================================================================================
use millau_runtime::{self, opaque::Block, RuntimeApi};
use sc_client_api::{ExecutorProvider, RemoteBackend};
use sc_client_api::ExecutorProvider;
use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams};
pub use sc_executor::NativeElseWasmExecutor;
use sc_finality_grandpa::SharedVoterState;
use sc_keystore::LocalKeystore;
use sc_service::{error::Error as ServiceError, Configuration, TaskManager};
use sc_telemetry::{Telemetry, TelemetryWorker};
@@ -44,7 +45,12 @@ use std::{sync::Arc, time::Duration};
pub struct ExecutorDispatch;
impl sc_executor::NativeExecutionDispatch for ExecutorDispatch {
/// Only enable the benchmarking host functions when we actually want to benchmark.
#[cfg(feature = "runtime-benchmarks")]
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
/// Otherwise we only use the default Substrate host functions.
#[cfg(not(feature = "runtime-benchmarks"))]
type ExtendHostFunctions = ();
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
millau_runtime::api::dispatch(method, data)
@@ -55,11 +61,11 @@ 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 FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
#[allow(clippy::type_complexity)]
pub fn new_partial(
config: &Configuration,
) -> Result<
@@ -70,7 +76,12 @@ pub fn new_partial(
sc_consensus::DefaultImportQueue<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>,
Option<Telemetry>,
),
@@ -78,7 +89,7 @@ pub fn new_partial(
ServiceError,
> {
if config.keystore_remote.is_some() {
return Err(ServiceError::Other("Remote Keystores are not supported.".to_string()));
return Err(ServiceError::Other(format!("Remote Keystores are not supported.")))
}
let telemetry = config
@@ -92,14 +103,22 @@ pub fn new_partial(
})
.transpose()?;
let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::<Block, RuntimeApi, Executor>(
config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
)?;
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, _>(
&config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
executor,
)?;
let client = Arc::new(client);
let telemetry = telemetry.map(|(worker, telemetry)| {
task_manager.spawn_handle().spawn("telemetry", worker.run());
task_manager.spawn_handle().spawn("telemetry", None, worker.run());
telemetry
});
@@ -122,26 +141,30 @@ pub fn new_partial(
let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration();
let import_queue = sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _, _>(ImportQueueParams {
block_import: grandpa_block_import.clone(),
justification_import: Some(Box::new(grandpa_block_import.clone())),
client: client.clone(),
create_inherent_data_providers: move |_, ()| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let import_queue =
sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _, _>(ImportQueueParams {
block_import: grandpa_block_import.clone(),
justification_import: Some(Box::new(grandpa_block_import.clone())),
client: client.clone(),
create_inherent_data_providers: move |_, ()| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp,
slot_duration,
);
let slot =
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp,
slot_duration,
);
Ok((timestamp, slot))
},
spawner: &task_manager.spawn_essential_handle(),
can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),
registry: config.prometheus_registry(),
check_for_equivocation: Default::default(),
telemetry: telemetry.as_ref().map(|x| x.handle()),
})?;
Ok((timestamp, slot))
},
spawner: &task_manager.spawn_essential_handle(),
can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(
client.executor().clone(),
),
registry: config.prometheus_registry(),
check_for_equivocation: Default::default(),
telemetry: telemetry.as_ref().map(|x| x.handle()),
})?;
Ok(sc_service::PartialComponents {
client,
@@ -155,7 +178,7 @@ pub fn new_partial(
})
}
fn remote_keystore(_url: &str) -> Result<Arc<LocalKeystore>, &'static str> {
fn remote_keystore(_url: &String) -> Result<Arc<LocalKeystore>, &'static str> {
// FIXME: here would the concrete keystore be built,
// must return a concrete type (NOT `LocalKeystore`) that
// implements `CryptoStore` and `SyncCryptoStore`
@@ -178,32 +201,40 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
if let Some(url) = &config.keystore_remote {
match remote_keystore(url) {
Ok(k) => keystore_container.set_remote_keystore(k),
Err(e) => {
Err(e) =>
return Err(ServiceError::Other(format!(
"Error hooking up remote keystore for {}: {}",
url, e
)))
}
))),
};
}
config
.network
.extra_sets
.push(sc_finality_grandpa::grandpa_peers_set_config());
config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config());
config.network.extra_sets.push(beefy_gadget::beefy_peers_set_config());
let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new(
backend.clone(),
grandpa_link.shared_authority_set().clone(),
Vec::default(),
));
let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue,
on_demand: None,
block_announce_validator_builder: None,
})?;
let (network, system_rpc_tx, network_starter) =
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue,
block_announce_validator_builder: None,
warp_sync: Some(warp_sync),
})?;
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();
@@ -212,7 +243,9 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
let name = config.network.node_name.clone();
let enable_grandpa = !config.disable_grandpa;
let prometheus_registry = config.prometheus_registry().cloned();
let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty();
let shared_voter_state = SharedVoterState::empty();
let (signed_commitment_sender, signed_commitment_stream) =
beefy_gadget::notification::BeefySignedCommitmentStream::channel();
let rpc_extensions_builder = {
use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider;
@@ -230,10 +263,12 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
let shared_authority_set = grandpa_link.shared_authority_set().clone();
let shared_voter_state = shared_voter_state.clone();
let finality_proof_provider =
GrandpaFinalityProofProvider::new_for_service(backend, Some(shared_authority_set.clone()));
let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(
backend,
Some(shared_authority_set.clone()),
);
Box::new(move |_, subscription_executor| {
Box::new(move |_, subscription_executor: sc_rpc::SubscriptionTaskExecutor| {
let mut io = jsonrpc_core::IoHandler::default();
io.extend_with(SystemApi::to_delegate(FullSystem::new(
client.clone(),
@@ -247,10 +282,19 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
shared_authority_set.clone(),
shared_voter_state.clone(),
justification_stream.clone(),
subscription_executor,
subscription_executor.clone(),
finality_proof_provider.clone(),
)));
io
io.extend_with(beefy_gadget_rpc::BeefyApi::to_delegate(
beefy_gadget_rpc::BeefyRpcHandler::new(
signed_commitment_stream.clone(),
subscription_executor,
),
));
io.extend_with(pallet_mmr_rpc::MmrApi::to_delegate(pallet_mmr_rpc::Mmr::new(
client.clone(),
)));
Ok(io)
})
};
@@ -261,9 +305,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
task_manager: &mut task_manager,
transaction_pool: transaction_pool.clone(),
rpc_extensions_builder,
on_demand: None,
remote_blockchain: None,
backend,
backend: backend.clone(),
system_rpc_tx,
config,
telemetry: telemetry.as_mut(),
@@ -278,51 +320,71 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
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 raw_slot_duration = slot_duration.slot_duration();
let aura = sc_consensus_aura::start_aura::<AuraPair, _, _, _, _, _, _, _, _, _, _, _>(StartAuraParams {
slot_duration,
client,
select_chain,
block_import,
proposer_factory,
create_inherent_data_providers: move |_, ()| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let aura = sc_consensus_aura::start_aura::<AuraPair, _, _, _, _, _, _, _, _, _, _, _>(
StartAuraParams {
slot_duration,
client: client.clone(),
select_chain,
block_import,
proposer_factory,
create_inherent_data_providers: move |_, ()| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp,
raw_slot_duration,
);
let slot =
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp,
raw_slot_duration,
);
Ok((timestamp, slot))
Ok((timestamp, slot))
},
force_authoring,
backoff_authoring_blocks,
keystore: keystore_container.sync_keystore(),
can_author_with,
sync_oracle: network.clone(),
justification_sync_link: network.clone(),
block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32),
max_block_proposal_slot_portion: None,
telemetry: telemetry.as_ref().map(|x| x.handle()),
},
force_authoring,
backoff_authoring_blocks,
keystore: keystore_container.sync_keystore(),
can_author_with,
sync_oracle: network.clone(),
justification_sync_link: network.clone(),
block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32),
max_block_proposal_slot_portion: None,
telemetry: telemetry.as_ref().map(|x| x.handle()),
})?;
)?;
// the AURA authoring task is considered essential, i.e. if it
// fails we take down the service with it.
task_manager.spawn_essential_handle().spawn_blocking("aura", aura);
task_manager
.spawn_essential_handle()
.spawn_blocking("aura", Some("block-authoring"), aura);
}
// if the node isn't actively participating in consensus then it doesn't
// need a keystore, regardless of which protocol we use below.
let keystore = if role.is_authority() {
Some(keystore_container.sync_keystore())
} else {
None
let keystore =
if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None };
let beefy_params = beefy_gadget::BeefyParams {
client,
backend,
key_store: keystore.clone(),
network: network.clone(),
signed_commitment_sender,
min_block_delta: 4,
prometheus_registry: prometheus_registry.clone(),
};
// Start the BEEFY bridge gadget.
task_manager.spawn_essential_handle().spawn_blocking(
"beefy-gadget",
None,
beefy_gadget::start_beefy_gadget::<_, _, _, _>(beefy_params),
);
let grandpa_config = sc_finality_grandpa::Config {
// FIXME #1578 make this available through chainspec
gossip_duration: Duration::from_millis(333),
@@ -353,133 +415,13 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
// the GRANDPA voter task is considered infallible, i.e.
// if it fails we take down the service with it.
task_manager
.spawn_essential_handle()
.spawn_blocking("grandpa-voter", sc_finality_grandpa::run_grandpa_voter(grandpa_config)?);
}
network_starter.start_network();
Ok(task_manager)
}
/// Builds a new service for a light client.
pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError> {
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 (client, backend, keystore_container, mut task_manager, on_demand) =
sc_service::new_light_parts::<Block, RuntimeApi, Executor>(
&config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
)?;
let mut telemetry = telemetry.map(|(worker, telemetry)| {
task_manager.spawn_handle().spawn("telemetry", worker.run());
telemetry
});
config
.network
.extra_sets
.push(sc_finality_grandpa::grandpa_peers_set_config());
let select_chain = sc_consensus::LongestChain::new(backend.clone());
let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light(
config.transaction_pool.clone(),
config.prometheus_registry(),
task_manager.spawn_essential_handle(),
client.clone(),
on_demand.clone(),
));
let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import(
client.clone(),
&(client.clone() as Arc<_>),
select_chain,
telemetry.as_ref().map(|x| x.handle()),
)?;
let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration();
let import_queue = sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _, _>(ImportQueueParams {
block_import: grandpa_block_import.clone(),
justification_import: Some(Box::new(grandpa_block_import)),
client: client.clone(),
create_inherent_data_providers: move |_, ()| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp,
slot_duration,
);
Ok((timestamp, slot))
},
spawner: &task_manager.spawn_essential_handle(),
can_author_with: sp_consensus::NeverCanAuthor,
registry: config.prometheus_registry(),
check_for_equivocation: Default::default(),
telemetry: telemetry.as_ref().map(|x| x.handle()),
})?;
let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue,
on_demand: Some(on_demand.clone()),
block_announce_validator_builder: None,
})?;
if config.offchain_worker.enabled {
sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone());
}
let enable_grandpa = !config.disable_grandpa;
if enable_grandpa {
let name = config.network.node_name.clone();
let config = sc_finality_grandpa::Config {
gossip_duration: std::time::Duration::from_millis(333),
justification_period: 512,
name: Some(name),
observer_enabled: false,
keystore: None,
local_role: config.role.clone(),
telemetry: telemetry.as_ref().map(|x| x.handle()),
};
task_manager.spawn_handle().spawn_blocking(
"grandpa-observer",
sc_finality_grandpa::run_grandpa_observer(config, grandpa_link, network.clone())?,
task_manager.spawn_essential_handle().spawn_blocking(
"grandpa-voter",
None,
sc_finality_grandpa::run_grandpa_voter(grandpa_config)?,
);
}
sc_service::spawn_tasks(sc_service::SpawnTasksParams {
remote_blockchain: Some(backend.remote_blockchain()),
transaction_pool,
task_manager: &mut task_manager,
on_demand: Some(on_demand),
rpc_extensions_builder: Box::new(|_, _| ()),
config,
client,
keystore: keystore_container.sync_keystore(),
backend,
network,
system_rpc_tx,
telemetry: telemetry.as_mut(),
})?;
network_starter.start_network();
Ok(task_manager)
}
+48 -31
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"
[dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
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
@@ -24,36 +25,43 @@ bridge-runtime-common = { path = "../../runtime-common", default-features = fals
pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false }
pallet-bridge-grandpa = { path = "../../../modules/grandpa", 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 }
# Substrate Dependencies
frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
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-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-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-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 }
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-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-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-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-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 }
beefy-primitives = { 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-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
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-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-beefy-mmr = { 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-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-mmr-primitives = { 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-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 }
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-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-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-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-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 }
[build-dependencies]
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -61,6 +69,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran
[features]
default = ["std"]
std = [
"beefy-primitives/std",
"bp-header-chain/std",
"bp-messages/std",
"bp-millau/std",
@@ -75,10 +84,14 @@ std = [
"frame-system/std",
"pallet-aura/std",
"pallet-balances/std",
"pallet-beefy/std",
"pallet-beefy-mmr/std",
"pallet-bridge-dispatch/std",
"pallet-bridge-grandpa/std",
"pallet-bridge-messages/std",
"pallet-bridge-token-swap/std",
"pallet-grandpa/std",
"pallet-mmr/std",
"pallet-randomness-collective-flip/std",
"pallet-session/std",
"pallet-shift-session-manager/std",
@@ -86,6 +99,7 @@ std = [
"pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std",
"scale-info/std",
"serde",
"sp-api/std",
"sp-block-builder/std",
@@ -101,6 +115,9 @@ std = [
"sp-trie/std",
"sp-version/std",
]
# 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 = [
"frame-benchmarking",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-bridge-token-swap/runtime-benchmarks",
]
+270 -62
View File
@@ -34,18 +34,25 @@ pub mod rialto_messages;
use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge};
use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_delivery_fee, MessageBridge};
use codec::Decode;
use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo};
use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet};
use bridge_runtime_common::messages::{
source::estimate_message_dispatch_and_delivery_fee, MessageBridge,
};
use pallet_grandpa::{
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
};
use pallet_mmr_primitives::{
DataOrHash, EncodableOpaqueLeaf, Error as MmrError, LeafDataProvider, Proof as MmrProof,
};
use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo};
use sp_api::impl_runtime_apis;
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, MultiSignature, MultiSigner,
ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
@@ -62,8 +69,7 @@ pub use frame_support::{
pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall;
pub use pallet_bridge_grandpa::Call as BridgeGrandpaRialtoCall;
pub use pallet_bridge_grandpa::Call as BridgeGrandpaWestendCall;
pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall;
pub use pallet_bridge_messages::Call as MessagesCall;
pub use pallet_sudo::Call as SudoCall;
pub use pallet_timestamp::Call as TimestampCall;
@@ -90,7 +96,7 @@ pub type AccountIndex = u32;
pub type Balance = bp_millau::Balance;
/// 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.
pub type Hash = bp_millau::Hash;
@@ -98,9 +104,6 @@ pub type Hash = bp_millau::Hash;
/// Hashing algorithm used by the chain.
pub type Hashing = bp_millau::Hasher;
/// Digest item type.
pub type DigestItem = generic::DigestItem<Hash>;
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
@@ -121,6 +124,7 @@ pub mod opaque {
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: Aura,
pub beefy: Beefy,
pub grandpa: Grandpa,
}
}
@@ -139,10 +143,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
/// 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(),
}
NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
}
parameter_types! {
@@ -214,10 +215,16 @@ parameter_types! {
impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
type MaxAuthorities = MaxAuthorities;
type DisabledValidators = ();
}
impl pallet_beefy::Config for Runtime {
type BeefyId = BeefyId;
}
impl pallet_bridge_dispatch::Config for Runtime {
type Event = Event;
type MessageId = (bp_messages::LaneId, bp_messages::MessageNonce);
type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce);
type Call = Call;
type CallFilter = frame_support::traits::Everything;
type EncodedCall = crate::rialto_messages::FromRialtoEncodedCall;
@@ -231,12 +238,50 @@ impl pallet_grandpa::Config for Runtime {
type Event = Event;
type Call = Call;
type KeyOwnerProofSystem = ();
type KeyOwnerProof = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;
type KeyOwnerIdentification =
<Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::IdentificationTuple;
type KeyOwnerProof =
<Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;
type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(
KeyTypeId,
GrandpaId,
)>>::IdentificationTuple;
type HandleEquivocation = ();
// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
}
type MmrHash = <Keccak256 as sp_runtime::traits::Hash>::Output;
impl pallet_mmr::Config for Runtime {
const INDEXING_PREFIX: &'static [u8] = b"mmr";
type Hashing = Keccak256;
type Hash = MmrHash;
type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest<Runtime>;
type WeightInfo = ();
type LeafData = pallet_beefy_mmr::Pallet<Runtime>;
}
parameter_types! {
/// Version of the produced MMR leaf.
///
/// The version consists of two parts;
/// - `major` (3 bits)
/// - `minor` (5 bits)
///
/// `major` should be updated only if decoding the previous MMR Leaf format from the payload
/// is not possible (i.e. backward incompatible change).
/// `minor` should be updated if fields are added to the previous MMR Leaf, which given SCALE
/// encoding does not prevent old leafs from being decoded.
///
/// Hence we expect `major` to be changed really rarely (think never).
/// See [`MmrLeafVersion`] type documentation for more details.
pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0);
}
impl pallet_beefy_mmr::Config for Runtime {
type LeafVersion = LeafVersion;
type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum;
type ParachainHeads = ();
}
parameter_types! {
@@ -244,7 +289,7 @@ parameter_types! {
}
impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the Unix epoch.
/// A timestamp: milliseconds since the UNIX epoch.
type Moment = u64;
type OnTimestampSet = Aura;
type MinimumPeriod = MinimumPeriod;
@@ -278,13 +323,25 @@ impl pallet_balances::Config for Runtime {
parameter_types! {
pub const TransactionBaseFee: Balance = 0;
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 {
type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, ()>;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = ();
type OperationalFeeMultiplier = OperationalFeeMultiplier;
type WeightToFee = bp_millau::WeightToFee;
type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment<
Runtime,
TargetBlockFullness,
AdjustmentVariable,
MinimumMultiplier,
>;
}
impl pallet_sudo::Config for Runtime {
@@ -357,10 +414,11 @@ parameter_types! {
pub const GetDeliveryConfirmationTransactionFee: Balance =
bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _;
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.
pub type WithRialtoMessagesInstance = pallet_bridge_messages::DefaultInstance;
pub type WithRialtoMessagesInstance = ();
impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime {
type Event = Event;
@@ -382,16 +440,45 @@ impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime {
type TargetHeaderChain = crate::rialto_messages::Rialto;
type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier;
type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments<
Runtime,
pallet_balances::Pallet<Runtime>,
GetDeliveryConfirmationTransactionFee,
RootAccountForPayments,
>;
type OnDeliveryConfirmed = ();
type MessageDeliveryAndDispatchPayment =
pallet_bridge_messages::instant_payments::InstantCurrencyPayments<
Runtime,
(),
pallet_balances::Pallet<Runtime>,
GetDeliveryConfirmationTransactionFee,
RootAccountForPayments,
>;
type OnMessageAccepted = ();
type OnDeliveryConfirmed =
pallet_bridge_token_swap::Pallet<Runtime, WithRialtoTokenSwapInstance>;
type SourceHeaderChain = crate::rialto_messages::Rialto;
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!(
@@ -400,20 +487,35 @@ construct_runtime!(
NodeBlock = opaque::Block,
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>},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>},
// Must be before session.
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>},
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>},
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event},
ShiftSessionManager: pallet_shift_session_manager::{Pallet},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},
// BEEFY Bridges support.
Beefy: pallet_beefy::{Pallet, Storage, Config<T>},
Mmr: pallet_mmr::{Pallet, Storage},
MmrLeaf: pallet_beefy_mmr::{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 +551,7 @@ pub type Executive = frame_executive::Executive<
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
AllPallets,
>;
impl_runtime_apis! {
@@ -522,7 +624,7 @@ impl_runtime_apis! {
}
fn authorities() -> Vec<AuraId> {
Aura::authorities()
Aura::authorities().to_vec()
}
}
@@ -550,7 +652,50 @@ impl_runtime_apis! {
}
}
impl beefy_primitives::BeefyApi<Block> for Runtime {
fn validator_set() -> ValidatorSet<BeefyId> {
Beefy::validator_set()
}
}
impl pallet_mmr_primitives::MmrApi<Block, MmrHash> for Runtime {
fn generate_proof(leaf_index: u64)
-> Result<(EncodableOpaqueLeaf, MmrProof<MmrHash>), MmrError>
{
Mmr::generate_proof(leaf_index)
.map(|(leaf, proof)| (EncodableOpaqueLeaf::from_leaf(&leaf), proof))
}
fn verify_proof(leaf: EncodableOpaqueLeaf, proof: MmrProof<MmrHash>)
-> Result<(), MmrError>
{
pub type Leaf = <
<Runtime as pallet_mmr::Config>::LeafData as LeafDataProvider
>::LeafData;
let leaf: Leaf = leaf
.into_opaque_leaf()
.try_decode()
.ok_or(MmrError::Verify)?;
Mmr::verify_leaf(leaf, proof)
}
fn verify_proof_stateless(
root: MmrHash,
leaf: EncodableOpaqueLeaf,
proof: MmrProof<MmrHash>
) -> Result<(), MmrError> {
type MmrHashing = <Runtime as pallet_mmr::Config>::Hashing;
let node = DataOrHash::Data(leaf.into_opaque_leaf());
pallet_mmr::verify_leaf_proof::<MmrHashing, _>(root, node, proof)
}
}
impl fg_primitives::GrandpaApi<Block> for Runtime {
fn current_set_id() -> fg_primitives::SetId {
Grandpa::current_set_id()
}
fn grandpa_authorities() -> GrandpaAuthorityList {
Grandpa::grandpa_authorities()
}
@@ -619,20 +764,11 @@ impl_runtime_apis! {
begin: bp_messages::MessageNonce,
end: bp_messages::MessageNonce,
) -> Vec<bp_messages::MessageDetails<Balance>> {
(begin..=end).filter_map(|nonce| {
let message_data = BridgeRialtoMessages::outbound_message_data(lane, nonce)?;
let decoded_payload = rialto_messages::ToRialtoMessagePayload::decode(
&mut &message_data.payload[..]
).ok()?;
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()
bridge_runtime_common::messages_api::outbound_message_details::<
Runtime,
WithRialtoMessagesInstance,
WithRialtoMessageBridge,
>(lane, begin, end)
}
fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce {
@@ -657,6 +793,67 @@ impl_runtime_apis! {
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.
@@ -698,6 +895,7 @@ mod tests {
bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT,
bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT,
DbWeight::get(),
);
let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add(
@@ -707,21 +905,31 @@ mod tests {
bp_millau::max_extrinsic_size(),
bp_millau::max_extrinsic_weight(),
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(
bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _,
bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _,
)
.unwrap_or(u32::MAX);
let max_incoming_inbound_lane_data_proof_size =
bp_messages::InboundLaneData::<()>::encoded_size_hint(
bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _,
bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _,
)
.unwrap_or(u32::MAX);
pallet_bridge_messages::ensure_able_to_receive_confirmation::<Weights>(
bp_millau::max_extrinsic_size(),
bp_millau::max_extrinsic_weight(),
max_incoming_inbound_lane_data_proof_size,
bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_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},
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};
/// 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! {
/// Rialto to Millau conversion rate. Initially we treat both tokens as equal.
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.
pub type ToRialtoMessagePayload = messages::source::FromThisChainMessagePayload<WithRialtoMessageBridge>;
pub type ToRialtoMessagePayload =
messages::source::FromThisChainMessagePayload<WithRialtoMessageBridge>;
/// 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.
pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload<WithRialtoMessageBridge>;
pub type FromRialtoMessagePayload =
messages::target::FromBridgedChainMessagePayload<WithRialtoMessageBridge>;
/// Encoded Millau Call as it comes from Rialto.
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>;
/// 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.
pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch<
WithRialtoMessageBridge,
crate::Runtime,
pallet_balances::Pallet<Runtime>,
pallet_bridge_dispatch::DefaultInstance,
(),
>;
/// Millau <-> Rialto message bridge.
@@ -76,14 +86,16 @@ impl MessageBridge for WithRialtoMessageBridge {
const RELAYER_FEE_PERCENT: u32 = 10;
const THIS_CHAIN_ID: ChainId = MILLAU_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 BridgedChain = Rialto;
type BridgedMessagesInstance = crate::WithRialtoMessagesInstance;
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))
.unwrap_or(bp_millau::Balance::MAX)
bp_millau::Balance::try_from(
RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance),
)
.unwrap_or(bp_millau::Balance::MAX)
}
}
@@ -104,7 +116,9 @@ impl messages::ThisChainWithMessages for Millau {
type Call = crate::Call;
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 {
@@ -128,11 +142,15 @@ impl messages::ThisChainWithMessages for Millau {
}
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
messages::transaction_payment(
bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic,
1,
FixedU128::zero(),
multiplier,
|weight| weight as _,
transaction,
)
@@ -159,12 +177,15 @@ impl messages::BridgedChainWithMessages for Rialto {
fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive<Weight> {
// 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
// minimal dispatch weight here
// this bridge may be used to deliver all kind of messages, so we're not making any
// assumptions about minimal dispatch weight here
0..=upper_limit
}
@@ -195,11 +216,14 @@ impl messages::BridgedChainWithMessages for Rialto {
}
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
messages::transaction_payment(
bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic,
1,
FixedU128::zero(),
multiplier,
|weight| weight as _,
transaction,
)
@@ -221,9 +245,11 @@ impl TargetHeaderChain<ToRialtoMessagePayload, bp_rialto::AccountId> for Rialto
fn verify_messages_delivery_proof(
proof: Self::MessagesDeliveryProof,
) -> Result<(LaneId, InboundLaneData<bp_millau::AccountId>), Self::Error> {
messages::source::verify_messages_delivery_proof::<WithRialtoMessageBridge, Runtime, crate::RialtoGrandpaInstance>(
proof,
)
messages::source::verify_messages_delivery_proof::<
WithRialtoMessageBridge,
Runtime,
crate::RialtoGrandpaInstance,
>(proof)
}
}
@@ -240,15 +266,16 @@ impl SourceHeaderChain<bp_rialto::Balance> for Rialto {
proof: Self::MessagesProof,
messages_count: u32,
) -> Result<ProvedMessages<Message<bp_rialto::Balance>>, Self::Error> {
messages::target::verify_messages_proof::<WithRialtoMessageBridge, Runtime, crate::RialtoGrandpaInstance>(
proof,
messages_count,
)
messages::target::verify_messages_proof::<
WithRialtoMessageBridge,
Runtime,
crate::RialtoGrandpaInstance,
>(proof, messages_count)
}
}
/// Millau -> Rialto message lane pallet parameters.
#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq)]
#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)]
pub enum MillauToRialtoMessagesParameter {
/// The conversion formula we use is: `MillauTokens = RialtoTokens * conversion_rate`.
RialtoToMillauConversionRate(FixedU128),
@@ -257,9 +284,8 @@ pub enum MillauToRialtoMessagesParameter {
impl MessagesParameter for MillauToRialtoMessagesParameter {
fn save(&self) {
match *self {
MillauToRialtoMessagesParameter::RialtoToMillauConversionRate(ref conversion_rate) => {
RialtoToMillauConversionRate::set(conversion_rate)
}
MillauToRialtoMessagesParameter::RialtoToMillauConversionRate(ref 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" }
@@ -14,13 +14,9 @@
// 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/>.
//! Relaying [`currency-exchange`](../pallet_bridge_currency_exchange/index.html) application
//! specific data. Currency exchange application allows exchanging tokens between bridged chains.
//! This module provides entrypoints for crafting and submitting (single and multiple)
//! proof-of-exchange-at-source-chain transaction(s) to target chain.
use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed};
#![warn(missing_docs)]
pub mod exchange;
pub mod exchange_loop;
pub mod exchange_loop_metrics;
fn main() {
generate_cargo_keys();
rerun_if_git_head_changed();
}
@@ -0,0 +1,164 @@
// 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(),
},
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,140 @@
// 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(long)]
pub parachain_id: Option<u32>,
#[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.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.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,493 @@
// 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", None, 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(),
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 {
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,
);
+63 -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"
[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"
serde_json = "1.0.59"
thiserror = "1.0"
# Bridge dependencies
bp-messages = { path = "../../../primitives/messages" }
bp-runtime = { path = "../../../primitives/runtime" }
bp-rialto = { path = "../../../primitives/chain-rialto" }
pallet-bridge-messages = { path = "../../../modules/messages" }
@@ -24,32 +28,86 @@ rialto-runtime = { path = "../runtime" }
# Substrate Dependencies
beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "master" }
beefy-gadget-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
beefy-primitives = { 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-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-mmr-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-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-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-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-warp-sync = { 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-service = { 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" }
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-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-finality-grandpa = { 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-timestamp = { 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 Dependencies
polkadot-client = { git = "https://github.com/paritytech/polkadot", 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-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]
substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -14,13 +14,17 @@
// 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 beefy_primitives::crypto::AuthorityId as BeefyId;
use bp_rialto::derive_account_from_millau_id;
use polkadot_primitives::v1::{AssignmentId, ValidatorId};
use rialto_runtime::{
AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoPoaConfig, GenesisConfig, GrandpaConfig,
SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY,
AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig,
ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature,
SudoConfig, SystemConfig, WASM_BINARY,
};
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_finality_grandpa::AuthorityId as GrandpaId;
use sp_runtime::traits::{IdentifyAccount, Verify};
@@ -56,12 +60,18 @@ where
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
}
/// Helper function to generate an authority key for Aura
pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) {
/// Helper function to generate authority keys.
pub fn get_authority_keys_from_seed(
s: &str,
) -> (AccountId, BabeId, BeefyId, GrandpaId, ValidatorId, AssignmentId, AuthorityDiscoveryId) {
(
get_account_id_from_seed::<sr25519::Public>(s),
get_from_seed::<AuraId>(s),
get_from_seed::<BabeId>(s),
get_from_seed::<BeefyId>(s),
get_from_seed::<GrandpaId>(s),
get_from_seed::<ValidatorId>(s),
get_from_seed::<AssignmentId>(s),
get_from_seed::<AuthorityDiscoveryId>(s),
)
}
@@ -71,10 +81,7 @@ impl Alternative {
let properties = Some(
json!({
"tokenDecimals": 9,
"tokenSymbol": "RLT",
"bridgeIds": {
"Millau": bp_runtime::MILLAU_CHAIN_ID,
}
"tokenSymbol": "RLT"
})
.as_object()
.expect("Map given; qed")
@@ -82,8 +89,8 @@ impl Alternative {
);
match self {
Alternative::Development => ChainSpec::from_genesis(
"Development",
"dev",
"Rialto Development",
"rialto_dev",
sc_service::ChainType::Development,
|| {
testnet_genesis(
@@ -108,8 +115,8 @@ impl Alternative {
None,
),
Alternative::LocalTestnet => ChainSpec::from_genesis(
"Local Testnet",
"local_testnet",
"Rialto Local",
"rialto_local",
sc_service::ChainType::Local,
|| {
testnet_genesis(
@@ -138,10 +145,12 @@ impl Alternative {
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>("Harry//stash"),
pallet_bridge_messages::Pallet::<
rialto_runtime::Runtime,
pallet_bridge_messages::DefaultInstance,
>::relayer_fund_account_id(),
get_account_id_from_seed::<sr25519::Public>("MillauMessagesOwner"),
get_account_id_from_seed::<sr25519::Public>("WithMillauTokenSwap"),
pallet_bridge_messages::relayer_fund_account_id::<
bp_rialto::AccountId,
bp_rialto::AccountIdConverter,
>(),
derive_account_from_millau_id(bp_runtime::SourceAccount::Account(
get_account_id_from_seed::<sr25519::Public>("Alice"),
)),
@@ -174,12 +183,27 @@ impl Alternative {
}
}
fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys {
SessionKeys { aura, grandpa }
fn session_keys(
babe: BabeId,
beefy: BeefyId,
grandpa: GrandpaId,
para_validator: ValidatorId,
para_assignment: AssignmentId,
authority_discovery: AuthorityDiscoveryId,
) -> SessionKeys {
SessionKeys { babe, beefy, grandpa, para_validator, para_assignment, authority_discovery }
}
fn testnet_genesis(
initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>,
initial_authorities: Vec<(
AccountId,
BabeId,
BeefyId,
GrandpaId,
ValidatorId,
AssignmentId,
AuthorityDiscoveryId,
)>,
root_key: AccountId,
endowed_accounts: Vec<AccountId>,
_enable_println: bool,
@@ -187,51 +211,93 @@ fn testnet_genesis(
GenesisConfig {
system: SystemConfig {
code: WASM_BINARY.expect("Rialto development WASM not available").to_vec(),
changes_trie_config: Default::default(),
},
balances: BalancesConfig {
balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(),
},
aura: AuraConfig {
authorities: Vec::new(),
},
bridge_rialto_poa: load_rialto_poa_bridge_config(),
bridge_kovan: load_kovan_bridge_config(),
grandpa: GrandpaConfig {
babe: BabeConfig {
authorities: Vec::new(),
epoch_config: Some(rialto_runtime::BABE_GENESIS_EPOCH_CONFIG),
},
beefy: BeefyConfig { authorities: Vec::new() },
grandpa: GrandpaConfig { authorities: Vec::new() },
sudo: SudoConfig { key: root_key },
session: SessionConfig {
keys: initial_authorities
.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(),
x.6.clone(),
),
)
})
.collect::<Vec<_>>(),
},
}
}
fn load_rialto_poa_bridge_config() -> BridgeRialtoPoaConfig {
BridgeRialtoPoaConfig {
initial_header: rialto_runtime::rialto_poa::genesis_header(),
initial_difficulty: 0.into(),
initial_validators: rialto_runtime::rialto_poa::genesis_validators(),
}
}
fn load_kovan_bridge_config() -> BridgeKovanConfig {
BridgeKovanConfig {
initial_header: rialto_runtime::kovan::genesis_header(),
initial_difficulty: 0.into(),
initial_validators: rialto_runtime::kovan::genesis_validators(),
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()
},
}
}
#[test]
fn derived_dave_account_is_as_expected() {
let dave = get_account_id_from_seed::<sr25519::Public>("Dave");
let derived: AccountId = derive_account_from_millau_id(bp_runtime::SourceAccount::Account(dave));
assert_eq!(
derived.to_string(),
"5HZhdv53gSJmWWtD8XR5Ypu4PgbT5JNWwGw2mkE75cN61w9t".to_string()
);
let derived: AccountId =
derive_account_from_millau_id(bp_runtime::SourceAccount::Account(dave));
assert_eq!(derived.to_string(), "5HZhdv53gSJmWWtD8XR5Ypu4PgbT5JNWwGw2mkE75cN61w9t".to_string());
}
+17 -2
View File
@@ -29,10 +29,10 @@ pub struct Cli {
/// Possible subcommands of the main binary.
#[derive(Debug, StructOpt)]
pub enum Subcommand {
/// Key management cli utilities
/// Key management CLI utilities
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),
/// Generate a seed that provides a vanity address.
@@ -67,4 +67,19 @@ pub enum Subcommand {
/// Benchmark runtime pallets.
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,
}
+75 -55
View File
@@ -14,9 +14,10 @@
// 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::cli::{Cli, Subcommand};
use crate::service;
use crate::service::new_partial;
use crate::{
cli::{Cli, Subcommand},
service::new_partial,
};
use rialto_runtime::{Block, RuntimeApi};
use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli};
use sc_service::PartialComponents;
@@ -69,24 +70,23 @@ impl SubstrateCli for Cli {
/// Parse and run command line arguments
pub fn run() -> sc_cli::Result<()> {
let cli = Cli::from_args();
sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::Custom(
sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::custom(
rialto_runtime::SS58Prefix::get() as u16,
));
match &cli.subcommand {
Some(Subcommand::Benchmark(cmd)) => {
Some(Subcommand::Benchmark(cmd)) =>
if cfg!(feature = "runtime-benchmarks") {
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 {
println!(
"Benchmarking wasn't enabled when building the node. \
You can enable it with `--features runtime-benchmarks`."
);
Ok(())
}
}
},
Some(Subcommand::Key(cmd)) => cmd.run(&cli),
Some(Subcommand::Sign(cmd)) => cmd.run(),
Some(Subcommand::Verify(cmd)) => cmd.run(),
@@ -94,79 +94,99 @@ pub fn run() -> sc_cli::Result<()> {
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)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client,
task_manager,
import_queue,
..
} = new_partial(&config)?;
runner.async_run(|mut config| {
let PartialComponents { client, task_manager, import_queue, .. } =
new_partial(&mut config).map_err(service_error)?;
Ok((cmd.run(client, import_queue), task_manager))
})
}
},
Some(Subcommand::ExportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client, task_manager, ..
} = new_partial(&config)?;
runner.async_run(|mut config| {
let PartialComponents { client, task_manager, .. } =
new_partial(&mut config).map_err(service_error)?;
Ok((cmd.run(client, config.database), task_manager))
})
}
},
Some(Subcommand::ExportState(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client, task_manager, ..
} = new_partial(&config)?;
runner.async_run(|mut config| {
let PartialComponents { client, task_manager, .. } =
new_partial(&mut config).map_err(service_error)?;
Ok((cmd.run(client, config.chain_spec), task_manager))
})
}
},
Some(Subcommand::ImportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client,
task_manager,
import_queue,
..
} = new_partial(&config)?;
runner.async_run(|mut config| {
let PartialComponents { client, task_manager, import_queue, .. } =
new_partial(&mut config).map_err(service_error)?;
Ok((cmd.run(client, import_queue), task_manager))
})
}
},
Some(Subcommand::PurgeChain(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.database))
}
},
Some(Subcommand::Revert(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents {
client,
task_manager,
backend,
..
} = new_partial(&config)?;
runner.async_run(|mut config| {
let PartialComponents { client, task_manager, backend, .. } =
new_partial(&mut config).map_err(service_error)?;
Ok((cmd.run(client, backend), task_manager))
})
}
},
Some(Subcommand::Inspect(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 => {
let runner = cli.create_runner(&cli.run)?;
runner
.run_node_until_exit(|config| async move {
match config.role {
Role::Light => service::new_light(config),
_ => service::new_full(config),
}
})
.map_err(sc_cli::Error::Service)
}
// 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 {
Role::Light => Err(sc_cli::Error::Service(sc_service::Error::Other(
"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),
}
})
},
}
}
// 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 cli;
mod command;
mod overseer;
mod parachains_db;
/// Run the Rialto Node
fn main() -> sc_cli::Result<()> {
@@ -0,0 +1,316 @@
// 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_provisioner::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,
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_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
+57 -45
View File
@@ -8,16 +8,15 @@ repository = "https://github.com/paritytech/parity-bridges-common/"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[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"
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 }
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
bp-currency-exchange = { path = "../../../primitives/currency-exchange", default-features = false }
bp-eth-poa = { path = "../../../primitives/ethereum-poa", default-features = false }
bp-header-chain = { path = "../../../primitives/header-chain", default-features = false }
bp-message-dispatch = { path = "../../../primitives/message-dispatch", default-features = false }
bp-messages = { path = "../../../primitives/messages", default-features = false }
@@ -25,47 +24,56 @@ bp-millau = { path = "../../../primitives/chain-millau", default-features = fals
bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false }
bp-runtime = { path = "../../../primitives/runtime", default-features = false }
bridge-runtime-common = { path = "../../runtime-common", default-features = false }
pallet-bridge-currency-exchange = { path = "../../../modules/currency-exchange", default-features = false }
pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false }
pallet-bridge-eth-poa = { path = "../../../modules/ethereum", default-features = false }
pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false }
pallet-bridge-messages = { path = "../../../modules/messages", default-features = false }
pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false }
# 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-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-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-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-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-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 }
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-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-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-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-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 }
beefy-primitives = { 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-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-system-rpc-runtime-api = { 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-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-beefy-mmr = { 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-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-mmr-primitives = { 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-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 }
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-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-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-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-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 }
# 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]
libsecp256k1 = { version = "0.3.4", features = ["hmac"] }
libsecp256k1 = { version = "0.7", features = ["hmac"] }
[build-dependencies]
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -73,8 +81,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran
[features]
default = ["std"]
std = [
"bp-currency-exchange/std",
"bp-eth-poa/std",
"beefy-primitives/std",
"bp-header-chain/std",
"bp-message-dispatch/std",
"bp-messages/std",
@@ -89,24 +96,31 @@ std = [
"frame-system-rpc-runtime-api/std",
"frame-system/std",
"log/std",
"pallet-aura/std",
"pallet-authority-discovery/std",
"pallet-babe/std",
"pallet-balances/std",
"pallet-bridge-currency-exchange/std",
"pallet-beefy/std",
"pallet-beefy-mmr/std",
"pallet-bridge-dispatch/std",
"pallet-bridge-eth-poa/std",
"pallet-bridge-grandpa/std",
"pallet-bridge-messages/std",
"pallet-grandpa/std",
"pallet-randomness-collective-flip/std",
"pallet-mmr/std",
"pallet-mmr-primitives/std",
"pallet-shift-session-manager/std",
"pallet-sudo/std",
"pallet-timestamp/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-transaction-payment/std",
"polkadot-primitives/std",
"polkadot-runtime-common/std",
"polkadot-runtime-parachains/std",
"scale-info/std",
"serde",
"sp-api/std",
"sp-authority-discovery/std",
"sp-block-builder/std",
"sp-consensus-aura/std",
"sp-consensus-babe/std",
"sp-core/std",
"sp-finality-grandpa/std",
"sp-inherents/std",
@@ -125,8 +139,6 @@ runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"libsecp256k1",
"pallet-bridge-currency-exchange/runtime-benchmarks",
"pallet-bridge-eth-poa/runtime-benchmarks",
"pallet-bridge-messages/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
@@ -1,37 +0,0 @@
// 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/>.
//! We want to use a different validator configuration for benchmarking than what's used in Kovan
//! or in our Rialto test network. However, we can't configure a new validator set on the fly which
//! means we need to wire the runtime together like this
use pallet_bridge_eth_poa::{ValidatorsConfiguration, ValidatorsSource};
use sp_std::vec;
pub use crate::kovan::{
genesis_header, genesis_validators, BridgeAuraConfiguration, FinalityVotesCachingInterval, PruningStrategy,
};
frame_support::parameter_types! {
pub BridgeValidatorsConfiguration: pallet_bridge_eth_poa::ValidatorsConfiguration = bench_validator_config();
}
fn bench_validator_config() -> ValidatorsConfiguration {
ValidatorsConfiguration::Multi(vec![
(0, ValidatorsSource::List(vec![[1; 20].into()])),
(1, ValidatorsSource::Contract([3; 20].into(), vec![[1; 20].into()])),
])
}
@@ -1,260 +0,0 @@
// 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/>.
//! Support for PoA -> Substrate native tokens exchange.
//!
//! If you want to exchange native PoA tokens for native Substrate
//! chain tokens, you need to:
//! 1) send some PoA tokens to `LOCK_FUNDS_ADDRESS` address on PoA chain. Data field of
//! the transaction must be SCALE-encoded id of Substrate account that will receive
//! funds on Substrate chain;
//! 2) wait until the 'lock funds' transaction is mined on PoA chain;
//! 3) wait until the block containing the 'lock funds' transaction is finalized on PoA chain;
//! 4) wait until the required PoA header and its finality are provided
//! to the PoA -> Substrate bridge module (it can be provided by you);
//! 5) receive tokens by providing proof-of-inclusion of PoA transaction.
use bp_currency_exchange::{
Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, Result as ExchangeResult,
};
use bp_eth_poa::{transaction_decode_rlp, RawTransaction, RawTransactionReceipt};
use codec::{Decode, Encode};
use frame_support::RuntimeDebug;
use hex_literal::hex;
use sp_std::vec::Vec;
/// Ethereum address where locked PoA funds must be sent to.
pub const LOCK_FUNDS_ADDRESS: [u8; 20] = hex!("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF");
/// Ethereum transaction inclusion proof.
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)]
pub struct EthereumTransactionInclusionProof {
/// Hash of the block with transaction.
pub block: sp_core::H256,
/// Index of the transaction within the block.
pub index: u64,
/// The proof itself (right now it is all RLP-encoded transactions of the block +
/// RLP-encoded receipts of all transactions of the block).
pub proof: Vec<(RawTransaction, RawTransactionReceipt)>,
}
/// We uniquely identify transfer by the pair (sender, nonce).
///
/// The assumption is that this pair will never appear more than once in
/// transactions included into finalized blocks. This is obviously true
/// for any existing eth-like chain (that keep current transaction format),
/// because otherwise transaction can be replayed over and over.
#[derive(Encode, Decode, PartialEq, RuntimeDebug)]
pub struct EthereumTransactionTag {
/// Account that has locked funds.
pub account: [u8; 20],
/// Lock transaction nonce.
pub nonce: sp_core::U256,
}
/// Eth transaction from runtime perspective.
pub struct EthTransaction;
impl MaybeLockFundsTransaction for EthTransaction {
type Transaction = RawTransaction;
type Id = EthereumTransactionTag;
type Recipient = crate::AccountId;
type Amount = crate::Balance;
fn parse(
raw_tx: &Self::Transaction,
) -> ExchangeResult<LockFundsTransaction<Self::Id, Self::Recipient, Self::Amount>> {
let tx = transaction_decode_rlp(raw_tx).map_err(|_| ExchangeError::InvalidTransaction)?;
// we only accept transactions sending funds directly to the pre-configured address
if tx.unsigned.to != Some(LOCK_FUNDS_ADDRESS.into()) {
log::trace!(
target: "runtime",
"Failed to parse fund locks transaction. Invalid peer recipient: {:?}",
tx.unsigned.to,
);
return Err(ExchangeError::InvalidTransaction);
}
let mut recipient_raw = sp_core::H256::default();
match tx.unsigned.payload.len() {
32 => recipient_raw.as_fixed_bytes_mut().copy_from_slice(&tx.unsigned.payload),
len => {
log::trace!(
target: "runtime",
"Failed to parse fund locks transaction. Invalid recipient length: {}",
len,
);
return Err(ExchangeError::InvalidRecipient);
}
}
let amount = tx.unsigned.value.low_u128();
if tx.unsigned.value != amount.into() {
log::trace!(
target: "runtime",
"Failed to parse fund locks transaction. Invalid amount: {}",
tx.unsigned.value,
);
return Err(ExchangeError::InvalidAmount);
}
Ok(LockFundsTransaction {
id: EthereumTransactionTag {
account: *tx.sender.as_fixed_bytes(),
nonce: tx.unsigned.nonce,
},
recipient: crate::AccountId::from(*recipient_raw.as_fixed_bytes()),
amount,
})
}
}
/// Prepares everything required to bench claim of funds locked by given transaction.
#[cfg(feature = "runtime-benchmarks")]
pub(crate) fn prepare_environment_for_claim<T: pallet_bridge_eth_poa::Config<I>, I: frame_support::traits::Instance>(
transactions: &[(RawTransaction, RawTransactionReceipt)],
) -> bp_eth_poa::H256 {
use bp_eth_poa::compute_merkle_root;
use pallet_bridge_eth_poa::{
test_utils::{insert_dummy_header, validator_utils::validator, HeaderBuilder},
BridgeStorage, Storage,
};
let mut storage = BridgeStorage::<T, I>::new();
let header = HeaderBuilder::with_parent_number_on_runtime::<T, I>(0)
.transactions_root(compute_merkle_root(transactions.iter().map(|(tx, _)| tx)))
.receipts_root(compute_merkle_root(transactions.iter().map(|(_, receipt)| receipt)))
.sign_by(&validator(0));
let header_id = header.compute_id();
insert_dummy_header(&mut storage, header);
storage.finalize_and_prune_headers(Some(header_id), 0);
header_id.hash
}
/// Prepare signed ethereum lock-funds transaction.
#[cfg(any(feature = "runtime-benchmarks", test))]
pub(crate) fn prepare_ethereum_transaction(
recipient: &crate::AccountId,
editor: impl Fn(&mut bp_eth_poa::UnsignedTransaction),
) -> (RawTransaction, RawTransactionReceipt) {
use bp_eth_poa::{signatures::SignTransaction, Receipt, TransactionOutcome};
// prepare tx for OpenEthereum private dev chain:
// chain id is 0x11
// sender secret is 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7
let chain_id = 0x11;
let signer = secp256k1::SecretKey::parse(&hex!(
"4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7"
))
.unwrap();
let recipient_raw: &[u8; 32] = recipient.as_ref();
let mut eth_tx = bp_eth_poa::UnsignedTransaction {
nonce: 0.into(),
to: Some(LOCK_FUNDS_ADDRESS.into()),
value: 100.into(),
gas: 100_000.into(),
gas_price: 100_000.into(),
payload: recipient_raw.to_vec(),
};
editor(&mut eth_tx);
(
eth_tx.sign_by(&signer, Some(chain_id)),
Receipt {
outcome: TransactionOutcome::StatusCode(1),
gas_used: Default::default(),
log_bloom: Default::default(),
logs: Vec::new(),
}
.rlp(),
)
}
#[cfg(test)]
mod tests {
use super::*;
use hex_literal::hex;
fn ferdie() -> crate::AccountId {
hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c").into()
}
#[test]
fn valid_transaction_accepted() {
assert_eq!(
EthTransaction::parse(&prepare_ethereum_transaction(&ferdie(), |_| {}).0),
Ok(LockFundsTransaction {
id: EthereumTransactionTag {
account: hex!("00a329c0648769a73afac7f9381e08fb43dbea72"),
nonce: 0.into(),
},
recipient: ferdie(),
amount: 100,
}),
);
}
#[test]
fn invalid_transaction_rejected() {
assert_eq!(
EthTransaction::parse(&Vec::new()),
Err(ExchangeError::InvalidTransaction),
);
}
#[test]
fn transaction_with_invalid_peer_recipient_rejected() {
assert_eq!(
EthTransaction::parse(
&prepare_ethereum_transaction(&ferdie(), |tx| {
tx.to = None;
})
.0
),
Err(ExchangeError::InvalidTransaction),
);
}
#[test]
fn transaction_with_invalid_recipient_rejected() {
assert_eq!(
EthTransaction::parse(
&prepare_ethereum_transaction(&ferdie(), |tx| {
tx.payload.clear();
})
.0
),
Err(ExchangeError::InvalidRecipient),
);
}
#[test]
fn transaction_with_invalid_amount_rejected() {
assert_eq!(
EthTransaction::parse(
&prepare_ethereum_transaction(&ferdie(), |tx| {
tx.value = sp_core::U256::from(u128::MAX) + sp_core::U256::from(1);
})
.0
),
Err(ExchangeError::InvalidAmount),
);
}
}
@@ -1,192 +0,0 @@
// 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 crate::exchange::EthereumTransactionInclusionProof;
use bp_eth_poa::{Address, AuraHeader, RawTransaction, U256};
use bp_header_chain::InclusionProofVerifier;
use frame_support::RuntimeDebug;
use hex_literal::hex;
use pallet_bridge_eth_poa::{
AuraConfiguration, ChainTime as TChainTime, PruningStrategy as BridgePruningStrategy, ValidatorsConfiguration,
ValidatorsSource,
};
use sp_std::prelude::*;
frame_support::parameter_types! {
pub const FinalityVotesCachingInterval: Option<u64> = Some(16);
pub BridgeAuraConfiguration: AuraConfiguration =
kovan_aura_configuration();
pub BridgeValidatorsConfiguration: ValidatorsConfiguration =
kovan_validators_configuration();
}
/// Max number of finalized headers to keep. It is equivalent of approximately
/// 24 hours of finalized blocks on current Kovan chain.
const FINALIZED_HEADERS_TO_KEEP: u64 = 20_000;
/// Aura engine configuration for Kovan chain.
pub fn kovan_aura_configuration() -> AuraConfiguration {
AuraConfiguration {
empty_steps_transition: u64::MAX,
strict_empty_steps_transition: 0,
validate_step_transition: 0x16e360,
validate_score_transition: 0x41a3c4,
two_thirds_majority_transition: u64::MAX,
min_gas_limit: 0x1388.into(),
max_gas_limit: U256::MAX,
maximum_extra_data_size: 0x20,
}
}
/// Validators configuration for Kovan chain.
pub fn kovan_validators_configuration() -> ValidatorsConfiguration {
ValidatorsConfiguration::Multi(vec![
(0, ValidatorsSource::List(genesis_validators())),
(
10960440,
ValidatorsSource::List(vec![
hex!("00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED").into(),
hex!("0010f94b296a852aaac52ea6c5ac72e03afd032d").into(),
hex!("00a0a24b9f0e5ec7aa4c7389b8302fd0123194de").into(),
]),
),
(
10960500,
ValidatorsSource::Contract(
hex!("aE71807C1B0a093cB1547b682DC78316D945c9B8").into(),
vec![
hex!("d05f7478c6aa10781258c5cc8b4f385fc8fa989c").into(),
hex!("03801efb0efe2a25ede5dd3a003ae880c0292e4d").into(),
hex!("a4df255ecf08bbf2c28055c65225c9a9847abd94").into(),
hex!("596e8221a30bfe6e7eff67fee664a01c73ba3c56").into(),
hex!("faadface3fbd81ce37b0e19c0b65ff4234148132").into(),
],
),
),
])
}
/// Genesis validators set of Kovan chain.
pub fn genesis_validators() -> Vec<Address> {
vec![
hex!("00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED").into(),
hex!("00427feae2419c15b89d1c21af10d1b6650a4d3d").into(),
hex!("4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c").into(),
hex!("0020ee4Be0e2027d76603cB751eE069519bA81A1").into(),
hex!("0010f94b296a852aaac52ea6c5ac72e03afd032d").into(),
hex!("007733a1FE69CF3f2CF989F81C7b4cAc1693387A").into(),
hex!("00E6d2b931F55a3f1701c7389d592a7778897879").into(),
hex!("00e4a10650e5a6D6001C38ff8E64F97016a1645c").into(),
hex!("00a0a24b9f0e5ec7aa4c7389b8302fd0123194de").into(),
]
}
/// Genesis header of the Kovan chain.
pub fn genesis_header() -> AuraHeader {
AuraHeader {
parent_hash: Default::default(),
timestamp: 0,
number: 0,
author: Default::default(),
transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(),
extra_data: vec![],
state_root: hex!("2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2").into(),
receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
log_bloom: Default::default(),
gas_used: Default::default(),
gas_limit: 6000000.into(),
difficulty: 131072.into(),
seal: vec![
vec![128],
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,
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,
],
],
}
}
/// Kovan headers pruning strategy.
///
/// We do not prune unfinalized headers because exchange module only accepts
/// claims from finalized headers. And if we're pruning unfinalized headers, then
/// some claims may never be accepted.
#[derive(Default, RuntimeDebug)]
pub struct PruningStrategy;
impl BridgePruningStrategy for PruningStrategy {
fn pruning_upper_bound(&mut self, _best_number: u64, best_finalized_number: u64) -> u64 {
best_finalized_number.saturating_sub(FINALIZED_HEADERS_TO_KEEP)
}
}
/// PoA Header timestamp verification against `Timestamp` pallet.
#[derive(Default, RuntimeDebug)]
pub struct ChainTime;
impl TChainTime for ChainTime {
fn is_timestamp_ahead(&self, timestamp: u64) -> bool {
let now = super::Timestamp::now();
timestamp > now
}
}
/// The Kovan Blockchain as seen by the runtime.
pub struct KovanBlockchain;
impl InclusionProofVerifier for KovanBlockchain {
type Transaction = RawTransaction;
type TransactionInclusionProof = EthereumTransactionInclusionProof;
fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option<Self::Transaction> {
let is_transaction_finalized =
crate::BridgeKovan::verify_transaction_finalized(proof.block, proof.index, &proof.proof);
if !is_transaction_finalized {
return None;
}
proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pruning_strategy_keeps_enough_headers() {
assert_eq!(
PruningStrategy::default().pruning_upper_bound(100_000, 10_000),
0,
"10_000 <= 20_000 => nothing should be pruned yet",
);
assert_eq!(
PruningStrategy::default().pruning_upper_bound(100_000, 20_000),
0,
"20_000 <= 20_000 => nothing should be pruned yet",
);
assert_eq!(
PruningStrategy::default().pruning_upper_bound(100_000, 30_000),
10_000,
"20_000 <= 30_000 => we're ready to prune first 10_000 headers",
);
}
}
+354 -364
View File
@@ -30,34 +30,32 @@
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
pub mod exchange;
#[cfg(feature = "runtime-benchmarks")]
pub mod benches;
pub mod kovan;
pub mod millau_messages;
pub mod rialto_poa;
pub mod parachains;
use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge};
use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet};
use bridge_runtime_common::messages::{
source::estimate_message_dispatch_and_delivery_fee, MessageBridge,
};
use codec::Decode;
use pallet_grandpa::{
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
};
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo};
use pallet_mmr_primitives::{
DataOrHash, EncodableOpaqueLeaf, Error as MmrError, LeafDataProvider, Proof as MmrProof,
};
use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo};
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_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys},
traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys},
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")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
@@ -72,8 +70,6 @@ pub use frame_support::{
pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall;
pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall;
pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall;
pub use pallet_bridge_grandpa::Call as BridgeGrandpaMillauCall;
pub use pallet_bridge_messages::Call as MessagesCall;
pub use pallet_sudo::Call as SudoCall;
@@ -101,7 +97,7 @@ pub type AccountIndex = u32;
pub type Balance = bp_rialto::Balance;
/// 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.
pub type Hash = bp_rialto::Hash;
@@ -109,9 +105,6 @@ pub type Hash = bp_rialto::Hash;
/// Hashing algorithm used by the chain.
pub type Hashing = bp_rialto::Hasher;
/// Digest item type.
pub type DigestItem = generic::DigestItem<Hash>;
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
@@ -131,8 +124,12 @@ pub mod opaque {
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: Aura,
pub babe: Babe,
pub grandpa: Grandpa,
pub beefy: Beefy,
pub para_validator: Initializer,
pub para_assignment: SessionInfo,
pub authority_discovery: AuthorityDiscovery,
}
}
@@ -171,7 +168,7 @@ impl frame_system::Config for Runtime {
/// The aggregated dispatch type that is available for extrinsics.
type Call = Call;
/// The lookup mechanism to get account ID from whatever is passed in dispatchers.
type Lookup = IdentityLookup<AccountId>;
type Lookup = AccountIdLookup<AccountId, ()>;
/// The index type for storing how many extrinsics an account has signed.
type Index = Index;
/// The index type for blocks.
@@ -213,62 +210,50 @@ impl frame_system::Config for Runtime {
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! {
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;
}
impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
impl pallet_babe::Config for Runtime {
type EpochDuration = EpochDuration;
type ExpectedBlockTime = ExpectedBlockTime;
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;
impl pallet_bridge_eth_poa::Config<RialtoPoA> for Runtime {
type AuraConfiguration = rialto_poa::BridgeAuraConfiguration;
type FinalityVotesCachingInterval = rialto_poa::FinalityVotesCachingInterval;
type ValidatorsConfiguration = rialto_poa::BridgeValidatorsConfiguration;
type PruningStrategy = rialto_poa::PruningStrategy;
type ChainTime = rialto_poa::ChainTime;
type OnHeadersSubmitted = ();
}
type Kovan = pallet_bridge_eth_poa::Instance2;
impl pallet_bridge_eth_poa::Config<Kovan> for Runtime {
type AuraConfiguration = kovan::BridgeAuraConfiguration;
type FinalityVotesCachingInterval = kovan::FinalityVotesCachingInterval;
type ValidatorsConfiguration = kovan::BridgeValidatorsConfiguration;
type PruningStrategy = kovan::PruningStrategy;
type ChainTime = kovan::ChainTime;
type OnHeadersSubmitted = ();
}
type RialtoCurrencyExchange = pallet_bridge_currency_exchange::Instance1;
impl pallet_bridge_currency_exchange::Config<RialtoCurrencyExchange> for Runtime {
type OnTransactionSubmitted = ();
type PeerBlockchain = rialto_poa::RialtoBlockchain;
type PeerMaybeLockFundsTransaction = exchange::EthTransaction;
type RecipientsMap = bp_currency_exchange::IdentityRecipients<AccountId>;
type Amount = Balance;
type CurrencyConverter = bp_currency_exchange::IdentityCurrencyConverter<Balance>;
type DepositInto = DepositInto;
}
type KovanCurrencyExchange = pallet_bridge_currency_exchange::Instance2;
impl pallet_bridge_currency_exchange::Config<KovanCurrencyExchange> for Runtime {
type OnTransactionSubmitted = ();
type PeerBlockchain = kovan::KovanBlockchain;
type PeerMaybeLockFundsTransaction = exchange::EthTransaction;
type RecipientsMap = bp_currency_exchange::IdentityRecipients<AccountId>;
type Amount = Balance;
type CurrencyConverter = bp_currency_exchange::IdentityCurrencyConverter<Balance>;
type DepositInto = DepositInto;
impl pallet_beefy::Config for Runtime {
type BeefyId = BeefyId;
}
impl pallet_bridge_dispatch::Config for Runtime {
type Event = Event;
type MessageId = (bp_messages::LaneId, bp_messages::MessageNonce);
type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce);
type Call = Call;
type CallFilter = frame_support::traits::Everything;
type EncodedCall = crate::millau_messages::FromMillauEncodedCall;
@@ -278,71 +263,10 @@ impl pallet_bridge_dispatch::Config for Runtime {
type AccountIdConverter = bp_rialto::AccountIdConverter;
}
pub struct DepositInto;
impl bp_currency_exchange::DepositInto for DepositInto {
type Recipient = AccountId;
type Amount = Balance;
fn deposit_into(
recipient: Self::Recipient,
amount: Self::Amount,
) -> bp_currency_exchange::Result<()> {
// let balances module make all checks for us (it won't allow depositing lower than existential
// deposit, balance overflow, ...)
let deposited = <pallet_balances::Pallet<Runtime> as Currency<AccountId>>::deposit_creating(
&recipient, amount,
);
// I'm dropping deposited here explicitly to illustrate the fact that it'll update `TotalIssuance`
// on drop
let deposited_amount = deposited.peek();
drop(deposited);
// we have 3 cases here:
// - deposited == amount: success
// - deposited == 0: deposit has failed and no changes to storage were made
// - deposited != 0: (should never happen in practice) deposit has been partially completed
match deposited_amount {
_ if deposited_amount == amount => {
log::trace!(
target: "runtime",
"Deposited {} to {:?}",
amount,
recipient,
);
Ok(())
},
_ if deposited_amount == 0 => {
log::error!(
target: "runtime",
"Deposit of {} to {:?} has failed",
amount,
recipient,
);
Err(bp_currency_exchange::Error::DepositFailed)
},
_ => {
log::error!(
target: "runtime",
"Deposit of {} to {:?} has partially competed. {} has been deposited",
amount,
recipient,
deposited_amount,
);
// we can't return DepositFailed error here, because storage changes were made
Err(bp_currency_exchange::Error::DepositPartiallyFailed)
},
}
}
}
impl pallet_grandpa::Config for Runtime {
type Event = Event;
type Call = Call;
type MaxAuthorities = MaxAuthorities;
type KeyOwnerProofSystem = ();
type KeyOwnerProof =
<Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;
@@ -356,14 +280,46 @@ impl pallet_grandpa::Config for Runtime {
type MaxAuthorities = MaxAuthorities;
}
impl pallet_mmr::Config for Runtime {
const INDEXING_PREFIX: &'static [u8] = b"mmr";
type Hashing = Keccak256;
type Hash = <Keccak256 as sp_runtime::traits::Hash>::Output;
type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest<Runtime>;
type WeightInfo = ();
type LeafData = pallet_beefy_mmr::Pallet<Runtime>;
}
parameter_types! {
/// Version of the produced MMR leaf.
///
/// The version consists of two parts;
/// - `major` (3 bits)
/// - `minor` (5 bits)
///
/// `major` should be updated only if decoding the previous MMR Leaf format from the payload
/// is not possible (i.e. backward incompatible change).
/// `minor` should be updated if fields are added to the previous MMR Leaf, which given SCALE
/// encoding does not prevent old leafs from being decoded.
///
/// Hence we expect `major` to be changed really rarely (think never).
/// See [`MmrLeafVersion`] type documentation for more details.
pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0);
}
impl pallet_beefy_mmr::Config for Runtime {
type LeafVersion = LeafVersion;
type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum;
type ParachainHeads = ();
}
parameter_types! {
pub const MinimumPeriod: u64 = bp_rialto::SLOT_DURATION / 2;
}
impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the Unix epoch.
type Moment = u64;
type OnTimestampSet = Aura;
/// A timestamp: milliseconds since the UNIX epoch.
type Moment = bp_rialto::Moment;
type OnTimestampSet = Babe;
type MinimumPeriod = MinimumPeriod;
// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
type WeightInfo = ();
@@ -395,13 +351,25 @@ impl pallet_balances::Config for Runtime {
parameter_types! {
pub const TransactionBaseFee: Balance = 0;
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 {
type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, ()>;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = ();
type OperationalFeeMultiplier = OperationalFeeMultiplier;
type WeightToFee = bp_rialto::WeightToFee;
type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment<
Runtime,
TargetBlockFullness,
AdjustmentVariable,
MinimumMultiplier,
>;
}
impl pallet_sudo::Config for Runtime {
@@ -409,17 +377,12 @@ impl pallet_sudo::Config for Runtime {
type Call = Call;
}
parameter_types! {
pub const Period: BlockNumber = bp_rialto::SESSION_LENGTH;
pub const Offset: BlockNumber = 0;
}
impl pallet_session::Config for Runtime {
type Event = Event;
type ValidatorId = <Self as frame_system::Config>::AccountId;
type ValidatorIdOf = ();
type ShouldEndSession = pallet_session::PeriodicSessions<Period, Offset>;
type NextSessionRotation = pallet_session::PeriodicSessions<Period, Offset>;
type ShouldEndSession = Babe;
type NextSessionRotation = Babe;
type SessionManager = pallet_shift_session_manager::Pallet<Runtime>;
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys;
@@ -427,6 +390,10 @@ impl pallet_session::Config for Runtime {
type WeightInfo = ();
}
impl pallet_authority_discovery::Config for Runtime {
type MaxAuthorities = MaxAuthorities;
}
parameter_types! {
/// This is a pretty unscientific cap.
///
@@ -475,10 +442,11 @@ parameter_types! {
pub const GetDeliveryConfirmationTransactionFee: Balance =
bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _;
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.
pub type WithMillauMessagesInstance = pallet_bridge_messages::DefaultInstance;
pub type WithMillauMessagesInstance = ();
impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
type Event = Event;
@@ -502,14 +470,17 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
type MessageDeliveryAndDispatchPayment =
pallet_bridge_messages::instant_payments::InstantCurrencyPayments<
Runtime,
(),
pallet_balances::Pallet<Runtime>,
GetDeliveryConfirmationTransactionFee,
RootAccountForPayments,
>;
type OnMessageAccepted = ();
type OnDeliveryConfirmed = ();
type SourceHeaderChain = crate::millau_messages::Millau;
type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch;
type BridgedChainId = BridgedChainId;
}
construct_runtime!(
@@ -518,28 +489,55 @@ construct_runtime!(
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
BridgeRialtoPoa: pallet_bridge_eth_poa::<Instance1>::{Pallet, Call, Config, Storage, ValidateUnsigned},
BridgeKovan: pallet_bridge_eth_poa::<Instance2>::{Pallet, Call, Config, Storage, ValidateUnsigned},
BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::<Instance1>::{Pallet, Call},
BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::<Instance2>::{Pallet, Call},
BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event<T>},
BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, 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>},
// Must be before session.
Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Aura: pallet_aura::{Pallet, Config<T>},
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
TransactionPayment: pallet_transaction_payment::{Pallet, Storage},
Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>},
// 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},
// BEEFY Bridges support.
Beefy: pallet_beefy::{Pallet, Storage, Config<T>},
Mmr: pallet_mmr::{Pallet, Storage},
MmrLeaf: pallet_beefy_mmr::{Pallet, Storage},
// Millau bridge modules.
BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event<T>},
BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>, Config<T>},
// Parachain modules.
ParachainsOrigin: polkadot_runtime_parachains::origin::{Pallet, Origin},
Configuration: polkadot_runtime_parachains::configuration::{Pallet, Call, Storage, Config<T>},
Shared: polkadot_runtime_parachains::shared::{Pallet, Call, Storage},
Inclusion: polkadot_runtime_parachains::inclusion::{Pallet, Call, Storage, Event<T>},
ParasInherent: polkadot_runtime_parachains::paras_inherent::{Pallet, Call, Storage, Inherent},
Scheduler: polkadot_runtime_parachains::scheduler::{Pallet, Storage},
Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config},
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.
pub type Address = AccountId;
pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
/// Block header type as expected by this runtime.
pub type Header = generic::Header<BlockNumber, Hashing>;
/// Block type as expected by this runtime.
@@ -570,7 +568,7 @@ pub type Executive = frame_executive::Executive<
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
AllPallets,
>;
impl_runtime_apis! {
@@ -621,43 +619,42 @@ impl_runtime_apis! {
}
}
impl bp_eth_poa::RialtoPoAHeaderApi<Block> for Runtime {
fn best_block() -> (u64, bp_eth_poa::H256) {
let best_block = BridgeRialtoPoa::best_block();
(best_block.number, best_block.hash)
}
fn finalized_block() -> (u64, bp_eth_poa::H256) {
let finalized_block = BridgeRialtoPoa::finalized_block();
(finalized_block.number, finalized_block.hash)
}
fn is_import_requires_receipts(header: bp_eth_poa::AuraHeader) -> bool {
BridgeRialtoPoa::is_import_requires_receipts(header)
}
fn is_known_block(hash: bp_eth_poa::H256) -> bool {
BridgeRialtoPoa::is_known_block(hash)
impl beefy_primitives::BeefyApi<Block> for Runtime {
fn validator_set() -> ValidatorSet<BeefyId> {
Beefy::validator_set()
}
}
impl bp_eth_poa::KovanHeaderApi<Block> for Runtime {
fn best_block() -> (u64, bp_eth_poa::H256) {
let best_block = BridgeKovan::best_block();
(best_block.number, best_block.hash)
impl pallet_mmr_primitives::MmrApi<Block, Hash> for Runtime {
fn generate_proof(leaf_index: u64)
-> Result<(EncodableOpaqueLeaf, MmrProof<Hash>), MmrError>
{
Mmr::generate_proof(leaf_index)
.map(|(leaf, proof)| (EncodableOpaqueLeaf::from_leaf(&leaf), proof))
}
fn finalized_block() -> (u64, bp_eth_poa::H256) {
let finalized_block = BridgeKovan::finalized_block();
(finalized_block.number, finalized_block.hash)
fn verify_proof(leaf: EncodableOpaqueLeaf, proof: MmrProof<Hash>)
-> Result<(), MmrError>
{
pub type Leaf = <
<Runtime as pallet_mmr::Config>::LeafData as LeafDataProvider
>::LeafData;
let leaf: Leaf = leaf
.into_opaque_leaf()
.try_decode()
.ok_or(MmrError::Verify)?;
Mmr::verify_leaf(leaf, proof)
}
fn is_import_requires_receipts(header: bp_eth_poa::AuraHeader) -> bool {
BridgeKovan::is_import_requires_receipts(header)
}
fn is_known_block(hash: bp_eth_poa::H256) -> bool {
BridgeKovan::is_known_block(hash)
fn verify_proof_stateless(
root: Hash,
leaf: EncodableOpaqueLeaf,
proof: MmrProof<Hash>
) -> Result<(), MmrError> {
type MmrHashing = <Runtime as pallet_mmr::Config>::Hashing;
let node = DataOrHash::Data(leaf.into_opaque_leaf());
pallet_mmr::verify_leaf_proof::<MmrHashing, _>(root, node, proof)
}
}
@@ -672,18 +669,6 @@ impl_runtime_apis! {
}
}
impl bp_currency_exchange::RialtoCurrencyExchangeApi<Block, exchange::EthereumTransactionInclusionProof> for Runtime {
fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool {
BridgeRialtoCurrencyExchange::filter_transaction_proof(&proof)
}
}
impl bp_currency_exchange::KovanCurrencyExchangeApi<Block, exchange::EthereumTransactionInclusionProof> for Runtime {
fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool {
BridgeKovanCurrencyExchange::filter_transaction_proof(&proof)
}
}
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(
source: TransactionSource,
@@ -700,13 +685,152 @@ impl_runtime_apis! {
}
}
impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
fn slot_duration() -> sp_consensus_aura::SlotDuration {
sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
impl sp_consensus_babe::BabeApi<Block> for Runtime {
fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration {
// 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> {
Aura::authorities()
fn current_epoch_start() -> sp_consensus_babe::Slot {
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 assumed_validation_data(
para_id: polkadot_primitives::v1::Id,
expected_persisted_validation_data_hash: Hash,
) -> Option<(polkadot_primitives::v1::PersistedValidationData<Hash, BlockNumber>, polkadot_primitives::v1::ValidationCodeHash)> {
polkadot_runtime_parachains::runtime_api_impl::v1::assumed_validation_data::<Runtime>(para_id, expected_persisted_validation_data_hash)
}
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 +859,10 @@ impl_runtime_apis! {
}
impl fg_primitives::GrandpaApi<Block> for Runtime {
fn current_set_id() -> fg_primitives::SetId {
Grandpa::current_set_id()
}
fn grandpa_authorities() -> GrandpaAuthorityList {
Grandpa::grandpa_authorities()
}
@@ -781,20 +909,11 @@ impl_runtime_apis! {
begin: bp_messages::MessageNonce,
end: bp_messages::MessageNonce,
) -> Vec<bp_messages::MessageDetails<Balance>> {
(begin..=end).filter_map(|nonce| {
let message_data = BridgeMillauMessages::outbound_message_data(lane, nonce)?;
let decoded_payload = millau_messages::ToMillauMessagePayload::decode(
&mut &message_data.payload[..]
).ok()?;
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()
bridge_runtime_common::messages_api::outbound_message_details::<
Runtime,
WithMillauMessagesInstance,
WithMillauMessageBridge,
>(lane, begin, end)
}
fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce {
@@ -829,18 +948,11 @@ impl_runtime_apis! {
use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};
use frame_support::traits::StorageInfoTrait;
list_benchmark!(
list,
extra,
pallet_bridge_currency_exchange,
BridgeCurrencyExchangeBench::<Runtime, KovanCurrencyExchange>
);
list_benchmark!(
list,
extra,
pallet_bridge_messages,
MessagesBench::<Runtime, WithMillauMessagesInstance>
);
use pallet_bridge_messages::benchmarking::Pallet as MessagesBench;
let mut list = Vec::<BenchmarkList>::new();
list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::<Runtime, WithMillauMessagesInstance>);
list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeMillauGrandpa);
let storage_info = AllPalletsWithSystem::storage_info();
@@ -873,46 +985,6 @@ impl_runtime_apis! {
let mut batches = Vec::<BenchmarkBatch>::new();
let params = (&config, &whitelist);
use pallet_bridge_currency_exchange::benchmarking::{
Pallet as BridgeCurrencyExchangeBench,
Config as BridgeCurrencyExchangeConfig,
ProofParams as BridgeCurrencyExchangeProofParams,
};
impl BridgeCurrencyExchangeConfig<KovanCurrencyExchange> for Runtime {
fn make_proof(
proof_params: BridgeCurrencyExchangeProofParams<AccountId>,
) -> crate::exchange::EthereumTransactionInclusionProof {
use bp_currency_exchange::DepositInto;
if proof_params.recipient_exists {
<Runtime as pallet_bridge_currency_exchange::Config<KovanCurrencyExchange>>::DepositInto::deposit_into(
proof_params.recipient.clone(),
ExistentialDeposit::get(),
).unwrap();
}
let (transaction, receipt) = crate::exchange::prepare_ethereum_transaction(
&proof_params.recipient,
|tx| {
// our runtime only supports transactions where data is exactly 32 bytes long
// (receiver key)
// => we are ignoring `transaction_size_factor` here
tx.value = (ExistentialDeposit::get() * 10).into();
},
);
let transactions = sp_std::iter::repeat((transaction, receipt))
.take(1 + proof_params.proof_size_factor as usize)
.collect::<Vec<_>>();
let block_hash = crate::exchange::prepare_environment_for_claim::<Runtime, Kovan>(&transactions);
crate::exchange::EthereumTransactionInclusionProof {
block: block_hash,
index: 0,
proof: transactions,
}
}
}
use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge};
use bp_runtime::messages::DispatchFeePayment;
use bridge_runtime_common::messages;
@@ -981,7 +1053,7 @@ impl_runtime_apis! {
MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _],
_ => vec![],
};
let call = Call::System(SystemCall::remark(remark));
let call = Call::System(SystemCall::remark { remark });
let call_weight = call.get_dispatch_info().weight;
let millau_account_id: bp_millau::AccountId = Default::default();
@@ -1001,14 +1073,12 @@ impl_runtime_apis! {
Self::endow_account(&rialto_public.clone().into_account());
}
let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key::<
<WithMillauMessageBridge as MessageBridge>::BridgedMessagesInstance,
>(
let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key(
<WithMillauMessageBridge as MessageBridge>::BRIDGED_MESSAGES_PALLET_NAME,
&message_key.lane_id, message_key.nonce,
).0;
let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key::<
<WithMillauMessageBridge as MessageBridge>::BridgedMessagesInstance,
>(
let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key(
<WithMillauMessageBridge as MessageBridge>::BRIDGED_MESSAGES_PALLET_NAME,
&lane_id,
).0;
@@ -1054,9 +1124,8 @@ impl_runtime_apis! {
prepare_message_delivery_proof::<WithMillauMessageBridge, bp_millau::Hasher, Runtime, (), _, _>(
params,
|lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key::<
<WithMillauMessageBridge as MessageBridge>::BridgedMessagesInstance,
>(
|lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key(
<WithMillauMessageBridge as MessageBridge>::BRIDGED_MESSAGES_PALLET_NAME,
&lane_id,
).0,
|state_root| bp_millau::Header::new(
@@ -1082,12 +1151,6 @@ impl_runtime_apis! {
}
}
add_benchmark!(
params,
batches,
pallet_bridge_currency_exchange,
BridgeCurrencyExchangeBench::<Runtime, KovanCurrencyExchange>
);
add_benchmark!(
params,
batches,
@@ -1104,8 +1167,8 @@ impl_runtime_apis! {
/// Millau account ownership digest from Rialto.
///
/// 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
/// is also under his control.
/// This way, the owner of `rialto_account_id` on Rialto proves that the 'millau' account private
/// key is also under his control.
pub fn rialto_to_millau_account_ownership_digest<Call, AccountId, SpecVersion>(
millau_call: &Call,
rialto_account_id: AccountId,
@@ -1128,48 +1191,8 @@ where
#[cfg(test)]
mod tests {
use super::*;
use bp_currency_exchange::DepositInto;
use bridge_runtime_common::messages;
fn run_deposit_into_test(test: impl Fn(AccountId) -> Balance) {
let mut ext: sp_io::TestExternalities =
SystemConfig::default().build_storage::<Runtime>().unwrap().into();
ext.execute_with(|| {
// initially issuance is zero
assert_eq!(
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::total_issuance(),
0,
);
// create account
let account: AccountId = [1u8; 32].into();
let initial_amount = ExistentialDeposit::get();
let deposited =
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::deposit_creating(
&account,
initial_amount,
);
drop(deposited);
assert_eq!(
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::total_issuance(),
initial_amount,
);
assert_eq!(
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(&account),
initial_amount,
);
// run test
let total_issuance_change = test(account);
// check that total issuance has changed by `run_deposit_into_test`
assert_eq!(
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::total_issuance(),
initial_amount + total_issuance_change,
);
});
}
#[test]
fn ensure_rialto_message_lane_weights_are_correct() {
type Weights = pallet_bridge_messages::weights::RialtoWeight<Runtime>;
@@ -1179,6 +1202,7 @@ mod tests {
bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT,
bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT,
bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT,
DbWeight::get(),
);
let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add(
@@ -1206,50 +1230,16 @@ mod tests {
max_incoming_inbound_lane_data_proof_size,
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
DbWeight::get(),
);
}
#[test]
fn deposit_into_existing_account_works() {
run_deposit_into_test(|existing_account| {
let initial_amount =
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(
&existing_account,
);
let additional_amount = 10_000;
<Runtime as pallet_bridge_currency_exchange::Config<KovanCurrencyExchange>>::DepositInto::deposit_into(
existing_account.clone(),
additional_amount,
)
.unwrap();
assert_eq!(
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(
&existing_account
),
initial_amount + additional_amount,
);
additional_amount
});
}
#[test]
fn deposit_into_new_account_works() {
run_deposit_into_test(|_| {
let initial_amount = 0;
let additional_amount = ExistentialDeposit::get() + 10_000;
let new_account: AccountId = [42u8; 32].into();
<Runtime as pallet_bridge_currency_exchange::Config<KovanCurrencyExchange>>::DepositInto::deposit_into(
new_account.clone(),
additional_amount,
)
.unwrap();
assert_eq!(
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(
&new_account
),
initial_amount + additional_amount,
);
additional_amount
});
fn call_size() {
const DOT_MAX_CALL_SZ: usize = 230;
assert!(core::mem::size_of::<pallet_bridge_grandpa::Call<Runtime>>() <= DOT_MAX_CALL_SZ);
// FIXME: get this down to 230. https://github.com/paritytech/grandpa-bridge-gadget/issues/359
const BEEFY_MAX_CALL_SZ: usize = 232;
assert!(core::mem::size_of::<pallet_bridge_messages::Call<Runtime>>() <= BEEFY_MAX_CALL_SZ);
}
}
@@ -31,25 +31,34 @@ use frame_support::{
weights::{DispatchClass, Weight},
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};
/// 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! {
/// Millau to Rialto conversion rate. Initially we treat both tokens as equal.
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.
pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload<WithMillauMessageBridge>;
pub type ToMillauMessagePayload =
messages::source::FromThisChainMessagePayload<WithMillauMessageBridge>;
/// 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.
pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload<WithMillauMessageBridge>;
pub type FromMillauMessagePayload =
messages::target::FromBridgedChainMessagePayload<WithMillauMessageBridge>;
/// Encoded Rialto Call as it comes from Millau.
pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessageCall<crate::Call>;
@@ -59,14 +68,15 @@ pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDi
WithMillauMessageBridge,
crate::Runtime,
pallet_balances::Pallet<Runtime>,
pallet_bridge_dispatch::DefaultInstance,
(),
>;
/// Messages proof for Millau -> Rialto messages.
pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_millau::Hash>;
/// 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.
#[derive(RuntimeDebug, Clone, Copy)]
@@ -76,14 +86,16 @@ impl MessageBridge for WithMillauMessageBridge {
const RELAYER_FEE_PERCENT: u32 = 10;
const THIS_CHAIN_ID: ChainId = RIALTO_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 BridgedChain = Millau;
type BridgedMessagesInstance = crate::WithMillauMessagesInstance;
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))
.unwrap_or(bp_rialto::Balance::MAX)
bp_rialto::Balance::try_from(
MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance),
)
.unwrap_or(bp_rialto::Balance::MAX)
}
}
@@ -128,11 +140,15 @@ impl messages::ThisChainWithMessages for Rialto {
}
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
messages::transaction_payment(
bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic,
1,
FixedU128::zero(),
multiplier,
|weight| weight as _,
transaction,
)
@@ -159,12 +175,15 @@ impl messages::BridgedChainWithMessages for Millau {
fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive<Weight> {
// 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
// minimal dispatch weight here
// this bridge may be used to deliver all kind of messages, so we're not making any
// assumptions about minimal dispatch weight here
0..=upper_limit
}
@@ -195,11 +214,14 @@ impl messages::BridgedChainWithMessages for Millau {
}
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
messages::transaction_payment(
bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic,
1,
FixedU128::zero(),
multiplier,
|weight| weight as _,
transaction,
)
@@ -221,9 +243,11 @@ impl TargetHeaderChain<ToMillauMessagePayload, bp_millau::AccountId> for Millau
fn verify_messages_delivery_proof(
proof: Self::MessagesDeliveryProof,
) -> Result<(LaneId, InboundLaneData<bp_rialto::AccountId>), Self::Error> {
messages::source::verify_messages_delivery_proof::<WithMillauMessageBridge, Runtime, crate::MillauGrandpaInstance>(
proof,
)
messages::source::verify_messages_delivery_proof::<
WithMillauMessageBridge,
Runtime,
crate::MillauGrandpaInstance,
>(proof)
}
}
@@ -240,15 +264,16 @@ impl SourceHeaderChain<bp_millau::Balance> for Millau {
proof: Self::MessagesProof,
messages_count: u32,
) -> Result<ProvedMessages<Message<bp_millau::Balance>>, Self::Error> {
messages::target::verify_messages_proof::<WithMillauMessageBridge, Runtime, crate::MillauGrandpaInstance>(
proof,
messages_count,
)
messages::target::verify_messages_proof::<
WithMillauMessageBridge,
Runtime,
crate::MillauGrandpaInstance,
>(proof, messages_count)
}
}
/// Rialto -> Millau message lane pallet parameters.
#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq)]
#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)]
pub enum RialtoToMillauMessagesParameter {
/// The conversion formula we use is: `RialtoTokens = MillauTokens * conversion_rate`.
MillauToRialtoConversionRate(FixedU128),
@@ -257,9 +282,8 @@ pub enum RialtoToMillauMessagesParameter {
impl MessagesParameter for RialtoToMillauMessagesParameter {
fn save(&self) {
match *self {
RialtoToMillauMessagesParameter::MillauToRialtoConversionRate(ref conversion_rate) => {
MillauToRialtoConversionRate::set(conversion_rate)
}
RialtoToMillauMessagesParameter::MillauToRialtoConversionRate(ref conversion_rate) =>
MillauToRialtoConversionRate::set(conversion_rate),
}
}
}
@@ -274,7 +298,9 @@ mod tests {
MessageKey,
};
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::{
traits::Currency,
weights::{GetDispatchInfo, WeightToFeePolynomial},
@@ -286,12 +312,15 @@ mod tests {
// 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
// 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(|| {
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_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);
// create relayer account with minimal balance
@@ -303,12 +332,13 @@ mod tests {
);
// create dispatch account with minimal balance + dispatch fee
let dispatch_account = derive_account_id::<<Runtime as pallet_bridge_dispatch::Config>::SourceChainAccountId>(
bridge,
SourceAccount::Root,
);
let dispatch_account = derive_account_id::<
<Runtime as pallet_bridge_dispatch::Config>::SourceChainAccountId,
>(bridge, SourceAccount::Root);
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(
&dispatch_account,
initial_amount + dispatch_fee,
@@ -318,10 +348,7 @@ mod tests {
FromMillauMessageDispatch::dispatch(
&relayer_account,
DispatchMessage {
key: MessageKey {
lane_id: Default::default(),
nonce: 0,
},
key: MessageKey { lane_id: Default::default(), nonce: 0 },
data: DispatchMessageData {
payload: Ok(FromBridgedChainMessagePayload::<WithMillauMessageBridge> {
spec_version: VERSION.spec_version,
@@ -337,11 +364,15 @@ mod tests {
// ensure that fee has been transferred from dispatch to relayer account
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,
);
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,
);
});
@@ -0,0 +1,160 @@
// 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 {
type WeightInfo = parachains_paras_inherent::TestWeightInfo;
}
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
}
}
@@ -1,175 +0,0 @@
// 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/>.
//! Configuration parameters for the Rialto PoA chain.
use crate::exchange::EthereumTransactionInclusionProof;
use bp_eth_poa::{Address, AuraHeader, RawTransaction, U256};
use bp_header_chain::InclusionProofVerifier;
use frame_support::RuntimeDebug;
use hex_literal::hex;
use pallet_bridge_eth_poa::{
AuraConfiguration, ChainTime as TChainTime, PruningStrategy as TPruningStrategy, ValidatorsConfiguration,
ValidatorsSource,
};
use sp_std::prelude::*;
frame_support::parameter_types! {
pub const FinalityVotesCachingInterval: Option<u64> = Some(8);
pub BridgeAuraConfiguration: AuraConfiguration =
aura_configuration();
pub BridgeValidatorsConfiguration: ValidatorsConfiguration =
validators_configuration();
}
/// Max number of finalized headers to keep.
const FINALIZED_HEADERS_TO_KEEP: u64 = 5_000;
/// Aura engine configuration for Rialto chain.
pub fn aura_configuration() -> AuraConfiguration {
AuraConfiguration {
empty_steps_transition: 0xfffffffff,
strict_empty_steps_transition: 0,
validate_step_transition: 0,
validate_score_transition: 0,
two_thirds_majority_transition: u64::MAX,
min_gas_limit: 0x1388.into(),
max_gas_limit: U256::MAX,
maximum_extra_data_size: 0x20,
}
}
/// Validators configuration for Rialto PoA chain.
pub fn validators_configuration() -> ValidatorsConfiguration {
ValidatorsConfiguration::Single(ValidatorsSource::List(genesis_validators()))
}
/// Genesis validators set of Rialto PoA chain.
pub fn genesis_validators() -> Vec<Address> {
vec![
hex!("005e714f896a8b7cede9d38688c1a81de72a58e4").into(),
hex!("007594304039c2937a12220338aab821d819f5a4").into(),
hex!("004e7a39907f090e19b0b80a277e77b72b22e269").into(),
]
}
/// Genesis header of the Rialto PoA chain.
///
/// To obtain genesis header from a running node, invoke:
/// ```bash
/// $ http localhost:8545 jsonrpc=2.0 id=1 method=eth_getBlockByNumber params:='["earliest", false]' -v
/// ```
pub fn genesis_header() -> AuraHeader {
AuraHeader {
parent_hash: Default::default(),
timestamp: 0,
number: 0,
author: Default::default(),
transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(),
extra_data: vec![],
state_root: hex!("a992d04c791620ed7ed96555a80cf0568355bb4bee2656f46899a4372f25f248").into(),
receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
log_bloom: Default::default(),
gas_used: Default::default(),
gas_limit: 0x222222.into(),
difficulty: 0x20000.into(),
seal: vec![vec![0x80], {
let mut vec = vec![0xb8, 0x41];
vec.resize(67, 0);
vec
}],
}
}
/// Rialto PoA headers pruning strategy.
///
/// We do not prune unfinalized headers because exchange module only accepts
/// claims from finalized headers. And if we're pruning unfinalized headers, then
/// some claims may never be accepted.
#[derive(Default, RuntimeDebug)]
pub struct PruningStrategy;
impl TPruningStrategy for PruningStrategy {
fn pruning_upper_bound(&mut self, _best_number: u64, best_finalized_number: u64) -> u64 {
best_finalized_number.saturating_sub(FINALIZED_HEADERS_TO_KEEP)
}
}
/// `ChainTime` provider
#[derive(Default)]
pub struct ChainTime;
impl TChainTime for ChainTime {
fn is_timestamp_ahead(&self, timestamp: u64) -> bool {
let now = super::Timestamp::now();
timestamp > now
}
}
/// The Rialto PoA Blockchain as seen by the runtime.
pub struct RialtoBlockchain;
impl InclusionProofVerifier for RialtoBlockchain {
type Transaction = RawTransaction;
type TransactionInclusionProof = EthereumTransactionInclusionProof;
fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option<Self::Transaction> {
let is_transaction_finalized =
crate::BridgeRialtoPoa::verify_transaction_finalized(proof.block, proof.index, &proof.proof);
if !is_transaction_finalized {
return None;
}
proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn genesis_hash_matches() {
assert_eq!(
genesis_header().compute_hash(),
hex!("1468e1a0fa20d30025a5a0f87e1cced4fdc393b84b7d2850b11ca5863db482cb").into(),
);
}
#[test]
fn pruning_strategy_keeps_enough_headers() {
assert_eq!(
PruningStrategy::default().pruning_upper_bound(100_000, 1_000),
0,
"1_000 <= 5_000 => nothing should be pruned yet",
);
assert_eq!(
PruningStrategy::default().pruning_upper_bound(100_000, 5_000),
0,
"5_000 <= 5_000 => nothing should be pruned yet",
);
assert_eq!(
PruningStrategy::default().pruning_upper_bound(100_000, 10_000),
5_000,
"5_000 <= 10_000 => we're ready to prune first 5_000 headers",
);
}
}
@@ -8,7 +8,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[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 }
hash-db = { version = "0.15.2", default-features = false }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
@@ -24,13 +24,13 @@ pallet-bridge-messages = { path = "../../modules/messages", default-features = f
# Substrate dependencies
frame-support = { 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 }
sp-core = { 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-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
frame-support = { 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 }
sp-core = { 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-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
[features]
default = ["std"]
@@ -19,4 +19,5 @@
#![cfg_attr(not(feature = "std"), no_std)]
pub mod messages;
pub mod messages_api;
pub mod messages_benchmarking;
@@ -32,17 +32,20 @@ use bp_runtime::{
};
use codec::{Decode, Encode};
use frame_support::{
traits::{Currency, ExistenceRequirement, Instance},
traits::{Currency, ExistenceRequirement},
weights::{Weight, WeightToFeePolynomial},
RuntimeDebug,
};
use hash_db::Hasher;
use scale_info::TypeInfo;
use sp_runtime::{
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul},
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Saturating, Zero},
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;
/// Bidirectional message bridge.
@@ -54,16 +57,20 @@ pub trait MessageBridge {
const THIS_CHAIN_ID: ChainId;
/// Identifier of the Bridged chain.
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.
type ThisChain: ThisChainWithMessages;
/// Bridged chain in context of message bridge.
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.
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.
@@ -73,16 +80,23 @@ pub trait ChainWithMessages {
/// Accound id on the chain.
type AccountId: Encode + Decode;
/// 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.
type Signature: Decode;
type Signature: Encode + Decode;
/// 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
/// may be different, the `WeightOf<>` construct is used to avoid confusion between
/// different weights.
type Weight: From<frame_support::weights::Weight> + PartialOrd;
/// 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.
@@ -137,30 +151,40 @@ pub trait BridgedChainWithMessages: ChainWithMessages {
message_dispatch_weight: 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>;
}
pub(crate) type ThisChain<B> = <B as MessageBridge>::ThisChain;
pub(crate) type BridgedChain<B> = <B as MessageBridge>::BridgedChain;
pub(crate) type HashOf<C> = <C as ChainWithMessages>::Hash;
pub(crate) type AccountIdOf<C> = <C as ChainWithMessages>::AccountId;
pub(crate) type SignerOf<C> = <C as ChainWithMessages>::Signer;
pub(crate) type SignatureOf<C> = <C as ChainWithMessages>::Signature;
pub(crate) type WeightOf<C> = <C as ChainWithMessages>::Weight;
pub(crate) type BalanceOf<C> = <C as ChainWithMessages>::Balance;
pub(crate) type CallOf<C> = <C as ThisChainWithMessages>::Call;
/// This chain in context of message bridge.
pub type ThisChain<B> = <B as MessageBridge>::ThisChain;
/// Bridged chain in context of message bridge.
pub type BridgedChain<B> = <B as MessageBridge>::BridgedChain;
/// Hash used on the chain.
pub type HashOf<C> = <C as ChainWithMessages>::Hash;
/// Account id used on the chain.
pub type AccountIdOf<C> = <C as ChainWithMessages>::AccountId;
/// Public key of the chain account that may be used to verify signature.
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).
type RawStorageProof = Vec<Vec<u8>>;
/// 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`
/// at the moment when transaction is submitted. If you're charging this payment in advance (and that's what
/// happens with delivery and confirmation 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.
/// The value of `multiplier` parameter is the expected value of
/// `pallet_transaction_payment::NextFeeMultiplier` at the moment when transaction is submitted. If
/// you're charging this payment in advance (and that's what happens with delivery and confirmation
/// 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>(
base_extrinsic_weight: Weight,
per_byte_fee: Balance,
@@ -223,7 +247,8 @@ pub mod source {
}
/// '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.
///
@@ -235,19 +260,30 @@ pub mod source {
/// Following checks are made:
///
/// - message is rejected if its lane is currently blocked;
/// - message is rejected if there are too many pending (undelivered) messages at the outbound lane;
/// - check that the sender has rights to dispatch the call on target chain using provided dispatch origin;
/// - message is rejected if there are too many pending (undelivered) messages at the outbound
/// 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.
#[derive(RuntimeDebug)]
pub struct FromThisChainMessageVerifier<B>(PhantomData<B>);
pub(crate) const OUTBOUND_LANE_DISABLED: &str = "The outbound message lane is disabled.";
pub(crate) const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane.";
pub(crate) const BAD_ORIGIN: &str = "Unable to match the source origin to expected target origin.";
pub(crate) const TOO_LOW_FEE: &str = "Provided fee is below minimal threshold required by the lane.";
/// The error message returned from LaneMessageVerifier when outbound lane is disabled.
pub const OUTBOUND_LANE_DISABLED: &str = "The outbound message lane is disabled.";
/// The error message returned from LaneMessageVerifier when too many pending messages at the
/// 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>>>
for FromThisChainMessageVerifier<B>
impl<B>
LaneMessageVerifier<
AccountIdOf<ThisChain<B>>,
FromThisChainMessagePayload<B>,
BalanceOf<ThisChain<B>>,
> for FromThisChainMessageVerifier<B>
where
B: MessageBridge,
AccountIdOf<ThisChain<B>>: PartialEq + Clone,
@@ -263,7 +299,7 @@ pub mod source {
) -> Result<(), Self::Error> {
// reject message if lane is blocked
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
@@ -272,19 +308,20 @@ pub mod source {
.latest_generated_nonce
.saturating_sub(lane_outbound_data.latest_received_nonce);
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
// `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 =
estimate_message_dispatch_and_delivery_fee::<B>(payload, B::RELAYER_FEE_PERCENT)?;
// compare with actual fee paid
if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens {
return Err(TOO_LOW_FEE);
return Err(TOO_LOW_FEE)
}
Ok(())
@@ -306,13 +343,13 @@ pub mod source {
) -> Result<(), &'static str> {
let weight_limits = BridgedChain::<B>::message_weight_limits(&payload.call);
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
// `frame_system::Config::MaximumBlockLength` and `frame_system::Config::AvailableBlockRatio`
// constants. This check is here to be sure that the lane won't stuck because message is too
// large to fit into delivery transaction.
// `frame_system::Config::MaximumBlockLength` and
// `frame_system::Config::AvailableBlockRatio` constants. This check is here to be sure that
// 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
// 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
// 1/3 of the the maximal extrinsic weight for this data.
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(())
}
/// 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.
/// Returns `None` if overflow has happened.
/// The fee is paid in This chain Balance, but we use Bridged chain balance to avoid additional
/// conversions. Returns `None` if overflow has happened.
pub fn estimate_message_dispatch_and_delivery_fee<B: MessageBridge>(
payload: &FromThisChainMessagePayload<B>,
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
// 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(
&payload.call,
&payload.encode(),
pay_dispatch_fee_at_target_chain,
if pay_dispatch_fee_at_target_chain {
0.into()
} else {
payload.weight.into()
},
if pay_dispatch_fee_at_target_chain { 0.into() } else { payload.weight.into() },
);
let delivery_transaction_fee = BridgedChain::<B>::transaction_payment(delivery_transaction);
// 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_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
let minimal_fee =
B::bridged_balance_to_this_balance(delivery_transaction_fee).checked_add(&confirmation_transaction_fee);
let minimal_fee = B::bridged_balance_to_this_balance(delivery_transaction_fee)
.checked_add(&confirmation_transaction_fee);
// before returning, add extra fee that is paid to the relayer (relayer interest)
minimal_fee
@@ -377,14 +413,14 @@ pub mod source {
) -> Result<ParsedMessagesDeliveryProofFromBridgedChain<B>, &'static str>
where
ThisRuntime: pallet_bridge_grandpa::Config<GrandpaInstance>,
HashOf<BridgedChain<B>>:
Into<bp_runtime::HashOf<<ThisRuntime as pallet_bridge_grandpa::Config<GrandpaInstance>>::BridgedChain>>,
HashOf<BridgedChain<B>>: Into<
bp_runtime::HashOf<
<ThisRuntime as pallet_bridge_grandpa::Config<GrandpaInstance>>::BridgedChain,
>,
>,
{
let FromBridgedChainMessagesDeliveryProof {
bridged_header_hash,
storage_proof,
lane,
} = proof;
let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane } =
proof;
pallet_bridge_grandpa::Pallet::<ThisRuntime, GrandpaInstance>::parse_finalized_storage_proof(
bridged_header_hash.into(),
StorageProof::new(storage_proof),
@@ -392,7 +428,7 @@ pub mod source {
// Messages delivery proof is just proof of single storage key read => any error
// is fatal.
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
.read_value(storage_inbound_lane_data_key.0.as_ref())
.map_err(|_| "Failed to read inbound lane state from storage proof")?
@@ -469,14 +505,13 @@ pub mod target {
impl<DecodedCall> FromBridgedChainEncodedMessageCall<DecodedCall> {
/// Create encoded call.
pub fn new(encoded_call: Vec<u8>) -> Self {
FromBridgedChainEncodedMessageCall {
encoded_call,
_marker: PhantomData::default(),
}
FromBridgedChainEncodedMessageCall { 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 {
DecodedCall::decode(&mut &encoded_call.encoded_call[..]).map_err(drop)
}
@@ -492,20 +527,24 @@ pub mod target {
MessageDispatch<AccountIdOf<ThisChain<B>>, BalanceOf<BridgedChain<B>>>
for FromBridgedChainMessageDispatch<B, ThisRuntime, ThisCurrency, ThisDispatchInstance>
where
ThisDispatchInstance: frame_support::traits::Instance,
ThisRuntime: pallet_bridge_dispatch::Config<ThisDispatchInstance, MessageId = (LaneId, MessageNonce)>
+ pallet_transaction_payment::Config,
BalanceOf<ThisChain<B>>: Saturating + FixedPointOperand,
ThisDispatchInstance: 'static,
ThisRuntime: pallet_bridge_dispatch::Config<
ThisDispatchInstance,
BridgeMessageId = (LaneId, MessageNonce),
> + pallet_transaction_payment::Config,
<ThisRuntime as pallet_transaction_payment::Config>::OnChargeTransaction:
pallet_transaction_payment::OnChargeTransaction<ThisRuntime, Balance = BalanceOf<ThisChain<B>>>,
pallet_transaction_payment::OnChargeTransaction<
ThisRuntime,
Balance = BalanceOf<ThisChain<B>>,
>,
ThisCurrency: Currency<AccountIdOf<ThisChain<B>>, Balance = BalanceOf<ThisChain<B>>>,
<ThisRuntime as pallet_bridge_dispatch::Config<ThisDispatchInstance>>::Event: From<
pallet_bridge_dispatch::RawEvent<(LaneId, MessageNonce), AccountIdOf<ThisChain<B>>, ThisDispatchInstance>,
>,
pallet_bridge_dispatch::Pallet<ThisRuntime, ThisDispatchInstance>: bp_message_dispatch::MessageDispatch<
AccountIdOf<ThisChain<B>>,
(LaneId, MessageNonce),
Message = FromBridgedChainMessagePayload<B>,
>,
pallet_bridge_dispatch::Pallet<ThisRuntime, ThisDispatchInstance>:
bp_message_dispatch::MessageDispatch<
AccountIdOf<ThisChain<B>>,
(LaneId, MessageNonce),
Message = FromBridgedChainMessagePayload<B>,
>,
{
type DispatchPayload = FromBridgedChainMessagePayload<B>;
@@ -526,13 +565,22 @@ pub mod target {
message_id,
message.data.payload.map_err(drop),
|dispatch_origin, dispatch_weight| {
ThisCurrency::transfer(
dispatch_origin,
relayer_account,
ThisRuntime::WeightToFee::calc(&dispatch_weight),
ExistenceRequirement::AllowDeath,
)
.map_err(drop)
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(
dispatch_origin,
relayer_account,
adjusted_weight_fee,
ExistenceRequirement::AllowDeath,
)
.map_err(drop)
} else {
Ok(())
}
},
)
}
@@ -559,9 +607,11 @@ pub mod target {
) -> Result<ProvedMessages<Message<BalanceOf<BridgedChain<B>>>>, &'static str>
where
ThisRuntime: pallet_bridge_grandpa::Config<GrandpaInstance>,
ThisRuntime: pallet_bridge_messages::Config<B::BridgedMessagesInstance>,
HashOf<BridgedChain<B>>:
Into<bp_runtime::HashOf<<ThisRuntime as pallet_bridge_grandpa::Config<GrandpaInstance>>::BridgedChain>>,
HashOf<BridgedChain<B>>: Into<
bp_runtime::HashOf<
<ThisRuntime as pallet_bridge_grandpa::Config<GrandpaInstance>>::BridgedChain,
>,
>,
{
verify_messages_proof_with_parser::<B, _, _>(
proof,
@@ -596,12 +646,13 @@ pub mod target {
fn from(err: MessageProofError) -> &'static str {
match err {
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::FailedToDecodeMessage => "Failed to decode message from the proof",
MessageProofError::FailedToDecodeOutboundLaneState => {
"Failed to decode outbound lane data from the proof"
}
MessageProofError::FailedToDecodeMessage =>
"Failed to decode message from the proof",
MessageProofError::FailedToDecodeOutboundLaneState =>
"Failed to decode outbound lane data from the proof",
MessageProofError::Custom(err) => err,
}
}
@@ -624,14 +675,16 @@ pub mod target {
{
fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option<Vec<u8>> {
let storage_outbound_lane_data_key =
pallet_bridge_messages::storage_keys::outbound_lane_data_key::<B::BridgedMessagesInstance>(lane_id);
self.storage
.read_value(storage_outbound_lane_data_key.0.as_ref())
.ok()?
pallet_bridge_messages::storage_keys::outbound_lane_data_key(
B::BRIDGED_MESSAGES_PALLET_NAME,
lane_id,
);
self.storage.read_value(storage_outbound_lane_data_key.0.as_ref()).ok()?
}
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.nonce,
);
@@ -646,7 +699,8 @@ pub mod target {
build_parser: BuildParser,
) -> Result<ProvedMessages<Message<BalanceOf<BridgedChain<B>>>>, MessageProofError>
where
BuildParser: FnOnce(HashOf<BridgedChain<B>>, RawStorageProof) -> Result<Parser, MessageProofError>,
BuildParser:
FnOnce(HashOf<BridgedChain<B>>, RawStorageProof) -> Result<Parser, MessageProofError>,
Parser: MessageProofParser,
{
let FromBridgedChainMessagesProof {
@@ -658,18 +712,19 @@ pub mod target {
} = proof;
// 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's check that the user (relayer) has passed correct `messages_count`
// (this bounds maximal capacity of messages vec below)
let messages_in_the_proof = nonces_difference.saturating_add(1);
if messages_in_the_proof != MessageNonce::from(messages_count) {
return Err(MessageProofError::MessagesCountMismatch);
}
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`
// (this bounds maximal capacity of messages vec below)
let messages_in_the_proof = nonces_difference.saturating_add(1);
if messages_in_the_proof != MessageNonce::from(messages_count) {
return Err(MessageProofError::MessagesCountMismatch)
}
messages_in_the_proof
} else {
0
};
messages_in_the_proof
} else {
0
};
let parser = build_parser(bridged_header_hash, storage_proof)?;
@@ -683,20 +738,15 @@ pub mod target {
let raw_message_data = parser
.read_raw_message(&message_key)
.ok_or(MessageProofError::MissingRequiredMessage)?;
let message_data = MessageData::<BalanceOf<BridgedChain<B>>>::decode(&mut &raw_message_data[..])
.map_err(|_| MessageProofError::FailedToDecodeMessage)?;
messages.push(Message {
key: message_key,
data: message_data,
});
let message_data =
MessageData::<BalanceOf<BridgedChain<B>>>::decode(&mut &raw_message_data[..])
.map_err(|_| MessageProofError::FailedToDecodeMessage)?;
messages.push(Message { key: message_key, data: message_data });
}
// Now let's check if proof contains outbound lane state proof. It is optional, so we
// simply ignore `read_value` errors and missing value.
let mut proved_lane_messages = ProvedLaneMessages {
lane_state: None,
messages,
};
let mut proved_lane_messages = ProvedLaneMessages { lane_state: None, messages };
let raw_outbound_lane_data = parser.read_raw_outbound_lane_data(&lane);
if let Some(raw_outbound_lane_data) = raw_outbound_lane_data {
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.
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
@@ -733,7 +783,8 @@ mod tests {
const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: Weight = 2048;
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)]
struct OnThisChainBridge;
@@ -741,17 +792,20 @@ mod tests {
const RELAYER_FEE_PERCENT: u32 = 10;
const THIS_CHAIN_ID: ChainId = *b"this";
const BRIDGED_CHAIN_ID: ChainId = *b"brdg";
const BRIDGED_MESSAGES_PALLET_NAME: &'static str = "";
type ThisChain = ThisChain;
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)
}
}
/// 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)]
struct OnBridgedChainBridge;
@@ -759,10 +813,10 @@ mod tests {
const RELAYER_FEE_PERCENT: u32 = 20;
const THIS_CHAIN_ID: ChainId = *b"brdg";
const BRIDGED_CHAIN_ID: ChainId = *b"this";
const BRIDGED_MESSAGES_PALLET_NAME: &'static str = "";
type ThisChain = BridgedChain;
type BridgedChain = ThisChain;
type BridgedMessagesInstance = pallet_bridge_messages::DefaultInstance;
fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance {
unreachable!()
@@ -886,7 +940,9 @@ mod tests {
}
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!()
}
fn transaction_payment(_transaction: MessageTransaction<WeightOf<Self>>) -> BalanceOf<Self> {
fn transaction_payment(
_transaction: MessageTransaction<WeightOf<Self>>,
) -> BalanceOf<Self> {
unreachable!()
}
}
@@ -938,7 +996,9 @@ mod tests {
unreachable!()
}
fn transaction_payment(_transaction: MessageTransaction<WeightOf<Self>>) -> BalanceOf<Self> {
fn transaction_payment(
_transaction: MessageTransaction<WeightOf<Self>>,
) -> BalanceOf<Self> {
unreachable!()
}
}
@@ -949,7 +1009,8 @@ mod tests {
}
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
}
@@ -965,7 +1026,9 @@ mod tests {
}
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,19 +1039,22 @@ mod tests {
#[test]
fn message_from_bridged_chain_is_decoded() {
// the message is encoded on the bridged chain
let message_on_bridged_chain = source::FromThisChainMessagePayload::<OnBridgedChainBridge> {
spec_version: 1,
weight: 100,
origin: bp_message_dispatch::CallOrigin::SourceRoot,
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
call: ThisChainCall::Transfer.encode(),
}
.encode();
let message_on_bridged_chain =
source::FromThisChainMessagePayload::<OnBridgedChainBridge> {
spec_version: 1,
weight: 100,
origin: bp_message_dispatch::CallOrigin::SourceRoot,
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
call: ThisChainCall::Transfer.encode(),
}
.encode();
// and sent to this chain where it is decoded
let message_on_this_chain =
target::FromBridgedChainMessagePayload::<OnThisChainBridge>::decode(&mut &message_on_bridged_chain[..])
.unwrap();
target::FromBridgedChainMessagePayload::<OnThisChainBridge>::decode(
&mut &message_on_bridged_chain[..],
)
.unwrap();
assert_eq!(
message_on_this_chain,
target::FromBridgedChainMessagePayload::<OnThisChainBridge> {
@@ -1007,7 +1073,8 @@ mod tests {
const TEST_LANE_ID: &LaneId = b"test";
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> {
spec_version: 1,
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 mut payload_with_pay_on_target = regular_outbound_message_payload();
payload_with_pay_on_target.dispatch_fee_payment = DispatchFeePayment::AtTargetChain;
let fee_at_source = source::estimate_message_dispatch_and_delivery_fee::<OnThisChainBridge>(
&payload_with_pay_on_target,
OnThisChainBridge::RELAYER_FEE_PERCENT,
)
.expect("estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message");
let fee_at_source =
source::estimate_message_dispatch_and_delivery_fee::<OnThisChainBridge>(
&payload_with_pay_on_target,
OnThisChainBridge::RELAYER_FEE_PERCENT,
)
.expect(
"estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message",
);
assert!(
fee_at_source < EXPECTED_MINIMAL_FEE.into(),
"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)
);
assert!(
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
&Sender::Root,
&ThisChainBalance(1_000_000),
TEST_LANE_ID,
&test_lane_outbound_data(),
&payload,
)
.is_ok(),
);
assert!(source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
&Sender::Root,
&ThisChainBalance(1_000_000),
TEST_LANE_ID,
&test_lane_outbound_data(),
&payload,
)
.is_ok(),);
}
#[test]
@@ -1103,16 +1171,14 @@ mod tests {
),
Err(source::BAD_ORIGIN)
);
assert!(
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
&Sender::Root,
&ThisChainBalance(1_000_000),
TEST_LANE_ID,
&test_lane_outbound_data(),
&payload,
)
.is_ok(),
);
assert!(source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
&Sender::Root,
&ThisChainBalance(1_000_000),
TEST_LANE_ID,
&test_lane_outbound_data(),
&payload,
)
.is_ok(),);
}
#[test]
@@ -1137,16 +1203,14 @@ mod tests {
),
Err(source::BAD_ORIGIN)
);
assert!(
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
&Sender::Signed(ThisChainAccountId(1)),
&ThisChainBalance(1_000_000),
TEST_LANE_ID,
&test_lane_outbound_data(),
&payload,
)
.is_ok(),
);
assert!(source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
&Sender::Signed(ThisChainAccountId(1)),
&ThisChainBalance(1_000_000),
TEST_LANE_ID,
&test_lane_outbound_data(),
&payload,
)
.is_ok(),);
}
#[test]
@@ -1183,64 +1247,58 @@ mod tests {
#[test]
fn verify_chain_message_rejects_message_with_too_small_declared_weight() {
assert!(
source::verify_chain_message::<OnThisChainBridge>(&source::FromThisChainMessagePayload::<
OnThisChainBridge,
> {
assert!(source::verify_chain_message::<OnThisChainBridge>(
&source::FromThisChainMessagePayload::<OnThisChainBridge> {
spec_version: 1,
weight: 5,
origin: bp_message_dispatch::CallOrigin::SourceRoot,
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
call: vec![1, 2, 3, 4, 5, 6],
},)
.is_err()
);
},
)
.is_err());
}
#[test]
fn verify_chain_message_rejects_message_with_too_large_declared_weight() {
assert!(
source::verify_chain_message::<OnThisChainBridge>(&source::FromThisChainMessagePayload::<
OnThisChainBridge,
> {
assert!(source::verify_chain_message::<OnThisChainBridge>(
&source::FromThisChainMessagePayload::<OnThisChainBridge> {
spec_version: 1,
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1,
origin: bp_message_dispatch::CallOrigin::SourceRoot,
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
call: vec![1, 2, 3, 4, 5, 6],
},)
.is_err()
);
},
)
.is_err());
}
#[test]
fn verify_chain_message_rejects_message_too_large_message() {
assert!(
source::verify_chain_message::<OnThisChainBridge>(&source::FromThisChainMessagePayload::<
OnThisChainBridge,
> {
assert!(source::verify_chain_message::<OnThisChainBridge>(
&source::FromThisChainMessagePayload::<OnThisChainBridge> {
spec_version: 1,
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
origin: bp_message_dispatch::CallOrigin::SourceRoot,
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as usize + 1],
},)
.is_err()
);
},
)
.is_err());
}
#[test]
fn verify_chain_message_accepts_maximal_message() {
assert_eq!(
source::verify_chain_message::<OnThisChainBridge>(&source::FromThisChainMessagePayload::<
OnThisChainBridge,
> {
spec_version: 1,
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
origin: bp_message_dispatch::CallOrigin::SourceRoot,
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as _],
},),
source::verify_chain_message::<OnThisChainBridge>(
&source::FromThisChainMessagePayload::<OnThisChainBridge> {
spec_version: 1,
weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT,
origin: bp_message_dispatch::CallOrigin::SourceRoot,
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
call: vec![0; source::maximal_message_size::<OnThisChainBridge>() as _],
},
),
Ok(()),
);
}
@@ -1332,13 +1390,15 @@ mod tests {
#[test]
fn message_proof_is_rejected_if_required_message_is_missing() {
assert_eq!(
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(messages_proof(10), 10, |_, _| Ok(
TestMessageProofParser {
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(
messages_proof(10),
10,
|_, _| Ok(TestMessageProofParser {
failing: false,
messages: 1..=5,
outbound_lane_data: None,
}
),),
}),
),
Err(target::MessageProofError::MissingRequiredMessage),
);
}
@@ -1346,13 +1406,15 @@ mod tests {
#[test]
fn message_proof_is_rejected_if_message_decode_fails() {
assert_eq!(
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(messages_proof(10), 10, |_, _| Ok(
TestMessageProofParser {
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(
messages_proof(10),
10,
|_, _| Ok(TestMessageProofParser {
failing: true,
messages: 1..=10,
outbound_lane_data: None,
}
),),
}),
),
Err(target::MessageProofError::FailedToDecodeMessage),
);
}
@@ -1360,8 +1422,10 @@ mod tests {
#[test]
fn message_proof_is_rejected_if_outbound_lane_state_decode_fails() {
assert_eq!(
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(messages_proof(0), 0, |_, _| Ok(
TestMessageProofParser {
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(
messages_proof(0),
0,
|_, _| Ok(TestMessageProofParser {
failing: true,
messages: no_messages_range(),
outbound_lane_data: Some(OutboundLaneData {
@@ -1369,8 +1433,8 @@ mod tests {
latest_received_nonce: 1,
latest_generated_nonce: 1,
}),
}
),),
}),
),
Err(target::MessageProofError::FailedToDecodeOutboundLaneState),
);
}
@@ -1378,13 +1442,15 @@ mod tests {
#[test]
fn message_proof_is_rejected_if_it_is_empty() {
assert_eq!(
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(messages_proof(0), 0, |_, _| Ok(
TestMessageProofParser {
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(
messages_proof(0),
0,
|_, _| Ok(TestMessageProofParser {
failing: false,
messages: no_messages_range(),
outbound_lane_data: None,
}
),),
}),
),
Err(target::MessageProofError::Empty),
);
}
@@ -1392,8 +1458,10 @@ mod tests {
#[test]
fn non_empty_message_proof_without_messages_is_accepted() {
assert_eq!(
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(messages_proof(0), 0, |_, _| Ok(
TestMessageProofParser {
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(
messages_proof(0),
0,
|_, _| Ok(TestMessageProofParser {
failing: false,
messages: no_messages_range(),
outbound_lane_data: Some(OutboundLaneData {
@@ -1401,8 +1469,8 @@ mod tests {
latest_received_nonce: 1,
latest_generated_nonce: 1,
}),
}
),),
}),
),
Ok(vec![(
Default::default(),
ProvedLaneMessages {
@@ -1422,8 +1490,10 @@ mod tests {
#[test]
fn non_empty_message_proof_is_accepted() {
assert_eq!(
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(messages_proof(1), 1, |_, _| Ok(
TestMessageProofParser {
target::verify_messages_proof_with_parser::<OnThisChainBridge, _, _>(
messages_proof(1),
1,
|_, _| Ok(TestMessageProofParser {
failing: false,
messages: 1..=1,
outbound_lane_data: Some(OutboundLaneData {
@@ -1431,8 +1501,8 @@ mod tests {
latest_received_nonce: 1,
latest_generated_nonce: 1,
}),
}
),),
}),
),
Ok(vec![(
Default::default(),
ProvedLaneMessages {
@@ -1442,14 +1512,8 @@ mod tests {
latest_generated_nonce: 1,
}),
messages: vec![Message {
key: MessageKey {
lane_id: Default::default(),
nonce: 1
},
data: MessageData {
payload: 1u64.encode(),
fee: BridgedChainBalance(0)
},
key: MessageKey { lane_id: Default::default(), nonce: 1 },
data: MessageData { payload: 1u64.encode(), fee: BridgedChainBalance(0) },
}],
},
)]
@@ -1488,10 +1552,7 @@ mod tests {
10,
FixedU128::zero(),
|weight| weight,
MessageTransaction {
size: 50,
dispatch_weight: 777
},
MessageTransaction { size: 50, dispatch_weight: 777 },
),
100 + 50 * 10,
);
@@ -1507,10 +1568,7 @@ mod tests {
10,
FixedU128::one(),
|weight| weight,
MessageTransaction {
size: 50,
dispatch_weight: 777
},
MessageTransaction { size: 50, dispatch_weight: 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")]
use crate::messages::{
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, AccountIdOf, BalanceOf,
BridgedChain, HashOf, MessageBridge, ThisChain,
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
AccountIdOf, BalanceOf, BridgedChain, HashOf, MessageBridge, ThisChain,
};
use bp_messages::{LaneId, MessageData, MessageKey, MessagePayload};
@@ -29,13 +29,16 @@ use bp_runtime::ChainId;
use codec::Encode;
use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH};
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_runtime::traits::Header;
use sp_std::prelude::*;
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.
pub fn ed25519_sign(
@@ -47,8 +50,8 @@ pub fn ed25519_sign(
) -> ([u8; 32], [u8; 64]) {
// key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html)
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,
105, 025, 112, 059, 172, 003, 028, 174, 127, 096,
157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073,
197, 105, 123, 050, 105, 025, 112, 059, 172, 003, 028, 174, 127, 096,
])
.expect("harcoded key is valid");
let target_public: PublicKey = (&target_secret).into();
@@ -56,7 +59,8 @@ pub fn ed25519_sign(
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_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(
target_call,
@@ -92,11 +96,8 @@ where
MH: Fn(H::Out) -> <R::BridgedChain as bp_runtime::Chain>::Header,
{
// prepare Bridged chain storage with messages and (optionally) outbound lane state
let message_count = params
.message_nonces
.end()
.saturating_sub(*params.message_nonces.start())
+ 1;
let message_count =
params.message_nonces.end().saturating_sub(*params.message_nonces.start()) + 1;
let mut storage_keys = Vec::with_capacity(message_count as usize + 1);
let mut root = Default::default();
let mut mdb = MemoryDB::default();
@@ -105,10 +106,7 @@ where
// insert messages
for nonce in params.message_nonces.clone() {
let message_key = MessageKey {
lane_id: params.lane,
nonce,
};
let message_key = MessageKey { lane_id: params.lane, nonce };
let message_data = MessageData {
fee: BalanceOf::<BridgedChain<B>>::from(0),
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");
let size: usize = proof_recorder.drain().into_iter().map(|n| n.data.len()).sum();
if size > minimal_trie_size as _ {
return root;
return root
}
let mut trie = TrieDBMut::<H>::from_existing(mdb, &mut root)
+1 -1
View File
@@ -24,7 +24,7 @@ USER user
WORKDIR /home/user
ARG PROJECT=ethereum-poa-relay
ARG PROJECT=substrate-relay
COPY --chown=user:user ./${PROJECT} ./
COPY --chown=user:user ./bridge-entrypoint.sh ./
+10 -16
View File
@@ -48,27 +48,21 @@ notice = "warn"
# A list of advisory IDs to ignore. Note that ignored advisories will still
# output a note when they are encountered.
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.
"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",
# Comes from honggfuzz via storage-proof-fuzzer: 'memmap'
"RUSTSEC-2020-0077",
# 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
# 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
[licenses]
# The lint level for crates which do not have a detectable license
unlicensed = "deny"
unlicensed = "allow"
# List of explictly allowed licenses
# See https://spdx.org/licenses/ for list of possible licenses
# [possible values: any SPDX 3.7 short identifier (+ optional exception)].
+13 -20
View File
@@ -44,16 +44,16 @@ the monitoring Compose file is _not_ optional, and must be included for bridge d
### Running and Updating Deployments
We currently support two bridge deployments
1. Ethereum PoA to Rialto Substrate
2. Rialto Substrate to Millau Substrate
1. Rialto Substrate to Millau Substrate
2. Westend Substrate to Millau Substrate
These bridges can be deployed using our [`./run.sh`](./run.sh) script.
The first argument it takes is the name of the bridge you want to run. Right now we only support two
bridges: `poa-rialto` and `rialto-millau`.
bridges: `rialto-millau` and `westend-millau`.
```bash
./run.sh poa-rialto
./run.sh rialto-millau
```
If you add a second `update` argument to the script it will pull the latest images from Docker Hub
@@ -66,7 +66,7 @@ and restart the deployment.
You can also bring down a deployment using the script with the `stop` argument.
```bash
./run.sh poa-rialto stop
./run.sh rialto-millau stop
```
### Adding Deployments
@@ -80,7 +80,6 @@ not strictly required.
## General Notes
Rialto authorities are named: `Alice`, `Bob`, `Charlie`, `Dave`, `Eve`.
Rialto-PoA authorities are named: `Arthur`, `Bertha`, `Carlos`.
Millau authorities are named: `Alice`, `Bob`, `Charlie`, `Dave`, `Eve`.
Both authorities and following accounts have enough funds (for test purposes) on corresponding Substrate chains:
@@ -89,11 +88,11 @@ Both authorities and following accounts have enough funds (for test purposes) on
- on Millau: `Ferdie`, `George`, `Harry`.
Names of accounts on Substrate (Rialto and Millau) chains may be prefixed with `//` and used as
seeds for the `sr25519` keys. This seed may also be used in the signer argument in Substrate
and PoA relays. Example:
seeds for the `sr25519` keys. This seed may also be used in the signer argument in Substrate relays.
Example:
```bash
./substrate-relay relay-headers RialtoToMillau \
./substrate-relay relay-headers rialto-to-millau \
--source-host rialto-node-alice \
--source-port 9944 \
--target-host millau-node-alice \
@@ -105,13 +104,6 @@ and PoA relays. Example:
Some accounts are used by bridge components. Using these accounts to sign other transactions
is not recommended, because this may lead to nonces conflict.
Following accounts are used when `poa-rialto` bridge is running:
- Rialto's `Alice` signs relay transactions with new Rialto-PoA headers;
- Rialto's `Bob` signs relay transactions with Rialto-PoA -> Rialto currency exchange proofs.
- Rialto-PoA's `Arthur`: signs relay transactions with new Rialto headers;
- Rialto-PoA's `Bertha`: signs currency exchange transactions.
Following accounts are used when `rialto-millau` bridge is running:
- Millau's `Charlie` signs complex headers+messages relay transactions on Millau chain;
@@ -121,7 +113,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;
- 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;
- 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:
@@ -131,10 +125,10 @@ Following accounts are used when `westend-millau` bridge is running:
When the network is running you can query logs from individual nodes using:
```bash
docker logs rialto_poa-node-bertha_1 -f
docker logs rialto_millau-node-charlie_1 -f
```
To kill all left over containers and start the network from scratch next time:
To kill all leftover containers and start the network from scratch next time:
```bash
docker ps -a --format "{{.ID}}" | xargs docker rm # This removes all containers!
```
@@ -188,7 +182,6 @@ Here are the arguments currently supported:
- `PROJECT`: Project to build withing bridges repo. Can be one of:
- `rialto-bridge-node`
- `millau-bridge-node`
- `ethereum-poa-relay`
- `substrate-relay`
### GitHub Actions
@@ -1,26 +0,0 @@
FROM docker.io/library/node:12 as build-deps
# install tools and dependencies
RUN set -eux; \
apt-get install -y git
# clone UI repo
RUN cd /usr/src/ && git clone https://github.com/paritytech/bridge-ui.git
WORKDIR /usr/src/bridge-ui
RUN yarn
ARG SUBSTRATE_PROVIDER
ARG ETHEREUM_PROVIDER
ARG EXPECTED_ETHEREUM_NETWORK_ID
ENV SUBSTRATE_PROVIDER $SUBSTRATE_PROVIDER
ENV ETHEREUM_PROVIDER $ETHEREUM_PROVIDER
ENV EXPECTED_ETHEREUM_NETWORK_ID $EXPECTED_ETHEREUM_NETWORK_ID
RUN yarn build:docker
# Stage 2 - the production environment
FROM docker.io/library/nginx:1.12
COPY --from=build-deps /usr/src/bridge-ui/nginx/*.conf /etc/nginx/conf.d/
COPY --from=build-deps /usr/src/bridge-ui/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
@@ -1,474 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"links": [],
"panels": [
{
"datasource": "Prometheus",
"description": "",
"fieldConfig": {
"defaults": {
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 7,
"x": 0,
"y": 0
},
"id": 2,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "Ethereum_to_Substrate_Exchange_best_block_numbers",
"instant": true,
"interval": "",
"legendFormat": "Best {{type}} block",
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Best finalized blocks",
"type": "stat"
},
{
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 5,
"x": 7,
"y": 0
},
"id": 12,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "Ethereum_to_Substrate_Exchange_processed_blocks",
"instant": true,
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Number of processed blocks since last restart",
"type": "stat"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"custom": {},
"links": []
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 9,
"w": 6,
"x": 12,
"y": 0
},
"hiddenSeries": false,
"id": 6,
"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": "Ethereum_to_Substrate_Exchange_system_average_load",
"interval": "",
"legendFormat": "Average system load in last {{over}}",
"refId": "A"
}
],
"thresholds": [
{
"colorMode": "critical",
"fill": true,
"line": true,
"op": "gt",
"value": null
}
],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Average System Load",
"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",
"description": "",
"fieldConfig": {
"defaults": {
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 6,
"x": 18,
"y": 0
},
"id": 8,
"options": {
"orientation": "auto",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true
},
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "Ethereum_to_Substrate_Exchange_process_cpu_usage_percentage",
"interval": "",
"legendFormat": "1 CPU = 100",
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Relay Process CPU Usage",
"type": "gauge"
},
{
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 10,
"w": 12,
"x": 0,
"y": 7
},
"id": 14,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "Ethereum_to_Substrate_Exchange_processed_transactions",
"instant": true,
"interval": "",
"legendFormat": "{{type}} transactions",
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Number of processed transactions since last restart",
"type": "stat"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"custom": {},
"links": []
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 9
},
"hiddenSeries": false,
"id": 10,
"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": "Ethereum_to_Substrate_Exchange_process_memory_usage_bytes / 1024 / 1024",
"interval": "",
"legendFormat": "Process memory, MB",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Memory Usage for Relay Process",
"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
}
}
],
"refresh": "5s",
"schemaVersion": 26,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-5m",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
]
},
"timezone": "",
"title": "Ethereum PoA to Rialto Exchange Dashboard",
"uid": "relay-poa-to-rialto-exchange",
"version": 1
}
@@ -1,694 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"links": [],
"panels": [
{
"alert": {
"alertRuleTags": {},
"conditions": [
{
"evaluator": {
"params": [
5
],
"type": "gt"
},
"operator": {
"type": "and"
},
"query": {
"params": [
"A",
"5m",
"now"
]
},
"reducer": {
"params": [],
"type": "min"
},
"type": "query"
}
],
"executionErrorState": "alerting",
"for": "5m",
"frequency": "5m",
"handler": 1,
"message": "",
"name": "Synced Header Difference is Over 5 (Ethereum PoA to Rialto)",
"noDataState": "no_data",
"notifications": []
},
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"description": "Shows how many headers behind the target chain is from the source chain.",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 14,
"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": "max(Ethereum_to_Substrate_Sync_best_block_numbers{node=\"source\"}) - max(Ethereum_to_Substrate_Sync_best_block_numbers{node=\"target\"})",
"format": "table",
"instant": false,
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"thresholds": [
{
"colorMode": "critical",
"fill": true,
"line": true,
"op": "gt",
"value": 5
}
],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Difference Between Source and Target Headers",
"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
}
},
{
"alert": {
"alertRuleTags": {},
"conditions": [
{
"evaluator": {
"params": [
5
],
"type": "lt"
},
"operator": {
"type": "and"
},
"query": {
"params": [
"A",
"2m",
"now"
]
},
"reducer": {
"params": [],
"type": "min"
},
"type": "query"
}
],
"executionErrorState": "alerting",
"for": "3m",
"frequency": "5m",
"handler": 1,
"name": "No New Headers (Ethereum PoA to Rialto)",
"noDataState": "no_data",
"notifications": []
},
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"description": "How many headers has the relay synced from the source node in the last 2 mins?",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 0
},
"hiddenSeries": false,
"id": 16,
"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": "max_over_time(Ethereum_to_Substrate_Sync_best_block_numbers{node=\"source\"}[2m])-min_over_time(Ethereum_to_Substrate_Sync_best_block_numbers{node=\"source\"}[2m])",
"interval": "",
"legendFormat": "Number of new Headers on Ethereum PoA (Last 2 Mins)",
"refId": "A"
}
],
"thresholds": [
{
"colorMode": "critical",
"fill": true,
"line": true,
"op": "lt",
"value": 5
}
],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Headers Synced on Rialto (Last 2 Mins)",
"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",
"fieldConfig": {
"defaults": {
"custom": {
"align": null
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 6,
"w": 12,
"x": 0,
"y": 8
},
"id": 2,
"interval": "5s",
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "Ethereum_to_Substrate_Sync_best_block_numbers",
"format": "time_series",
"instant": true,
"interval": "",
"intervalFactor": 1,
"legendFormat": "Best Known Header on {{node}} Node",
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Best Blocks according to Relay",
"type": "stat"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"description": "",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 6,
"x": 12,
"y": 8
},
"hiddenSeries": false,
"id": 6,
"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": "Ethereum_to_Substrate_Sync_system_average_load",
"interval": "",
"legendFormat": "Average system load in last {{over}}",
"refId": "A"
}
],
"thresholds": [
{
"colorMode": "critical",
"fill": true,
"line": true,
"op": "gt",
"value": null
}
],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Average System Load",
"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",
"fieldConfig": {
"defaults": {
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 6,
"x": 18,
"y": 8
},
"id": 12,
"options": {
"orientation": "auto",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true
},
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "avg_over_time(Ethereum_to_Substrate_Sync_process_cpu_usage_percentage[1m])",
"instant": true,
"interval": "",
"legendFormat": "1 CPU = 100",
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Relay Process CPU Usage ",
"type": "gauge"
},
{
"datasource": "Prometheus",
"description": "",
"fieldConfig": {
"defaults": {
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 10,
"w": 12,
"x": 0,
"y": 14
},
"id": 4,
"options": {
"displayMode": "gradient",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"showUnfilled": true
},
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "Ethereum_to_Substrate_Sync_blocks_in_state",
"instant": true,
"interval": "",
"legendFormat": "{{state}}",
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Queued Headers in Relay",
"type": "bargauge"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"description": "",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 16
},
"hiddenSeries": false,
"id": 10,
"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": "Ethereum_to_Substrate_Sync_process_memory_usage_bytes / 1024 / 1024",
"interval": "",
"legendFormat": "Process memory, MB",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Memory Usage for Relay Process",
"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
}
}
],
"refresh": "5s",
"schemaVersion": 26,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-5m",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
]
},
"timezone": "",
"title": "Ethereum PoA to Rialto Header Sync Dashboard",
"uid": "relay-poa-to-rialto-headers",
"version": 1
}
@@ -1,694 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"links": [],
"panels": [
{
"alert": {
"alertRuleTags": {},
"conditions": [
{
"evaluator": {
"params": [
5
],
"type": "gt"
},
"operator": {
"type": "and"
},
"query": {
"params": [
"A",
"5m",
"now"
]
},
"reducer": {
"params": [],
"type": "min"
},
"type": "query"
}
],
"executionErrorState": "alerting",
"for": "5m",
"frequency": "5m",
"handler": 1,
"message": "",
"name": "Synced Header Difference is Over 5 (Rialto to Ethereum PoA)",
"noDataState": "no_data",
"notifications": []
},
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"description": "Shows how many headers behind the target chain is from the source chain.",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 14,
"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": "max(Substrate_to_Ethereum_Sync_best_block_numbers{node=\"source\"}) - max(Substrate_to_Ethereum_Sync_best_block_numbers{node=\"target\"})",
"format": "table",
"instant": false,
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"thresholds": [
{
"colorMode": "critical",
"fill": true,
"line": true,
"op": "gt",
"value": 5
}
],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Difference Between Source and Target Headers",
"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
}
},
{
"alert": {
"alertRuleTags": {},
"conditions": [
{
"evaluator": {
"params": [
5
],
"type": "lt"
},
"operator": {
"type": "and"
},
"query": {
"params": [
"A",
"2m",
"now"
]
},
"reducer": {
"params": [],
"type": "min"
},
"type": "query"
}
],
"executionErrorState": "alerting",
"for": "3m",
"frequency": "5m",
"handler": 1,
"name": "No New Headers (Rialto to Ethereum PoA)",
"noDataState": "no_data",
"notifications": []
},
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"description": "How many headers has the relay synced from the source node in the last 2 mins?",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 0
},
"hiddenSeries": false,
"id": 16,
"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": "max_over_time(Substrate_to_Ethereum_Sync_best_block_numbers{node=\"source\"}[2m])-min_over_time(Substrate_to_Ethereum_Sync_best_block_numbers{node=\"source\"}[2m])",
"interval": "",
"legendFormat": "Number of new Headers on Rialto (Last 2 Mins)",
"refId": "A"
}
],
"thresholds": [
{
"colorMode": "critical",
"fill": true,
"line": true,
"op": "lt",
"value": 5
}
],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Headers Synced on Ethereum PoA (Last 2 Mins)",
"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",
"fieldConfig": {
"defaults": {
"custom": {
"align": null
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 6,
"w": 12,
"x": 0,
"y": 8
},
"id": 2,
"interval": "5s",
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "Substrate_to_Ethereum_Sync_best_block_numbers",
"format": "time_series",
"instant": true,
"interval": "",
"intervalFactor": 1,
"legendFormat": "Best Known Header on {{node}} Node",
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Best Blocks according to Relay",
"type": "stat"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"description": "",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 6,
"x": 12,
"y": 8
},
"hiddenSeries": false,
"id": 6,
"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": "Substrate_to_Ethereum_Sync_system_average_load",
"interval": "",
"legendFormat": "Average system load in last {{over}}",
"refId": "A"
}
],
"thresholds": [
{
"colorMode": "critical",
"fill": true,
"line": true,
"op": "gt",
"value": null
}
],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Average System Load",
"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",
"fieldConfig": {
"defaults": {
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 6,
"x": 18,
"y": 8
},
"id": 12,
"options": {
"orientation": "auto",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true
},
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "avg_over_time(Substrate_to_Ethereum_Sync_process_cpu_usage_percentage[1m])",
"instant": true,
"interval": "",
"legendFormat": "1 CPU = 100",
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Relay Process CPU Usage ",
"type": "gauge"
},
{
"datasource": "Prometheus",
"description": "",
"fieldConfig": {
"defaults": {
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 10,
"w": 12,
"x": 0,
"y": 14
},
"id": 4,
"options": {
"displayMode": "gradient",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"showUnfilled": true
},
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "Substrate_to_Ethereum_Sync_blocks_in_state",
"instant": true,
"interval": "",
"legendFormat": "{{state}}",
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Queued Headers in Relay",
"type": "bargauge"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"description": "",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 16
},
"hiddenSeries": false,
"id": 10,
"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": "Substrate_to_Ethereum_Sync_process_memory_usage_bytes / 1024 / 1024",
"interval": "",
"legendFormat": "Process memory, MB",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Memory Usage for Relay Process",
"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
}
}
],
"refresh": "5s",
"schemaVersion": 26,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-5m",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
]
},
"timezone": "",
"title": "Rialto to Ethereum PoA Header Sync Dashboard",
"uid": "relay-rialto-to-poa-headers",
"version": 1
}
@@ -1,4 +0,0 @@
- targets:
- relay-headers-poa-to-rialto:9616
- relay-poa-exchange-rialto:9616
- relay-headers-rialto-to-poa:9616
@@ -1,94 +0,0 @@
# This Compose file should be built using the Rialto and Eth-PoA node
# compose files. Otherwise it won't work.
#
# Exposed ports: 9616, 9716, 9816, 9916, 8080
version: '3.5'
services:
# We override these nodes to make sure we have the correct chain config for this network.
poa-node-arthur: &poa-node
volumes:
- ./bridges/poa-rialto/poa-config:/config
poa-node-bertha:
<<: *poa-node
poa-node-carlos:
<<: *poa-node
# We provide an override for this particular node since this is a public facing
# node which we use to connect from things like Polkadot JS Apps.
rialto-node-charlie:
environment:
VIRTUAL_HOST: rialto.bridges.test-installations.parity.io,wss.rialto.brucke.link
VIRTUAL_PORT: 9944
LETSENCRYPT_HOST: rialto.bridges.test-installations.parity.io,wss.rialto.brucke.link
LETSENCRYPT_EMAIL: admin@parity.io
relay-headers-poa-to-rialto: &eth-poa-relay
image: paritytech/ethereum-poa-relay
entrypoint: /entrypoints/relay-headers-poa-to-rialto-entrypoint.sh
volumes:
- ./bridges/poa-rialto/entrypoints:/entrypoints
environment:
RUST_LOG: rpc=trace,bridge=trace
ports:
- "9616:9616"
depends_on: &all-nodes
- poa-node-arthur
- poa-node-bertha
- poa-node-carlos
- rialto-node-alice
- rialto-node-bob
- rialto-node-charlie
- rialto-node-dave
- rialto-node-eve
relay-poa-exchange-rialto:
<<: *eth-poa-relay
entrypoint: /entrypoints/relay-poa-exchange-rialto-entrypoint.sh
ports:
- "9716:9616"
relay-headers-rialto-to-poa:
<<: *eth-poa-relay
entrypoint: /entrypoints/relay-headers-rialto-to-poa-entrypoint.sh
ports:
- "9816:9616"
poa-exchange-tx-generator:
<<: *eth-poa-relay
entrypoint: /entrypoints/poa-exchange-tx-generator-entrypoint.sh
environment:
EXCHANGE_GEN_MIN_AMOUNT_FINNEY: ${EXCHANGE_GEN_MIN_AMOUNT_FINNEY:-1}
EXCHANGE_GEN_MAX_AMOUNT_FINNEY: ${EXCHANGE_GEN_MAX_AMOUNT_FINNEY:-100000}
EXCHANGE_GEN_MAX_SUBMIT_DELAY_S: ${EXCHANGE_GEN_MAX_SUBMIT_DELAY_S:-60}
ports:
- "9916:9616"
depends_on:
- relay-headers-poa-to-rialto
- relay-headers-rialto-to-poa
front-end:
build:
context: .
dockerfile: ./bridges/poa-rialto/Front-end.Dockerfile
args:
SUBSTRATE_PROVIDER: ${UI_SUBSTRATE_PROVIDER:-ws://localhost:9944}
ETHEREUM_PROVIDER: ${UI_ETHEREUM_PROVIDER:-http://localhost:8545}
EXPECTED_ETHEREUM_NETWORK_ID: ${UI_EXPECTED_ETHEREUM_NETWORK_ID:-105}
ports:
- "8080:80"
# Note: These are being overridden from the top level `monitoring` compose file.
prometheus-metrics:
volumes:
- ./bridges/poa-rialto/dashboard/prometheus/targets.yml:/etc/prometheus/targets-poa-rialto.yml
depends_on: *all-nodes
grafana-dashboard:
volumes:
- ./bridges/poa-rialto/dashboard/grafana:/etc/grafana/dashboards/poa-rialto:ro
environment:
VIRTUAL_HOST: dashboard.rialto.bridges.test-installations.parity.io,grafana.rialto.brucke.link
VIRTUAL_PORT: 3000
LETSENCRYPT_HOST: dashboard.rialto.bridges.test-installations.parity.io,grafana.rialto.brucke.link
LETSENCRYPT_EMAIL: admin@parity.io
@@ -1,99 +0,0 @@
#!/bin/bash
# THIS SCRIPT IS NOT INTENDED FOR USE IN PRODUCTION ENVIRONMENT
#
# This scripts periodically calls relay binary to generate PoA -> Substrate
# exchange transaction from hardcoded PoA senders (assuming they have
# enough funds) to hardcoded Substrate recipients.
set -eu
# Path to relay binary
RELAY_BINARY_PATH=${RELAY_BINARY_PATH:-./ethereum-poa-relay}
# Ethereum node host
ETH_HOST=${ETH_HOST:-poa-node-arthur}
# Ethereum node websocket port
ETH_PORT=${ETH_PORT:-8546}
# Ethereum chain id
ETH_CHAIN_ID=${ETH_CHAIN_ID:-105}
# All possible Substrate recipients (hex-encoded public keys)
SUB_RECIPIENTS=(
# Alice (5GrwvaEF...)
"d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"\
# Bob (5FHneW46...)
"8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48"\
# Charlie (5FLSigC9...)
"90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22"\
# Dave (5DAAnrj7...)
"306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20"\
# Eve (5HGjWAeF...)
"e659a7a1628cdd93febc04a4e0646ea20e9f5f0ce097d9a05290d4a9e054df4e"\
# Ferdie (5CiPPseX...)
"1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c"
)
# All possible Ethereum signers (hex-encoded private keys)
# (note that we're tracking nonce here => sender must not send concurrent transactions)
ETH_SIGNERS=(
# Bertha account (0x007594304039c2937a12220338aab821d819f5a4) and its current nonce (unknown by default)
"bc10e0f21e33456ade82182dd1ebdbdd89bca923d4e4adbd90fb5b44d7098cbe" ""
)
# Minimal exchange amount (in finney)
MIN_EXCHANGE_AMOUNT_FINNEY=${EXCHANGE_GEN_MIN_AMOUNT_FINNEY:-1} # 0.1 ETH
# Maximal exchange amount (in finney)
MAX_EXCHANGE_AMOUNT_FINNEY=${EXCHANGE_GEN_MAX_AMOUNT_FINNEY:-100000} # 100 ETH
# Max delay before submitting transactions (s)
MAX_SUBMIT_DELAY_S=${EXCHANGE_GEN_MAX_SUBMIT_DELAY_S:-60}
while true
do
# sleep some time
SUBMIT_DELAY_S=`shuf -i 0-$MAX_SUBMIT_DELAY_S -n 1`
echo "Sleeping $SUBMIT_DELAY_S seconds..."
sleep $SUBMIT_DELAY_S
# select recipient
SUB_RECIPIENTS_MAX_INDEX=$((${#SUB_RECIPIENTS[@]} - 1))
SUB_RECIPIENT_INDEX=`shuf -i 0-$SUB_RECIPIENTS_MAX_INDEX -n 1`
SUB_RECIPIENT=${SUB_RECIPIENTS[$SUB_RECIPIENT_INDEX]}
# select signer
ETH_SIGNERS_MAX_INDEX=$(((${#ETH_SIGNERS[@]} - 1) / 2))
ETH_SIGNERS_INDEX=`shuf -i 0-$ETH_SIGNERS_MAX_INDEX -n 1`
ETH_SIGNER_INDEX=$(($ETH_SIGNERS_INDEX * 2))
ETH_SIGNER_NONCE_INDEX=$(($ETH_SIGNER_INDEX + 1))
ETH_SIGNER=${ETH_SIGNERS[$ETH_SIGNER_INDEX]}
ETH_SIGNER_NONCE=${ETH_SIGNERS[$ETH_SIGNER_NONCE_INDEX]}
if [ -z $ETH_SIGNER_NONCE ]; then
ETH_SIGNER_NONCE_ARG=
else
ETH_SIGNER_NONCE_ARG=`printf -- "--eth-nonce=%s" $ETH_SIGNER_NONCE`
fi
# select amount
EXCHANGE_AMOUNT_FINNEY=`shuf -i $MIN_EXCHANGE_AMOUNT_FINNEY-$MAX_EXCHANGE_AMOUNT_FINNEY -n 1`
EXCHANGE_AMOUNT_ETH=`printf "%s000" $EXCHANGE_AMOUNT_FINNEY`
# submit transaction
echo "Sending $EXCHANGE_AMOUNT_ETH from PoA:$ETH_SIGNER to Substrate:$SUB_RECIPIENT. Nonce: $ETH_SIGNER_NONCE"
set -x
SUBMIT_OUTPUT=`$RELAY_BINARY_PATH 2>&1 eth-submit-exchange-tx \
--sub-recipient=$SUB_RECIPIENT \
--eth-host=$ETH_HOST \
--eth-port=$ETH_PORT \
--eth-chain-id=$ETH_CHAIN_ID \
--eth-signer=$ETH_SIGNER \
--eth-amount=$EXCHANGE_AMOUNT_ETH \
$ETH_SIGNER_NONCE_ARG`
set +x
# update sender nonce
SUBMIT_OUTPUT_RE='nonce: ([0-9]+)'
if [[ $SUBMIT_OUTPUT =~ $SUBMIT_OUTPUT_RE ]]; then
ETH_SIGNER_NONCE=${BASH_REMATCH[1]}
ETH_SIGNERS[$ETH_SIGNER_NONCE_INDEX]=$(($ETH_SIGNER_NONCE + 1))
else
echo "Missing nonce in relay response: $SUBMIT_OUTPUT"
exit 1
fi
done
@@ -1,15 +0,0 @@
#!/bin/bash
set -xeu
sleep 20
curl -v http://poa-node-arthur:8545/api/health
curl -v http://poa-node-bertha:8545/api/health
curl -v http://poa-node-carlos:8545/api/health
curl -v http://rialto-node-alice:9933/health
curl -v http://rialto-node-bob:9933/health
curl -v http://rialto-node-charlie:9933/health
/home/user/ethereum-poa-relay eth-to-sub \
--sub-host rialto-node-alice \
--eth-host poa-node-arthur \
--prometheus-host=0.0.0.0
@@ -1,26 +0,0 @@
#!/bin/bash
set -xeu
sleep 20
curl -v http://rialto-node-bob:9933/health
curl -v http://poa-node-bertha:8545/api/health
# Try to deploy contracts first
# networkID = 0x69
# Arthur's key.
/home/user/ethereum-poa-relay eth-deploy-contract \
--eth-chain-id 105 \
--eth-signer 0399dbd15cf6ee8250895a1f3873eb1e10e23ca18e8ed0726c63c4aea356e87d \
--sub-host rialto-node-bob \
--eth-host poa-node-bertha || echo "Failed to deploy contracts."
sleep 10
echo "Starting SUB -> ETH relay"
/home/user/ethereum-poa-relay sub-to-eth \
--eth-contract c9a61fb29e971d1dabfd98657969882ef5d0beee \
--eth-chain-id 105 \
--eth-signer 0399dbd15cf6ee8250895a1f3873eb1e10e23ca18e8ed0726c63c4aea356e87d \
--sub-host rialto-node-bob \
--eth-host poa-node-bertha \
--prometheus-host=0.0.0.0
@@ -1,16 +0,0 @@
#!/bin/bash
set -xeu
sleep 20
curl -v http://poa-node-arthur:8545/api/health
curl -v http://poa-node-bertha:8545/api/health
curl -v http://poa-node-carlos:8545/api/health
curl -v http://rialto-node-alice:9933/health
curl -v http://rialto-node-bob:9933/health
curl -v http://rialto-node-charlie:9933/health
/home/user/ethereum-poa-relay eth-exchange-sub \
--sub-host rialto-node-alice \
--sub-signer //Bob \
--eth-host poa-node-arthur \
--prometheus-host=0.0.0.0
@@ -1 +0,0 @@
{"id":"dd04f316-bc9d-2deb-4a34-51014cd5f34f","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"aa91e6f0e6cf48208be4a1bcf15c6f30"},"ciphertext":"6e057599b13a87e8181bb39a40e14848fdc97958d493ddfa6bb1260350f69328","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"79dd8c09c5c066b830179a2558a51efca6d97c0db2c4128090a01835786823c5"},"mac":"8f8b8e2c9de29ec8eefc54a60055e30ae7ff4dd4a367eaf38880edb887da771e"},"address":"005e714f896a8b7cede9d38688c1a81de72a58e4","name":"","meta":"{}"}
@@ -1 +0,0 @@
{"id":"6d1e690f-0b52-35f7-989b-46100e7c65ed","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"a5b4d0466834e75c9fd29c6cbbac57ad"},"ciphertext":"102ac328cbe66d8cb8515c42e3268776a9be4419a5cb7b79852860b1e691c15b","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"e8daf2e70086b0cacf925d368fd3f60cada1285e39a42c4cc73c135368cfdbef"},"mac":"1bc3b750900a1143c64ba9e677d69e1093aab47cb003ba09f3cd595a3b422db5"},"address":"007594304039c2937a12220338aab821d819f5a4","name":"","meta":"{}"}
@@ -1 +0,0 @@
{"id":"ffaebba1-f1b9-8758-7034-0314040b1396","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"97f124bc8a7bf55d00eb2755c2b50364"},"ciphertext":"b87827816f33d2bef2dc3102a8a7744b86912f8ace10e45cb282a13487769ed2","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"3114c67a05bff7831d112083f566b176bfc874aea160eebadbe5564e406ee85c"},"mac":"e9bfe8fd6f612bc036bb57659297fc03db022264f5086a1b5726972d3ab6f64a"},"address":"004e7a39907f090e19b0b80a277e77b72b22e269","name":"","meta":"{}"}
@@ -1 +0,0 @@
{"id":"ef9eb431-dc73-cf31-357e-736f64febe68","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"7077f1c4170d9fc2e05c5956be32fb51"},"ciphertext":"a053be448768d984257aeb8f9c7913e3f54c6e6e741accad9f09dd70c2d9828c","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"12580aa4624040970301e7474d3f9b2a93552bfe9ea2517f7119ccf8e91ebd0d"},"mac":"796dbb48adcfc09041fe39121632801d9f950d3c73dd47105180d8097d4f4491"},"address":"00eed42bf93b498f28acd21d207427a14074defe","name":"","meta":"{}"}
@@ -1 +0,0 @@
password
@@ -1,20 +0,0 @@
[parity]
chain = "/config/poa.json"
keys_path = "/config/keys"
no_persistent_txqueue = true
[account]
password = ["/config/pass"]
[network]
reserved_peers = "/config/reserved"
[rpc]
apis = ["all"]
cors = ["moz-extension://*", "chrome-extension://*"]
[mining]
force_sealing = true
[misc]
unsafe_expose = true
@@ -1,184 +0,0 @@
{
"name": "BridgePoa",
"engine": {
"authorityRound": {
"params": {
"stepDuration": 10,
"validators": {
"list": [
"0x005e714f896a8b7cede9d38688c1a81de72a58e4",
"0x007594304039c2937a12220338aab821d819f5a4",
"0x004e7a39907f090e19b0b80a277e77b72b22e269"
]
},
"validateScoreTransition": 0,
"validateStepTransition": 0,
"maximumUncleCountTransition": 0,
"maximumUncleCount": 0,
"emptyStepsTransition": "0xfffffffff",
"maximumEmptySteps": 1
}
}
},
"params": {
"accountStartNonce": "0x0",
"eip1014Transition": "0x0",
"eip1052Transition": "0x0",
"eip140Transition": "0x0",
"eip145Transition": "0x0",
"eip150Transition": "0x0",
"eip155Transition": "0x0",
"eip160Transition": "0x0",
"eip161abcTransition": "0x0",
"eip161dTransition": "0x0",
"eip211Transition": "0x0",
"eip214Transition": "0x0",
"eip658Transition": "0x0",
"eip98Transition": "0x7fffffffffffff",
"gasLimitBoundDivisor": "0x0400",
"maxCodeSize": 24576,
"maxCodeSizeTransition": "0x0",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x69",
"validateChainIdTransition": "0x0",
"validateReceiptsTransition": "0x0"
},
"genesis": {
"seal": {
"authorityRound": {
"step": "0x0",
"signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x20000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x222222"
},
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } },
"0000000000000000000000000000000000000006": {
"balance": "1",
"builtin": {
"name": "alt_bn128_add",
"pricing": {
"0": {
"price": { "alt_bn128_const_operations": { "price": 500 }}
},
"0x7fffffffffffff": {
"info": "EIP 1108 transition",
"price": { "alt_bn128_const_operations": { "price": 150 }}
}
}
}
},
"0000000000000000000000000000000000000007": {
"balance": "1",
"builtin": {
"name": "alt_bn128_mul",
"pricing": {
"0": {
"price": { "alt_bn128_const_operations": { "price": 40000 }}
},
"0x7fffffffffffff": {
"info": "EIP 1108 transition",
"price": { "alt_bn128_const_operations": { "price": 6000 }}
}
}
}
},
"0000000000000000000000000000000000000008": {
"balance": "1",
"builtin": {
"name": "alt_bn128_pairing",
"pricing": {
"0": {
"price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }}
},
"0x7fffffffffffff": {
"info": "EIP 1108 transition",
"price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }}
}
}
}
},
"0x0000000000000000000000000000000000000009": {
"builtin": {
"name": "blake2_f",
"activate_at": "0xd751a5",
"pricing": {
"blake2_f": {
"gas_per_round": 1
}
}
}
},
"0x0000000000000000000000000000000000000010": {
"builtin": {
"name": "parse_substrate_header",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000011": {
"builtin": {
"name": "get_substrate_header_signal",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000012": {
"builtin": {
"name": "verify_substrate_finality_proof",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000013": {
"builtin": {
"name": "my_test",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x005e714f896a8b7cede9d38688c1a81de72a58e4": {
"balance": "1606938044258990275541962092341162602522202993782792835301376",
"nonce": "0x1"
},
"0x007594304039c2937a12220338aab821d819f5a4": {
"balance": "1606938044258990275541962092341162602522202993782792835301376",
"nonce": "0x1"
},
"0x004e7a39907f090e19b0b80a277e77b72b22e269": {
"balance": "1606938044258990275541962092341162602522202993782792835301376",
"nonce": "0x1"
},
"0x00eed42bf93b498f28acd21d207427a14074defe": {
"balance": "1606938044258990275541962092341162602522202993782792835301376",
"nonce": "0x1"
}
}
}
@@ -1,3 +0,0 @@
enode://543d0874df46dff238d62547160f9d11e3d21897d7041bbbe46a04d2ee56d9eaf108f2133c0403159624f7647198e224d0755d23ad0e1a50c0912973af6e8a8a@poa-node-arthur:30303
enode://710de70733e88a24032e53054985f7239e37351f5f3335a468a1a78a3026e9f090356973b00262c346a6608403df2c7107fc4def2cfe4995ea18a41292b9384f@poa-node-bertha:30303
enode://943525f415b9482f1c49bd39eb979e4e2b406f4137450b0553bffa5cba2928e25ff89ef70f7325aad8a75dbb5955eaecc1aee7ac55d66bcaaa07c8ea58adb23a@poa-node-carlos:30303
@@ -471,7 +471,7 @@
}
],
"executionErrorState": "alerting",
"for": "5m",
"for": "7m",
"frequency": "1m",
"handler": 1,
"name": "Messages from Millau to Rialto are not being delivered",
@@ -896,7 +896,7 @@
}
],
"executionErrorState": "alerting",
"for": "5m",
"for": "7m",
"frequency": "1m",
"handler": 1,
"name": "Messages (00000001) from Millau to Rialto are not being delivered",
@@ -967,8 +967,7 @@
"fill": true,
"line": true,
"op": "lt",
"value": 1,
"yaxis": "left"
"value": 1
}
],
"timeFrom": null,
@@ -1155,6 +1154,249 @@
"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",
"fieldConfig": {
@@ -1181,7 +1423,7 @@
"h": 8,
"w": 8,
"x": 0,
"y": 38
"y": 49
},
"id": 16,
"options": {
@@ -1199,7 +1441,7 @@
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "avg_over_time(Millau_to_Rialto_MessageLane_00000000_process_cpu_usage_percentage[1m])",
"expr": "avg_over_time(process_cpu_usage_percentage{instance='relay-millau-rialto:9616'}[1m])",
"instant": true,
"interval": "",
"legendFormat": "1 CPU = 100",
@@ -1230,7 +1472,7 @@
"h": 8,
"w": 8,
"x": 8,
"y": 38
"y": 49
},
"hiddenSeries": false,
"id": 18,
@@ -1257,7 +1499,7 @@
"steppedLine": false,
"targets": [
{
"expr": "Millau_to_Rialto_MessageLane_00000000_system_average_load",
"expr": "system_average_load{instance='relay-millau-rialto:9616'}",
"interval": "",
"legendFormat": "Average system load in last {{over}}",
"refId": "A"
@@ -1323,7 +1565,7 @@
"h": 8,
"w": 8,
"x": 16,
"y": 38
"y": 49
},
"hiddenSeries": false,
"id": 20,
@@ -1350,7 +1592,7 @@
"steppedLine": false,
"targets": [
{
"expr": "Millau_to_Rialto_MessageLane_00000000_process_memory_usage_bytes / 1024 / 1024",
"expr": "process_memory_usage_bytes{instance='relay-millau-rialto:9616'} / 1024 / 1024",
"interval": "",
"legendFormat": "Process memory, MB",
"refId": "A"
@@ -462,7 +462,7 @@
}
],
"executionErrorState": "alerting",
"for": "5m",
"for": "7m",
"frequency": "1m",
"handler": 1,
"name": "Messages from Rialto to Millau are not being delivered",
@@ -887,7 +887,7 @@
}
],
"executionErrorState": "alerting",
"for": "5m",
"for": "7m",
"frequency": "1m",
"handler": 1,
"name": "Messages (00000001) from Rialto to Millau are not being delivered",
@@ -1190,7 +1190,7 @@
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "avg_over_time(Rialto_to_Millau_MessageLane_00000000_process_cpu_usage_percentage[1m])",
"expr": "avg_over_time(process_cpu_usage_percentage{instance='relay-millau-rialto:9616'}[1m])",
"instant": true,
"interval": "",
"legendFormat": "1 CPU = 100",
@@ -1248,7 +1248,7 @@
"steppedLine": false,
"targets": [
{
"expr": "Rialto_to_Millau_MessageLane_00000000_system_average_load",
"expr": "system_average_load{instance='relay-millau-rialto:9616'}",
"interval": "",
"legendFormat": "Average system load in last {{over}}",
"refId": "A"
@@ -1341,7 +1341,7 @@
"steppedLine": false,
"targets": [
{
"expr": "Rialto_to_Millau_MessageLane_00000000_process_memory_usage_bytes / 1024 / 1024",
"expr": "process_memory_usage_bytes{instance='relay-millau-rialto:9616'} / 1024 / 1024",
"interval": "",
"legendFormat": "Process memory, MB",
"refId": "A"
@@ -65,7 +65,7 @@
"targets": [
{
"exemplar": true,
"expr": "Rialto_to_Millau_MessageLane_00000000_rialto_storage_proof_overhead",
"expr": "rialto_storage_proof_overhead{instance='relay-millau-rialto:9616'}",
"interval": "",
"legendFormat": "Actual overhead",
"refId": "A"
@@ -169,14 +169,14 @@
"targets": [
{
"exemplar": true,
"expr": "Westend_to_Millau_Sync_kusama_to_base_conversion_rate / Westend_to_Millau_Sync_polkadot_to_base_conversion_rate",
"expr": "kusama_to_base_conversion_rate{instance='relay-millau-rialto:9616'} / polkadot_to_base_conversion_rate{instance='relay-millau-rialto:9616'}",
"interval": "",
"legendFormat": "Outside of runtime (actually Polkadot -> Kusama)",
"refId": "A"
},
{
"exemplar": true,
"expr": "Rialto_to_Millau_MessageLane_00000000_rialto_millau_to_rialto_conversion_rate",
"expr": "Millau_Rialto_to_Millau_conversion_rate{instance='relay-millau-rialto:9616'}",
"hide": false,
"interval": "",
"legendFormat": "At runtime",
@@ -187,7 +187,7 @@
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Rialto: Millau -> Rialto conversion rate",
"title": "Millau: Rialto -> Millau conversion rate",
"tooltip": {
"shared": true,
"sort": 0,
@@ -273,7 +273,7 @@
"targets": [
{
"exemplar": true,
"expr": "Millau_to_Rialto_MessageLane_00000000_millau_storage_proof_overhead",
"expr": "millau_storage_proof_overhead{instance='relay-millau-rialto:9616'}",
"interval": "",
"legendFormat": "Actual overhead",
"refId": "A"
@@ -377,14 +377,14 @@
"targets": [
{
"exemplar": true,
"expr": "Westend_to_Millau_Sync_polkadot_to_base_conversion_rate / Westend_to_Millau_Sync_kusama_to_base_conversion_rate",
"expr": "polkadot_to_base_conversion_rate{instance='relay-millau-rialto:9616'} / kusama_to_base_conversion_rate{instance='relay-millau-rialto:9616'}",
"interval": "",
"legendFormat": "Outside of runtime (actually Kusama -> Polkadot)",
"refId": "A"
},
{
"exemplar": true,
"expr": "Millau_to_Rialto_MessageLane_00000000_millau_rialto_to_millau_conversion_rate",
"expr": "Rialto_Millau_to_Rialto_conversion_rate{instance='relay-millau-rialto:9616'}",
"hide": false,
"interval": "",
"legendFormat": "At runtime",
@@ -395,7 +395,7 @@
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Millau: Rialto -> Millau conversion rate",
"title": "Rialto: Millau -> Rialto conversion rate",
"tooltip": {
"shared": true,
"sort": 0,
@@ -1,4 +1,4 @@
# Exposed ports: 10016, 10116, 10216, 10316, 10416
# Exposed ports: 10016, 10116, 10216, 10316, 10416, 10516, 10716
version: '3.5'
services:
@@ -52,6 +52,7 @@ services:
relay-messages-millau-to-rialto-generator:
<<: *sub-bridge-relay
environment:
RUST_LOG: bridge=trace
MSG_EXCHANGE_GEN_SECONDARY_LANE: "00000001"
entrypoint: /entrypoints/relay-messages-to-rialto-generator-entrypoint.sh
ports:
@@ -59,13 +60,24 @@ services:
depends_on:
- 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:
<<: *sub-bridge-relay
environment:
RUST_LOG: bridge=trace
MSG_EXCHANGE_GEN_LANE: "00000001"
entrypoint: /entrypoints/relay-messages-rialto-to-millau-entrypoint.sh
ports:
- "10316:9616"
- "10416:9616"
depends_on:
- relay-millau-rialto
@@ -75,7 +87,15 @@ services:
MSG_EXCHANGE_GEN_SECONDARY_LANE: "00000001"
entrypoint: /entrypoints/relay-messages-to-millau-generator-entrypoint.sh
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:
- relay-millau-rialto
@@ -1,13 +1,13 @@
#!/bin/bash
set -xeu
sleep 20
sleep 60
curl -v http://millau-node-bob:9933/health
curl -v http://rialto-node-bob:9933/health
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 \
--source-host millau-node-bob \
--source-port 9944 \
@@ -1,13 +1,13 @@
#!/bin/bash
set -xeu
sleep 20
sleep 60
curl -v http://millau-node-bob:9933/health
curl -v http://rialto-node-bob:9933/health
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 \
--source-host rialto-node-bob \
--source-port 9944 \
@@ -14,7 +14,7 @@ SECONDARY_MESSAGE_LANE=${MSG_EXCHANGE_GEN_SECONDARY_LANE}
MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE=1024
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"
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`
echo "Sleeping $SUBMIT_DELAY_S seconds..."
sleep $SUBMIT_DELAY_S
NOW=`date "+%Y-%m-%d %H:%M:%S"`
echo "Woke up at $NOW"
}
# start sending large messages immediately
@@ -32,6 +34,10 @@ LARGE_MESSAGES_TIME=0
# start sending message packs in a hour
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
do
rand_sleep
@@ -46,6 +52,7 @@ do
$SEND_MESSAGE \
--lane $SECONDARY_MESSAGE_LANE \
--origin Target \
--dispatch-fee-payment at-target-chain \
remark
fi
@@ -14,7 +14,7 @@ SECONDARY_MESSAGE_LANE=${MSG_EXCHANGE_GEN_SECONDARY_LANE}
MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE=128
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"
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`
echo "Sleeping $SUBMIT_DELAY_S seconds..."
sleep $SUBMIT_DELAY_S
NOW=`date "+%Y-%m-%d %H:%M:%S"`
echo "Woke up at $NOW"
}
# start sending large messages immediately
@@ -32,6 +34,10 @@ LARGE_MESSAGES_TIME=0
# start sending message packs in a hour
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
do
rand_sleep
@@ -46,6 +52,7 @@ do
$SEND_MESSAGE \
--lane $SECONDARY_MESSAGE_LANE \
--origin Target \
--dispatch-fee-payment at-target-chain \
remark
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
set -xeu
sleep 20
sleep 60
curl -v http://millau-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-port 9944 \
--target-host rialto-node-alice \
--target-port 9944 \
--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-port 9944 \
--target-host millau-node-alice \
@@ -26,8 +26,11 @@ sleep 6
--millau-host millau-node-alice \
--millau-port 9944 \
--millau-signer //Charlie \
--millau-messages-pallet-owner=//RialtoMessagesOwner \
--rialto-host rialto-node-alice \
--rialto-port 9944 \
--rialto-signer //Charlie \
--rialto-messages-pallet-owner=//MillauMessagesOwner \
--lane=00000000 \
--lane=73776170 \
--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": {
"params": [
5
32
],
"type": "gt"
},
@@ -46,11 +46,11 @@
}
],
"executionErrorState": "alerting",
"for": "5m",
"for": "60m",
"frequency": "5m",
"handler": 1,
"message": "",
"name": "Synced Header Difference is Over 5 (Westend to Millau)",
"name": "Synced Header Difference is Over 32 (Westend to Millau)",
"noDataState": "no_data",
"notifications": []
},
@@ -163,7 +163,7 @@
{
"evaluator": {
"params": [
5
32
],
"type": "lt"
},
@@ -185,7 +185,7 @@
}
],
"executionErrorState": "alerting",
"for": "3m",
"for": "60m",
"frequency": "5m",
"handler": 1,
"name": "No New Headers (Westend to Millau)",
@@ -237,9 +237,9 @@
"steppedLine": false,
"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": "",
"legendFormat": "Number of new Headers on Westend (Last 2 Mins)",
"legendFormat": "Number of new Headers on Westend (Last 10 Mins)",
"refId": "A"
}
],
@@ -401,7 +401,7 @@
"steppedLine": false,
"targets": [
{
"expr": "Westend_to_Millau_Sync_system_average_load",
"expr": "system_average_load{instance='relay-headers-westend-to-millau:9616'}",
"interval": "",
"legendFormat": "Average system load in last {{over}}",
"refId": "A"
@@ -500,7 +500,7 @@
"pluginVersion": "7.1.3",
"targets": [
{
"expr": "avg_over_time(Westend_to_Millau_Sync_process_cpu_usage_percentage[1m])",
"expr": "avg_over_time(process_cpu_usage_percentage{instance='relay-headers-westend-to-millau:9616'}[1m])",
"instant": true,
"interval": "",
"legendFormat": "1 CPU = 100",
@@ -615,7 +615,7 @@
"steppedLine": false,
"targets": [
{
"expr": "Westend_to_Millau_Sync_process_memory_usage_bytes / 1024 / 1024",
"expr": "process_memory_usage_bytes{instance='relay-headers-westend-to-millau:9616'} / 1024 / 1024",
"interval": "",
"legendFormat": "Process memory, MB",
"refId": "A"
@@ -1,11 +1,11 @@
#!/bin/bash
set -xeu
sleep 20
sleep 60
curl -v http://millau-node-alice:9933/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-port 443 \
--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
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-port 443 \
--source-secure \
--target-host millau-node-alice \
--target-port 9944 \
--target-signer //George \
--target-transactions-mortality=4\
--prometheus-host=0.0.0.0
@@ -1 +0,0 @@
{"id":"dd04f316-bc9d-2deb-4a34-51014cd5f34f","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"aa91e6f0e6cf48208be4a1bcf15c6f30"},"ciphertext":"6e057599b13a87e8181bb39a40e14848fdc97958d493ddfa6bb1260350f69328","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"79dd8c09c5c066b830179a2558a51efca6d97c0db2c4128090a01835786823c5"},"mac":"8f8b8e2c9de29ec8eefc54a60055e30ae7ff4dd4a367eaf38880edb887da771e"},"address":"005e714f896a8b7cede9d38688c1a81de72a58e4","name":"","meta":"{}"}
@@ -1 +0,0 @@
password
@@ -1,17 +0,0 @@
[parity]
chain = "./deployments/dev/poa-config/poa.json"
keys_path = "./deployments/dev/poa-config/keys"
no_persistent_txqueue = true
[account]
password = ["./deployments/dev/poa-config/pass"]
[rpc]
apis = ["all"]
cors = ["moz-extension://*", "chrome-extension://*"]
[mining]
force_sealing = true
[misc]
unsafe_expose = true
@@ -1,178 +0,0 @@
{
"name": "BridgePoa",
"engine": {
"authorityRound": {
"params": {
"stepDuration": 10,
"validators": {
"list": [
"0x005e714f896a8b7cede9d38688c1a81de72a58e4"
]
},
"validateScoreTransition": 0,
"validateStepTransition": 0,
"maximumUncleCountTransition": 0,
"maximumUncleCount": 0,
"emptyStepsTransition": "0xfffffffff",
"maximumEmptySteps": 1
}
}
},
"params": {
"accountStartNonce": "0x0",
"eip1014Transition": "0x0",
"eip1052Transition": "0x0",
"eip140Transition": "0x0",
"eip145Transition": "0x0",
"eip150Transition": "0x0",
"eip155Transition": "0x0",
"eip160Transition": "0x0",
"eip161abcTransition": "0x0",
"eip161dTransition": "0x0",
"eip211Transition": "0x0",
"eip214Transition": "0x0",
"eip658Transition": "0x0",
"eip98Transition": "0x7fffffffffffff",
"gasLimitBoundDivisor": "0x0400",
"maxCodeSize": 24576,
"maxCodeSizeTransition": "0x0",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x69",
"validateChainIdTransition": "0x0",
"validateReceiptsTransition": "0x0"
},
"genesis": {
"seal": {
"authorityRound": {
"step": "0x0",
"signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x20000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x222222"
},
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } },
"0000000000000000000000000000000000000006": {
"balance": "1",
"builtin": {
"name": "alt_bn128_add",
"pricing": {
"0": {
"price": { "alt_bn128_const_operations": { "price": 500 }}
},
"0x7fffffffffffff": {
"info": "EIP 1108 transition",
"price": { "alt_bn128_const_operations": { "price": 150 }}
}
}
}
},
"0000000000000000000000000000000000000007": {
"balance": "1",
"builtin": {
"name": "alt_bn128_mul",
"pricing": {
"0": {
"price": { "alt_bn128_const_operations": { "price": 40000 }}
},
"0x7fffffffffffff": {
"info": "EIP 1108 transition",
"price": { "alt_bn128_const_operations": { "price": 6000 }}
}
}
}
},
"0000000000000000000000000000000000000008": {
"balance": "1",
"builtin": {
"name": "alt_bn128_pairing",
"pricing": {
"0": {
"price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }}
},
"0x7fffffffffffff": {
"info": "EIP 1108 transition",
"price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }}
}
}
}
},
"0x0000000000000000000000000000000000000009": {
"builtin": {
"name": "blake2_f",
"activate_at": "0xd751a5",
"pricing": {
"blake2_f": {
"gas_per_round": 1
}
}
}
},
"0x0000000000000000000000000000000000000010": {
"builtin": {
"name": "parse_substrate_header",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000011": {
"builtin": {
"name": "get_substrate_header_signal",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000012": {
"builtin": {
"name": "verify_substrate_finality_proof",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000013": {
"builtin": {
"name": "my_test",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x005e714f896a8b7cede9d38688c1a81de72a58e4": {
"balance": "1606938044258990275541962092341162602522202993782792835301376",
"nonce": "0x1"
},
"0x007594304039c2937a12220338aab821d819f5a4": {
"balance": "1606938044258990275541962092341162602522202993782792835301376",
"nonce": "0x1"
},
"0x004e7a39907f090e19b0b80a277e77b72b22e269": {
"balance": "1606938044258990275541962092341162602522202993782792835301376",
"nonce": "0x1"
}
}
}
@@ -8,14 +8,14 @@
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-port 9955 \
--target-host 127.0.0.1 \
--target-port 9944 \
--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-port 9955 \
--target-host 127.0.0.1 \
@@ -8,14 +8,14 @@
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-port 9944 \
--target-host 127.0.0.1 \
--target-port 9955 \
--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-port 9944 \
--target-host 127.0.0.1 \
@@ -9,7 +9,7 @@ MILLAU_PORT="${MILLAU_PORT:-9945}"
RIALTO_PORT="${RIALTO_PORT:-9944}"
RUST_LOG=bridge=debug \
./target/debug/substrate-relay relay-messages MillauToRialto \
./target/debug/substrate-relay relay-messages millau-to-rialto \
--lane 00000000 \
--source-host localhost \
--source-port $MILLAU_PORT \
@@ -9,7 +9,7 @@ MILLAU_PORT="${MILLAU_PORT:-9945}"
RIALTO_PORT="${RIALTO_PORT:-9944}"
RUST_LOG=bridge=debug \
./target/debug/substrate-relay relay-messages RialtoToMillau \
./target/debug/substrate-relay relay-messages rialto-to-millau \
--lane 00000000 \
--source-host localhost \
--source-port $RIALTO_PORT \
@@ -9,7 +9,7 @@ MILLAU_PORT="${MILLAU_PORT:-9945}"
RIALTO_PORT="${RIALTO_PORT:-9944}"
RUST_LOG=bridge=debug \
./target/debug/substrate-relay init-bridge MillauToRialto \
./target/debug/substrate-relay init-bridge millau-to-rialto \
--source-host localhost \
--source-port $MILLAU_PORT \
--target-host localhost \
@@ -18,7 +18,7 @@ RUST_LOG=bridge=debug \
sleep 5
RUST_LOG=bridge=debug \
./target/debug/substrate-relay relay-headers MillauToRialto \
./target/debug/substrate-relay relay-headers millau-to-rialto \
--source-host localhost \
--source-port $MILLAU_PORT \
--target-host localhost \
@@ -9,7 +9,7 @@ MILLAU_PORT="${MILLAU_PORT:-9945}"
RIALTO_PORT="${RIALTO_PORT:-9944}"
RUST_LOG=bridge=debug \
./target/debug/substrate-relay init-bridge RialtoToMillau \
./target/debug/substrate-relay init-bridge rialto-to-millau \
--target-host localhost \
--target-port $MILLAU_PORT \
--source-host localhost \
@@ -18,7 +18,7 @@ RUST_LOG=bridge=debug \
sleep 5
RUST_LOG=bridge=debug \
./target/debug/substrate-relay relay-headers RialtoToMillau \
./target/debug/substrate-relay relay-headers rialto-to-millau \
--target-host localhost \
--target-port $MILLAU_PORT \
--source-host localhost \
@@ -1,91 +0,0 @@
FROM docker.io/library/ubuntu:xenial AS builder
# show backtraces
ENV RUST_BACKTRACE 1
ENV LAST_DEPS_UPDATE 2020-06-19
# install tools and dependencies
RUN set -eux; \
apt-get update && \
apt-get install -y file curl jq ca-certificates && \
apt-get install -y cmake pkg-config libssl-dev git clang libclang-dev
ENV LAST_CERTS_UPDATE 2020-06-19
RUN update-ca-certificates && \
curl https://sh.rustup.rs -sSf | sh -s -- -y
ENV PATH="/root/.cargo/bin:${PATH}"
ENV LAST_RUST_UPDATE="2020-09-09"
RUN rustup update stable && \
rustup install nightly && \
rustup target add wasm32-unknown-unknown --toolchain nightly
RUN rustc -vV && \
cargo -V && \
gcc -v && \
g++ -v && \
cmake --version
WORKDIR /openethereum
### Build from the repo
ARG ETHEREUM_REPO=https://github.com/paritytech/openethereum.git
ARG ETHEREUM_HASH=344991dbba2bc8657b00916f0e4b029c66f159e8
RUN git clone $ETHEREUM_REPO /openethereum && git checkout $ETHEREUM_HASH
### Build locally. Make sure to set the CONTEXT to main directory of the repo.
# ADD openethereum /openethereum
WORKDIR /parity-bridges-common
### Build from the repo
# Build using `master` initially.
ARG BRIDGE_REPO=https://github.com/paritytech/parity-bridges-common
RUN git clone $BRIDGE_REPO /parity-bridges-common && git checkout master
WORKDIR /openethereum
RUN cargo build --release --verbose || true
# Then rebuild by switching to a different branch to only incrementally
# build the changes.
WORKDIR /parity-bridges-common
ARG BRIDGE_HASH=master
RUN git checkout . && git fetch && git checkout $BRIDGE_HASH
### Build locally. Make sure to set the CONTEXT to main directory of the repo.
# ADD . /parity-bridges-common
WORKDIR /openethereum
RUN cargo build --release --verbose
RUN strip ./target/release/openethereum
FROM docker.io/library/ubuntu:xenial
# show backtraces
ENV RUST_BACKTRACE 1
RUN set -eux; \
apt-get update && \
apt-get install -y curl
RUN groupadd -g 1000 openethereum \
&& useradd -u 1000 -g openethereum -s /bin/sh -m openethereum
# switch to user openethereum here
USER openethereum
WORKDIR /home/openethereum
COPY --chown=openethereum:openethereum --from=builder /openethereum/target/release/openethereum ./
# Solve issues with custom --keys-path
RUN mkdir -p ~/.local/share/io.parity.ethereum/keys/
# check if executable works in this container
RUN ./openethereum --version
EXPOSE 8545 8546 30303/tcp 30303/udp
HEALTHCHECK --interval=2m --timeout=5s \
CMD curl -f http://localhost:8545/api/health || exit 1
ENTRYPOINT ["/home/openethereum/openethereum"]
@@ -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

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