Squashed 'bridges/' changes from 23dda62482..407bf44a8a

407bf44a8a add missing license header (#1204)
9babb19810  Custom relay strategy (#1198)
c287872a11 fix clippy things (#1200)
3a40e62789 Expose some const value and type (#1186)
32b61476d1 increase sleep before connectingMillau (#1195)
aabe7041fa revert messages transactions mortality (#1194)
3651f4f909 Message transactions mortality (#1191)
364d6e155d Bump dependencies (#1180)
f0389acc08 cargo +nightly fmt --all (#1192)
b270b6a016 Unify error enums in substrate and ethereum clients with `thiserror` (#1094)
58c4946f74 Limit max call size of Rialto/Millau runtimes (#1187)
fd56a8cd56 Add UI to the deployment (#1047)
16f01dc736 Westend -> Millau alerts are pending before notifications are sent (#1184)
5628c11ece replace collective flip with babe randomness in Rialto (#1188)
1094a63b00 ignore another (pretty bad) RUSTSEC (#1185)
379fe323ea fix/ignore cargo deny issues (#1183)
92af5e6e64 additional log in finality relay + rephrase "failed" (#1182)
b996a3b681 Rialto parachain in test deployments (#1178)
28d9332b44 Resubmit transactions strategy for Polkadot/Kusama (#1175)
d0172c6847 Playing with CI (#1179)
fb6f42456d fix checks order when registering parachain (#1177)
ee828c005a Register-parachain subcommand of substrate-relay (#1170)
8cd2b1a112 Token swap pallet benchmarks (#1174)
bb811accb1 fix collision with westend bridge (#1172)
8d2fba70ed add token swaps to test deployments (#1169)
b6d1bdfe2c publish rialto parachain collator image (#1171)
834ae4a10a Fix OutboundLaneData types (#1159)
5ee0ea1626 copypasted -> copied (#1168)
c3bb835f18 fix spelling (#1167)
f90d041dc9 Upgrade `jsonrpsee` to v0.3 (#1051)
598c9b6d0d add some basic tests for swap tokens (#1164)
05e88c61f5 publish images when tag of specific format(e.g. v2021-09-27 + v2021-09-27-1) is published (#1166)
7f3f94a6e0 Fix CI again (#1165)
ff37de332f Move calculation relayer reward into `MessageDeliveryAndDispatchPayment` (#1153)
36fbba839b fix clippy warning (#1163)
16da44d018 explicit wasm build (#1158)
c9c8226449 Match substrate's fmt (#1148)
2fdd7f3e5e Fix/ignore clippy warnings (#1157)
43dfcc2686 Adding LookupAddress (#1156)
951eaa5582 Add rialto-parachain runtime and node (#1142)
803d266d61 Rename MessageId -> BridgeMessageId (#1152)
5f234484fc Box large arguments of GRANDPA pallet (#1154)
cf9abc1011 Fix spelling (#1150)
ab83ba2e58 Relay subcommand that performs token RLT <> MLAU token swap (#1141)
832536caf0 Polkadot <> Kusama relayers (#1122)
6d0daa8975 Add `OnMessageAccepted` callback (#1134)
5d03a20b3e Integrate token swap pallet into Millau runtime (#1099)
ea4cfa833e Adding MultiAddress type and ValidationCodeHash (#1139)
c20325a784 Add tests for `Raw` and `BridgeSendMessage` enum `Call` variants (#1125)
6d802416e2 increase pause before pining Rialto nodes (#1137)
b54fa56b62 calculate fee using full message payload (#1132)
ca5d8178f5 Add parachain pallets to rialto runtime (#1053)
9eaae4142e fix transaction resubmitter limits for Millau -> Rialto transactions (#1135)
9d4e17783c add --mandatory-headers-only cli option to complex relay (#1129)
1c5e0ec1cb Add local CI info to README (#1131)
a8e0929e14 chore: spellchecker fixes (#1130)
3b8e2118e3 set fee for importing mandatory headers to zero (#1127)
49bba9aa52 another bunch of words for spellchecker (#1128)
8a72eafef6 Increase pause before messages generation start (#1126)
1f0ba9a191 Move some associated types from relay_substrate_client::Chain to bp_runtime::Chain (#1087)
74bc1a5b54 Transactions resubmitter (#1083)
21ba001f26 log max balance drop when sending message (#1117)
638a7ddffa Code Cleaning (#1124)
be6555c51b Fix buildah logout (#1120)
87539c4a98 Format code work (#1116)
526fe7fdd7 fix spelling (#1119)
bd4ce7f241 Fix spelling (#1118)
3c1147858e added missing constants to Kusama/Polkadot primitives (#1114)
52093b22ab Fix delivery transaction estimation used by rational relayer (#1109)
77a2f2fbed Remove fund account checks from upgrade. (#1111)
824334802b Rename param and update comment (#1108)
d7784bfe06 Fix spellcheck (#1110)
0b18f5906a Refactor substrate messages source and substrate messages target (#1105)
b27240bbff fix compilation (#1107)
9697da4fe8 Emit mortal transactions from relay (#1073)
b29396c077 Change vault vars type to env vars (#1084)
35e0bbdc0c Make clippy mandatory. (#1103)
a517e8541f Remove unused deps (#1102)
873dae608a Remove unnessary deps (#1101)
13450b74ee Stored conversion rate updater (#1005)
74389829f3 [BREAKING] Migrate messages pallet to frame v2 (#1088)
424da938dd README fix (#1100)
865744c909 upgrade currency exchange pallet to frame v2 (#1097)
b5038148b3 Add missing docs (#1095)
0791e911c1 Common crate for substrate-relay (#1082)
3834c9d880 Update high-level-overview.md (#1093)
c93553face Increase the time window for messaging alerts. (#1092)
8b9cc3cecd migrate pallet-shift-session-manager to frame v2 (#1090)
dc91813c22 migrate eth PoA pallet to frame v2 (#1091)
f16bb098cc Migrate dispatch pallet  to frame v2 (#1089)
19f4325348 Bridge/This Chain Ids should be exposed as constants on pallet level. (#1085)
6381122df7 Change ChainSpec::from_genesis for Rialto and Millau chains to reflect the chain names. (#1079)
0f1d33e973 Make CI happy again (#1086)
238e65d96f fix typo (#1080)
fc008457b6 Token-swap-over-bridge pallet (#944)
3fb97fa5ef Fix full spellcheck (#1076)
eae4ed7170 fixed wrong trace (#1075)
219a0fad04 merge two weight-related loops in messages pallet (#1071)
fc85632fdb increase_message_fee depends on stored mesage size (#1066)
530f37a23b companion for https://github.com/paritytech/polkadot/pull/3507 (#1067)
53b8cba683 sc_basic_authorship=trace for millau nodes (#1074)
9874e05e98 Improve traces of message generator scripts (#1069)
7b5ee84fbb extract message_details impl into runtime common (#1070)
5a4aed5a8b refund weight for mot pruning messages (#1062)
90e3d1e111 Fix Westend -> Millau sync (#1064)
427d30ddfc When restarting client, also "restart" tokio runtime (#1065)
d47c05eeef Change get pipeline sensitive variables from Vault instead of GitLab settings (#1063)
d775a85415 use tokio reactor to execute jsonrpsee futures (#1061)
15c8cd61cb Use BABE to author blocks on Rialto (previously: Aura) (#1050)
5186293500 Allow reading suri && password override from file (#1059)
b506298262 Update jsonrpsee reference (#1049)
1734d00517 enable weight fee adjustent in Rialto/Millau (#1044)
607265afae Pay dispatch fee at target chain cli option (#1043)
ce79ef91be bump dependencies before start referencing polkadot repo (#1048)
924fa24f6d Cli option for greedy relayer + run no-losses relayer by default (#1042)
e21eba7b59 Yrong README Fixup + M1 Fixes (#1045)
20d08204a2 Confirm delivery detects when more than expected messages are confirmed (#1039)
994b846b52 pre and post dispatch weights of OnDeliveryConfirmed callback (#1040)
1dd5297e84 give real value to Rialto and Millau tokens (#1038)
035bee8715 Use real conversion rate in greedy relayer strategy (#1035)
9cfaecd0f7 fixed metrics prefix (#1037)
1d8d224937 Use kebab-case for bridge arguments (#1036)
f30a4c79a6 Shared reference to conversion rate metric value (#1034)
c34d7a5cbb estimate transaction fee (#1015)
93404b18bb change alert period from 2m to 10m for Westend -> Millau (GRANDPA or public node itself is lagging sometimes) (#1032)

git-subtree-dir: bridges
git-subtree-split: 407bf44a8a5f4e60aceef2dc755cd9ff09929ac3
This commit is contained in:
antonio-dropulic
2021-12-01 09:24:53 +01:00
parent feefc34567
commit 392447f5c8
1020 changed files with 30080 additions and 179754 deletions
+173 -43
View File
@@ -1,109 +1,239 @@
150
adversary/SM
annualised/MS
Apache-2.0/M
api/SM
90
&&
1KB
1MB
5MB
=
API/SM
APIs
assignee/SM
async
AccountId/MS
Apache-2.0/M
Autogenerated
BFT/M
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
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
BTC
BTC/S
CLI/MS
codec/SM
chain_getBlock
choosen
config/MS
crypto/MS
customizable/B
debian/M
decodable/MS
dispatchable/SM
DMP/SM
DOT/S
delivery_and_dispatch_fee
dev
dispatchable
dispatchables
doesn
ed25519
enum/MS
ERC-20
ETH
entrypoint/MS
ethereum/MS
externality/MS
extrinsic/MS
extrinsics
fedora/M
GiB/S
GPL/M
GPLv3/M
Handler/MS
HMP/SM
functor
fuzzer
hasher
hardcoded
https
implementers
include/BG
inherent/MS
initialize/RG
instantiate/B
intrinsic/MS
intrinsics
invariant/MS
invariants
io
isn
isolate/BG
jaeger/MS
js
jsonrpsee
keccak
keccak256/M
KSM/S
keyring
keystore/MS
kusama/S
KYC/M
lane
malus
max_value
merkle/MS
metadata
millau
misbehavior/SM
misbehaviors
MIT/M
MQC/SM
multivalidator/SM
NFT/SM
natively
no_std
nonces
number
ok
oneshot/MS
others'
pallet_bridge_grandpa
pallet_bridge_messages
pallet_message_lane
parablock/MS
parachain/MS
param/MS
parameterize/D
picosecond/SM
plancks
polkadot/MS
pov-block/MS
PoV/MS
precommit
promethius
promethius'
provisioner/MS
probabilistically
prune_depth
prune_end
receival
reconnection
redhat/M
repo/MS
RPC/MS
runtime/MS
rustc/MS
relayer/MS
shouldn
source_at_target
source_latest_confirmed
source_latest_generated
sp_finality_grandpa
spawner
sr25519
src
stringified
struct/MS
submitters/MS
subsystem/MS
subsystems'
subcommand/MS
synchronizer
target_at_source
target_latest_confirmed
target_latest_received
taskmanager/MS
TCP
teleport/RG
teleportation/SM
teleporter/SM
teleporters
testnet/MS
timeframe
tokio
timestamp
trie/MS
trustless/Y
tuple/SM
tuple
u32
ubuntu/M
UDP
UI
unfinalize/B
undeliverable
unfinalized
union/MSG
unpruned
unservable/B
unsynced
updatable
validator/SM
VMP/SM
VRF/SM
ve
vec
verifier
w3f/MS
wakeup
wasm/M
WND/S
XCM/S
XCMP/M
instantiation/SM
NFA
websocket
x2
~
+3 -3
View File
@@ -2,12 +2,12 @@
lang = "en_US"
search_dirs = ["."]
extra_dictionaries = ["lingua.dic"]
skip_os_lookups = true
use_builtin = true
[hunspell.quirks]
# `Type`'s
# 5x
# He tagged it as 'TheGreatestOfAllTimes'
# Transforms'
transform_regex = ["^'([^\\s])'$", "^[0-9]+(?:\\.[0-9]*)?(x|%)$", "^(.*)'$", "^\\+$"]
transform_regex = ["^'([^\\s])'$", "^[0-9]+(?:\\.[0-9]*)?x$", "^'s$", "^\\+$", "[><+-]"]
allow_concatenation = true
allow_dashes = true
+1 -2
View File
@@ -1,2 +1 @@
doc
**/target
**/target/
+5 -12
View File
@@ -1,26 +1,19 @@
root = true
[*.rs]
[*]
indent_style=tab
indent_size=tab
tab_width=4
max_line_length=120
end_of_line=lf
charset=utf-8
trim_trailing_whitespace=true
max_line_length=100
insert_final_newline=true
[*.yml]
[*.{yml,md,yaml,sh}]
indent_style=space
indent_size=2
tab_width=8
end_of_line=lf
charset=utf-8
trim_trailing_whitespace=true
insert_final_newline=true
[*.sh]
indent_style=space
indent_size=2
tab_width=8
end_of_line=lf
[*.md]
max_line_length=80
-1
View File
@@ -1 +0,0 @@
bridges/* @tomusdrw @svyatonik @hcastano
-13
View File
@@ -1,13 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
- It would help if you submit info about the system you are running, e.g.: operating system, kernel version, amount of available memory and swap, etc.
- Logs could be very helpful. If possible, submit the whole log. Please format it as ```code blocks```.
- Describe the role your node plays, e.g. validator, full node or light client.
- Any command-line options were passed?
-143
View File
@@ -1,143 +0,0 @@
---
name: Release issue template
about: Tracking issue for new releases
title: Polkadot {{ env.VERSION }} Release checklist
---
# Release Checklist
This is the release checklist for Polkadot {{ env.VERSION }}. **All** following
checks should be completed before publishing a new release of the
Polkadot/Kusama/Westend runtime or client. The current release candidate can be
checked out with `git checkout release-{{ env.VERSION }}`
### Runtime Releases
These checks should be performed on the codebase prior to forking to a release-
candidate branch.
- [ ] Verify [`spec_version`](#spec-version) has been incremented since the
last release for any native runtimes from any existing use on public
(non-private/test) networks.
- [ ] Verify previously [completed migrations](#old-migrations-removed) are
removed for any public (non-private/test) networks.
- [ ] Verify pallet and [extrinsic ordering](#extrinsic-ordering) has stayed
the same. Bump `transaction_version` if not.
- [ ] Verify new extrinsics have been correctly whitelisted/blacklisted for
[proxy filters](#proxy-filtering).
- [ ] Verify [benchmarks](#benchmarks) have been updated for any modified
runtime logic.
The following checks can be performed after we have forked off to the release-
candidate branch or started an additional release candidate branch (rc-2, rc-3, etc)
- [ ] Verify [new migrations](#new-migrations) complete successfully, and the
runtime state is correctly updated for any public (non-private/test)
networks.
- [ ] Verify [Polkadot JS API](#polkadot-js) are up to date with the latest
runtime changes.
- [ ] Push runtime upgrade to Westend and verify network stability.
### All Releases
- [ ] Check that the new client versions have [run on the network](#burn-in)
without issue for 12 hours.
- [ ] Check that a draft release has been created at
https://github.com/paritytech/polkadot/releases with relevant [release
notes](#release-notes)
- [ ] Check that [build artifacts](#build-artifacts) have been added to the
draft-release
## Notes
### Burn In
Ensure that Parity DevOps has run the new release on Westend, Kusama, and
Polkadot validators for at least 12 hours prior to publishing the release.
### Build Artifacts
Add any necessary assets to the release. They should include:
- Linux binary
- GPG signature of the Linux binary
- SHA256 of binary
- Source code
- Wasm binaries of any runtimes
### Release notes
The release notes should list:
- The priority of the release (i.e., how quickly users should upgrade) - this is
based on the max priority of any *client* changes.
- Which native runtimes and their versions are included
- The proposal hashes of the runtimes as built with
[srtool](https://gitlab.com/chevdor/srtool)
- Any changes in this release that are still awaiting audit
The release notes may also list:
- Free text at the beginning of the notes mentioning anything important
regarding this release
- Notable changes (those labelled with B[1-9]-* labels) separated into sections
### Spec Version
A runtime upgrade must bump the spec number. This may follow a pattern with the
client release (e.g. runtime v12 corresponds to v0.8.12, even if the current
runtime is not v11).
### Old Migrations Removed
Any previous `on_runtime_upgrade` functions from old upgrades must be removed
to prevent them from executing a second time. The `on_runtime_upgrade` function
can be found in `runtime/<runtime>/src/lib.rs`.
### New Migrations
Ensure that any migrations that are required due to storage or logic changes
are included in the `on_runtime_upgrade` function of the appropriate pallets.
### Extrinsic Ordering
Offline signing libraries depend on a consistent ordering of call indices and
functions. Compare the metadata of the current and new runtimes and ensure that
the `module index, call index` tuples map to the same set of functions. In case
of a breaking change, increase `transaction_version`.
To verify the order has not changed:
1. Download the latest release-candidate binary either from the draft-release
on Github, or
[AWS](https://releases.parity.io/polkadot/x86_64-debian:stretch/{{ env.VERSION }}-rc1/polkadot)
(adjust the rc in this URL as necessary).
2. Run the release-candidate binary using a local chain:
`./polkadot --chain=polkadot-local` or `./polkadot --chain=kusama.local`
3. Use [`polkadot-js-tools`](https://github.com/polkadot-js/tools) to compare
the metadata:
- For Polkadot: `docker run --network host jacogr/polkadot-js-tools metadata wss://rpc.polkadot.io ws://localhost:9944`
- For Kusama: `docker run --network host jacogr/polkadot-js-tools metadata wss://kusama-rpc.polkadot.io ws://localhost:9944`
4. Things to look for in the output are lines like:
- `[Identity] idx 28 -> 25 (calls 15)` - indicates the index for `Identity` has changed
- `[+] Society, Recovery` - indicates the new version includes 2 additional modules/pallets.
- If no indices have changed, every modules line should look something like `[Identity] idx 25 (calls 15)`
Note: Adding new functions to the runtime does not constitute a breaking change
as long as they are added to the end of a pallet (i.e., does not break any
other call index).
### Proxy Filtering
The runtime contains proxy filters that map proxy types to allowable calls. If
the new runtime contains any new calls, verify that the proxy filters are up to
date to include them.
### Benchmarks
Run the benchmarking suite with the new runtime and update any function weights
if necessary.
### Polkadot JS
Ensure that a release of [Polkadot JS API]() contains any new types or
interfaces necessary to interact with the new runtime.
+40 -15
View File
@@ -1,17 +1,42 @@
version: 2
updates:
- package-ecosystem: "cargo"
directory: "/"
labels: ["A2-insubstantial", "B0-silent", "C1-low 📌"]
# Handle updates for crates from github.com/paritytech/substrate manually.
ignore:
- dependency-name: "substrate-*"
- dependency-name: "sc-*"
- dependency-name: "sp-*"
- dependency-name: "frame-*"
- dependency-name: "fork-tree"
- dependency-name: "pallet-*"
- dependency-name: "beefy-*"
- dependency-name: "try-runtime-*"
schedule:
interval: "daily"
- package-ecosystem: cargo
directory: "/"
schedule:
interval: weekly
time: "03:00"
timezone: Europe/Berlin
open-pull-requests-limit: 20
ignore:
- dependency-name: frame-*
versions:
- ">= 0"
- dependency-name: node-inspect
versions:
- ">= 0"
- dependency-name: pallet-*
versions:
- ">= 0"
- dependency-name: sc-*
versions:
- ">= 0"
- dependency-name: sp-*
versions:
- ">= 0"
- dependency-name: substrate-*
versions:
- ">= 0"
- dependency-name: vergen
versions:
- 4.0.1
- 4.0.2
- 4.1.0
- 4.2.0
- dependency-name: jsonrpc-core
versions:
- 17.0.0
- dependency-name: finality-grandpa
versions:
- 0.13.0
- 0.14.0
rebase-strategy: disabled
-21
View File
@@ -1,21 +0,0 @@
name: Label PRs
on:
pull_request:
types: [opened,ready_for_review]
jobs:
label-new-prs:
runs-on: ubuntu-latest
steps:
- name: Label drafts
uses: andymckay/labeler@master
if: github.event.pull_request.draft == true
with:
add-labels: 'A3-inprogress'
remove-labels: 'A0-pleasereview'
- name: Label PRs
uses: andymckay/labeler@master
if: github.event.pull_request.draft == false && ! contains(github.event.pull_request.labels.*.name, 'A2-insubstantial')
with:
add-labels: 'A0-pleasereview'
remove-labels: 'A3-inprogress'
@@ -1,17 +0,0 @@
name: Notify devops when burn-in label applied
on:
pull_request:
types: [labeled]
jobs:
notify-devops:
runs-on: ubuntu-latest
steps:
- name: Notify devops
if: github.event.label.name == 'A1-needsburnin'
uses: s3krit/matrix-message-action@v0.0.3
with:
room_id: ${{ secrets.POLKADOT_DEVOPS_MATRIX_ROOM_ID }}
access_token: ${{ secrets.POLKADOT_DEVOPS_MATRIX_ACCESS_TOKEN }}
message: "@room Burn-in request received for the following PR: ${{ github.event.pull_request.html_url }}"
server: "matrix.parity.io"
-22
View File
@@ -1,22 +0,0 @@
name: Check labels
on:
pull_request:
types: [labeled, opened, synchronize, unlabeled]
jobs:
check-labels:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Check labels
run: bash ${{ github.workspace }}/scripts/github/check_labels.sh
env:
GITHUB_PR: ${{ github.event.pull_request.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
-84
View File
@@ -1,84 +0,0 @@
name: Run nightly fuzzer jobs
on:
schedule:
- cron: '0 0 * * *'
jobs:
erasure-coding-round-trip:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Install minimal stable Rust
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Install minimal nightly Rust
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
target: wasm32-unknown-unknown
- name: Install honggfuzz deps
run: sudo apt-get install --no-install-recommends binutils-dev libunwind8-dev
- name: Install honggfuzz
uses: actions-rs/cargo@v1
with:
command: install
args: honggfuzz --version "0.5.54"
- name: Build fuzzer binaries
working-directory: erasure-coding/fuzzer
run: cargo hfuzz build
- name: Run fuzzer
working-directory: erasure-coding/fuzzer
run: bash $GITHUB_WORKSPACE/scripts/github/run_fuzzer.sh round_trip
erasure-coding-reconstruct:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Install minimal stable Rust
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Install minimal nightly Rust
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
target: wasm32-unknown-unknown
- name: Install honggfuzz deps
run: sudo apt-get install --no-install-recommends binutils-dev libunwind8-dev
- name: Install honggfuzz
uses: actions-rs/cargo@v1
with:
command: install
args: honggfuzz --version "0.5.54"
- name: Build fuzzer binaries
working-directory: erasure-coding/fuzzer
run: cargo hfuzz build
- name: Run fuzzer
working-directory: erasure-coding/fuzzer
run: bash $GITHUB_WORKSPACE/scripts/github/run_fuzzer.sh reconstruct
-43
View File
@@ -1,43 +0,0 @@
name: Publish Docker image for new releases
on:
release:
types:
- published
jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to Dockerhub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
push: true
file: scripts/docker/release.Dockerfile
tags: |
parity/polkadot:latest
parity/polkadot:${{ github.event.release.tag_name }}
build-args: |
POLKADOT_VERSION=${{ github.event.release.tag_name }}
VCS_REF=${{ github.ref }}
BUILD_DATE=${{ github.event.release.published_at }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
-145
View File
@@ -1,145 +0,0 @@
name: Publish draft release
on:
push:
tags:
# Catches v1.2.3 and v1.2.3-rc1
- v[0-9]+.[0-9]+.[0-9]+*
jobs:
get-rust-versions:
runs-on: ubuntu-latest
container:
image: paritytech/ci-linux:production
outputs:
rustc-stable: ${{ steps.get-rust-versions.outputs.stable }}
rustc-nightly: ${{ steps.get-rust-versions.outputs.nightly }}
steps:
- id: get-rust-versions
run: |
echo "::set-output name=stable::$(rustc +stable --version)"
echo "::set-output name=nightly::$(rustc +nightly --version)"
build-runtimes:
runs-on: ubuntu-latest
strategy:
matrix:
runtime: ['polkadot', 'kusama']
container:
image: paritytech/srtool:nightly-2021-03-15
volumes:
- ${{ github.workspace }}:/build
env:
PACKAGE: ${{ matrix.runtime }}-runtime
RUSTC_VERSION: nightly-2020-10-27
steps:
- uses: actions/checkout@v2
- name: Cache target dir
uses: actions/cache@v2
with:
path: '${{ github.workspace }}/runtime/${{ matrix.runtime }}/target'
key: srtool-target-${{ matrix.runtime }}-${{ github.sha }}
restore-keys: |
srtool-target-${{ matrix.runtime }}-
srtool-target-
- name: Build ${{ matrix.runtime }} runtime
id: build-runtime
shell: bash
env:
srtool_output_filename: ${{ matrix.runtime }}_srtool_output.json
run: |
cd /build
pwd
ls -la
build --json | tee $srtool_output_filename
cat $srtool_output_filename
while IFS= read -r line; do
echo "::set-output name=$line::$(jq -r ".$line" < $srtool_output_filename)"
done <<< "$(jq -r 'keys[]' < $srtool_output_filename)"
- name: Upload ${{ matrix.runtime }} srtool json
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.runtime }}-srtool-json
path: ${{ matrix.runtime }}_srtool_output.json
- name: Upload ${{ matrix.runtime }} runtime
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.runtime }}-runtime
path: "${{ steps.build-runtime.outputs.wasm }}"
publish-draft-release:
runs-on: ubuntu-latest
needs: ['get-rust-versions', 'build-runtimes']
outputs:
release_url: ${{ steps.create-release.outputs.html_url }}
asset_upload_url: ${{ steps.create-release.outputs.upload_url }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
path: polkadot
- name: Set up Ruby 2.7
uses: actions/setup-ruby@v1
with:
ruby-version: 2.7
- name: Download srtool json output
uses: actions/download-artifact@v2
- name: Generate release text
env:
RUSTC_STABLE: ${{ needs.get-rust-versions.outputs.rustc-stable }}
RUSTC_NIGHTLY: ${{ needs.get-rust-versions.outputs.rustc-nightly }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gem install changelogerator git toml
ruby $GITHUB_WORKSPACE/polkadot/scripts/github/generate_release_text.rb | tee release_text.md
- name: Create draft release
id: create-release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Polkadot ${{ github.ref }}
body_path: ./release_text.md
draft: true
publish-runtimes:
runs-on: ubuntu-latest
needs: ['publish-draft-release']
strategy:
matrix:
runtime: ['polkadot', 'kusama']
steps:
- uses: actions/checkout@v2
- uses: actions/download-artifact@v2
- name: Set up Ruby 2.7
uses: actions/setup-ruby@v1
with:
ruby-version: 2.7
- name: Get runtime version
id: get-runtime-ver
run: |
ls
ls "${{ matrix.runtime }}-runtime"
runtime_ver="$(ruby -e 'require "./scripts/github/lib.rb"; puts get_runtime("${{ matrix.runtime }}")')"
echo "::set-output name=runtime_ver::$runtime_ver"
- name: Upload ${{ matrix.runtime }} wasm
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.publish-draft-release.outputs.asset_upload_url }}
asset_path: "${{ matrix.runtime }}-runtime/${{ matrix.runtime }}_runtime.compact.wasm"
asset_name: ${{ matrix.runtime }}_runtime-v${{ steps.get-runtime-ver.outputs.runtime_ver }}.compact.wasm
asset_content_type: application/wasm
post_to_matrix:
runs-on: ubuntu-latest
needs: publish-draft-release
steps:
- name: Internal polkadot channel
uses: s3krit/matrix-message-action@v0.0.2
with:
room_id: ${{ secrets.INTERNAL_POLKADOT_MATRIX_ROOM_ID }}
access_token: ${{ secrets.MATRIX_ACCESS_TOKEN }}
message: "**New version of polkadot tagged**: ${{ github.ref }}<br/>Draft release created: ${{ needs.publish-draft-release.outputs.release_url }}"
server: "matrix.parity.io"
-23
View File
@@ -1,23 +0,0 @@
name: Send new release notification to matrix channels
on:
release:
types:
- published
jobs:
ping_matrix:
strategy:
matrix:
channel:
- '!LhjZccBOqFNYKLdmbb:polkadot.builders' # #KusamaValidatorLounge:polkadot.builders
- '!FMwxpQnYhRCNDRsYGI:matrix.parity.io' # #kusama-announcements:matrix.parity.io
- '!NZrbtteFeqYKCUGQtr:matrix.parity.io' # #polkadotvalidatorlounge:web3.foundation
- '!UqHPWiCBGZWxrmYBkF:matrix.parity.io' # #polkadot-announcements:matrix.parity.io
- '!NTogofoetwjbTwOoPi:matrix.parity.io' # Internal release-notes channel
runs-on: ubuntu-latest
steps:
- uses: s3krit/matrix-message-action@v0.0.3
with:
room_id: ${{ matrix.channel }} # heh
access_token: ${{ secrets.MATRIX_ACCESS_TOKEN }}
message: "***Polkadot ${{github.event.release.tag_name}} has been released!***<br/>${{github.event.release.html_url}}<br/><br/>${{github.event.release.body}}<br/>"
server: "matrix.parity.io"
-57
View File
@@ -1,57 +0,0 @@
name: Release-candidate automation
on:
push:
branches:
- release-v[0-9]+.[0-9]+.[0-9]+
jobs:
tag_rc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- id: compute_tag
name: Compute next rc tag
shell: bash
run: |
# Get last rc tag if exists, else set it to {version}-rc1
version=${GITHUB_REF#refs/heads/release-}
echo "$version"
echo "::set-output name=version::$version"
git tag -l
last_rc=$(git tag -l "$version-rc*" | sort -V | tail -n 1)
if [ -n "$last_rc" ]; then
suffix=$(echo "$last_rc" | grep -Eo '[0-9]+$')
echo $suffix
((suffix++))
echo $suffix
echo "::set-output name=new_tag::$version-rc$suffix"
echo "::set-output name=first_rc::false"
else
echo "::set-output name=new_tag::$version-rc1"
echo "::set-output name=first_rc::true"
fi
- name: Apply new tag
uses: tvdias/github-tagger@v0.0.2
with:
# We can't use the normal GITHUB_TOKEN for the following reason:
# https://docs.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token
# RELEASE_BRANCH_TOKEN requires public_repo OAuth scope
repo-token: "${{ secrets.RELEASE_BRANCH_TOKEN }}"
tag: ${{ steps.compute_tag.outputs.new_tag }}
- id: create-issue
uses: JasonEtco/create-an-issue@v2
# Only create the issue if it's the first release candidate
if: steps.compute_tag.outputs.first_rc == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.compute_tag.outputs.version }}
with:
filename: .github/ISSUE_TEMPLATE/release.md
- uses: s3krit/matrix-message-action@v0.0.2
if: steps.create-issue.outputs.url != ''
with:
room_id: ${{ secrets.INTERNAL_POLKADOT_MATRIX_ROOM_ID }}
access_token: ${{ secrets.MATRIX_ACCESS_TOKEN }}
server: "matrix.parity.io"
message: "Release process for polkadot ${{ steps.compute_tag.outputs.version }} has been started. Tracking issue: ${{ steps.create-issue.outputs.url }}"
+22 -9
View File
@@ -1,13 +1,26 @@
**/target/
**/.env
**/.env2
**/rust-toolchain
hfuzz_target
hfuzz_workspace
**/Cargo.lock
**/*.rs.bk
*.swp
.wasm-binaries
runtime/wasm/target/
**/._*
*.o
*.so
*.rlib
*.dll
.gdb_history
*.exe
.DS_Store
.cargo
.idea
.vscode
polkadot.*
!polkadot.service
!.rpm/*
.DS_Store
.cargo
*.iml
*.swp
*.swo
+216 -310
View File
@@ -1,33 +1,22 @@
# .gitlab-ci.yml
#
# polkadot
#
# pipelines can be triggered manually in the web
# setting DEPLOY_TAG will only deploy the tagged image
#
# please do not add new jobs without "rules:" and "*-env". There are &rules-test for everything,
# &rules-pr-only preset. And "kubernetes-env" with "docker-env" to set a runner
# which executes the job.
stages:
- lint
- check
- test
- build
- publish
- deploy
image: paritytech/ci-linux:production
workflow:
rules:
- if: $CI_COMMIT_TAG
- if: $CI_COMMIT_BRANCH
variables:
variables: &default-vars
GIT_STRATEGY: fetch
GIT_DEPTH: 100
CI_SERVER_NAME: "GitLab CI"
DOCKER_OS: "debian:stretch"
CARGO_INCREMENTAL: 0
ARCH: "x86_64"
CI_IMAGE: "paritytech/bridges-ci:staging"
RUST_BACKTRACE: full
default:
cache: {}
@@ -36,16 +25,23 @@ default:
artifacts:
name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
when: on_success
expire_in: 28 days
expire_in: 7 days
paths:
- ./artifacts/
- artifacts/
.kubernetes-env: &kubernetes-env
.kubernetes-build: &kubernetes-build
tags:
- kubernetes-parity-build
interruptible: true
.docker-env: &docker-env
image: "${CI_IMAGE}"
before_script:
- rustup show
- cargo --version
- rustup +nightly show
- cargo +nightly --version
- sccache -s
retry:
max: 2
when:
@@ -56,336 +52,246 @@ default:
tags:
- linux-docker
.compiler-info: &compiler-info
before_script:
- rustup show
- cargo --version
- sccache -s
.rules-test: &rules-test
# these jobs run always*
.test-refs: &test-refs
rules:
- if: $CI_COMMIT_REF_NAME == "rococo-v1"
when: never
- when: always
.pr-only: &rules-pr-only
# these jobs run only on PRs
rules:
- if: $CI_COMMIT_REF_NAME == "rococo-v1"
when: never
# FIXME: This is the cause why pipelines wouldn't start. The problem might be in our custom
# mirroring. This should be investigated further, but for now let's have the working
# pipeline.
# - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH
# changes:
# - '**.md'
# - diagrams/*
# - docs/*
# when: never
- if: $CI_PIPELINE_SOURCE == "pipeline"
- if: $CI_PIPELINE_SOURCE == "web"
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
- if: $CI_COMMIT_REF_NAME == "master"
- if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs
- if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1
.build-refs: &build-refs
rules:
# won't run on the CI image update pipeline
- 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
- if: $CI_PIPELINE_SOURCE == "schedule" && $PIPELINE == "nightly"
.nightly-test: &nightly-test
rules:
# 2. another is triggered by scripts repo $CI_PIPELINE_SOURCE == "pipeline" it's for the CI image
# update, it also runs all the nightly checks.
- if: $CI_PIPELINE_SOURCE == "pipeline"
#### stage: lint
clippy-nightly:
stage: lint
<<: *docker-env
<<: *test-refs
script:
- SKIP_WASM_BUILD=1 cargo +nightly clippy --all-targets -- -A clippy::redundant_closure
fmt:
stage: lint
<<: *docker-env
<<: *test-refs
script:
- cargo +nightly fmt --all -- --check
spellcheck:
stage: lint
<<: *docker-env
<<: *test-refs
script:
- cargo spellcheck check -vvvv --cfg=.config/spellcheck.toml --checkers hunspell -m 1
#### stage: check
check:
stage: check
<<: *docker-env
<<: *test-refs
script: &check-script
- SKIP_WASM_BUILD=1 time cargo check --locked --verbose --workspace
# Check Rialto benchmarks runtime
- SKIP_WASM_BUILD=1 time cargo check -p rialto-runtime --locked --features runtime-benchmarks --verbose
# Check Millau benchmarks runtime
- SKIP_WASM_BUILD=1 time cargo check -p millau-runtime --locked --features runtime-benchmarks --verbose
check-nightly:
stage: check
<<: *docker-env
<<: *nightly-test
script:
- rustup default nightly
- *check-script
#### stage: test
check-runtime:
test:
stage: test
image: paritytech/tools:latest
<<: *kubernetes-env
<<: *rules-pr-only
variables:
GITLAB_API: "https://gitlab.parity.io/api/v4"
GITHUB_API_PROJECT: "parity%2Finfrastructure%2Fgithub-api"
<<: *docker-env
<<: *test-refs
# variables:
# RUSTFLAGS: "-D warnings"
script: &test-script
- 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
<<: *docker-env
<<: *nightly-test
script:
- ./scripts/gitlab/check_runtime.sh
- rustup default nightly
- *test-script
deny:
stage: test
<<: *docker-env
<<: *nightly-test
<<: *collect-artifacts
script:
- cargo deny check advisories --hide-inclusion-graph
- cargo deny check bans sources --hide-inclusion-graph
after_script:
- mkdir -p ./artifacts
- echo "___Complete logs can be found in the artifacts___"
- cargo deny check advisories 2> advisories.log
- cargo deny check bans sources 2> bans_sources.log
# this job is allowed to fail, only licenses check is important
allow_failure: true
check-line-width:
stage: test
image: paritytech/tools:latest
<<: *kubernetes-env
<<: *rules-pr-only
script:
- ./scripts/gitlab/check_line_width.sh
allow_failure: true
test-deterministic-wasm:
stage: test
<<: *rules-test
<<: *docker-env
<<: *compiler-info
script:
- ./scripts/gitlab/test_deterministic_wasm.sh
test-build-linux-stable:
deny-licenses:
stage: test
<<: *docker-env
<<: *compiler-info
<<: *test-refs
<<: *collect-artifacts
variables:
RUST_TOOLCHAIN: stable
# Enable debug assertions since we are running optimized builds for testing
# but still want to have debug assertions.
RUSTFLAGS: "-Cdebug-assertions=y -Dwarnings"
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_COMMIT_REF_NAME == "master"
- if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1
- if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs
- if: $CI_COMMIT_REF_NAME == "rococo-v1"
script:
- ./scripts/gitlab/test_linux_stable.sh
# we're using the bin built here, instead of having a parallel `build-linux-release`
- time cargo build --release --verbose --bin polkadot
- sccache -s
# pack-artifacts
- cargo deny check licenses --hide-inclusion-graph
after_script:
- mkdir -p ./artifacts
- VERSION="${CI_COMMIT_REF_NAME}" # will be tag or branch name
- mv ./target/release/polkadot ./artifacts/.
- sha256sum ./artifacts/polkadot | tee ./artifacts/polkadot.sha256
- EXTRATAG="$(./artifacts/polkadot --version |
sed -n -r 's/^polkadot ([0-9.]+.*-[0-9a-f]{7,13})-.*$/\1/p')"
- EXTRATAG="${CI_COMMIT_REF_NAME}-${EXTRATAG}-$(cut -c 1-8 ./artifacts/polkadot.sha256)"
- echo "Polkadot version = ${VERSION} (EXTRATAG = ${EXTRATAG})"
- echo -n ${VERSION} > ./artifacts/VERSION
- echo -n ${EXTRATAG} > ./artifacts/EXTRATAG
- cp -r scripts/docker/* ./artifacts
check-web-wasm:
stage: test
<<: *rules-test
<<: *docker-env
<<: *compiler-info
script:
# WASM support is in progress. As more and more crates support WASM, we should
# add entries here. See https://github.com/paritytech/polkadot/issues/625
- ./scripts/gitlab/check_web_wasm.sh
- sccache -s
check-runtime-benchmarks:
stage: test
<<: *rules-test
<<: *docker-env
<<: *compiler-info
script:
# Check that the node will compile with `runtime-benchmarks` feature flag.
- ./scripts/gitlab/check_runtime_benchmarks.sh
- sccache -s
build-adder-collator:
stage: test
<<: *collect-artifacts
<<: *docker-env
<<: *compiler-info
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_COMMIT_REF_NAME == "master"
- if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs
- if: $CI_COMMIT_REF_NAME == "rococo-v1"
script:
- time cargo build --release --verbose -p test-parachain-adder-collator
- sccache -s
# pack artifacts
- mkdir -p ./artifacts
- mv ./target/release/adder-collator ./artifacts/.
- echo -n "${CI_COMMIT_REF_NAME}" > ./artifacts/VERSION
- echo -n "${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHORT_SHA}" > ./artifacts/EXTRATAG
- echo "adder-collator version = $(cat ./artifacts/VERSION) (EXTRATAG = $(cat ./artifacts/EXTRATAG))"
- cp -r scripts/docker/* ./artifacts
- echo "___Complete logs can be found in the artifacts___"
- cargo deny check licenses 2> licenses.log
#### stage: build
check-transaction-versions:
image: node:15
build:
stage: build
<<: *rules-test
<<: *docker-env
needs:
- job: test-build-linux-stable
artifacts: true
before_script:
- apt-get -y update; apt-get -y install jq lsof
- npm install --ignore-scripts -g @polkadot/metadata-cmp
- git fetch origin release
script:
- scripts/gitlab/check_extrinsics_ordering.sh
<<: *build-refs
<<: *collect-artifacts
# master
script: &build-script
- 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/
- mv -v ./ci.Dockerfile ./artifacts/
generate-impl-guide:
build-nightly:
stage: build
<<: *rules-test
<<: *docker-env
image:
name: michaelfbryan/mdbook-docker-image:v0.4.4
entrypoint: [""]
<<: *collect-artifacts
<<: *nightly-test
script:
- mdbook build roadmap/implementers-guide
- rustup default nightly
- *build-script
#### stage: publish
.build-push-image: &build-push-image
<<: *kubernetes-env
<<: *kubernetes-build
image: quay.io/buildah/stable
<<: *build-refs
variables: &image-variables
GIT_STRATEGY: none
DOCKER_USER: ${PARITYPR_USER}
DOCKER_PASS: ${PARITYPR_PASS}
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
before_script: &check-versions
- test -s ./artifacts/VERSION || exit 1
- test -s ./artifacts/EXTRATAG || exit 1
- VERSION="$(cat ./artifacts/VERSION)"
- EXTRATAG="$(cat ./artifacts/EXTRATAG)"
- echo "Polkadot version = ${VERSION} (EXTRATAG = ${EXTRATAG})"
- if [[ "${CI_COMMIT_TAG}" ]]; then
VERSION=${CI_COMMIT_TAG};
elif [[ "${CI_COMMIT_REF_NAME}" ]]; then
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_USER" -a "$DOCKER_PASS" ||
- test "${DOCKER_HUB_USER}" -a "${DOCKER_HUB_PASS}" ||
( echo "no docker credentials provided"; exit 1 )
- cd ./artifacts
- buildah bud
--format=docker
--build-arg VCS_REF="${CI_COMMIT_SHA}"
--build-arg BUILD_DATE="$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
--build-arg IMAGE_NAME="${IMAGE_NAME}"
--tag "$IMAGE_NAME:$VERSION"
--tag "$IMAGE_NAME:$EXTRATAG"
--file ${DOCKERFILE} .
--build-arg VCS_REF="${CI_COMMIT_SHORT_SHA}"
--build-arg BUILD_DATE="$(date +%d-%m-%Y)"
--build-arg PROJECT="${CI_JOB_NAME}"
--build-arg VERSION="${VERSION}"
--tag "${IMAGE_NAME}:${VERSION}"
--tag "${IMAGE_NAME}:sha-${CI_COMMIT_SHORT_SHA}"
--tag "${IMAGE_NAME}:latest"
--file "${DOCKERFILE}" .
# The job will success only on the protected branch
- echo "$DOCKER_PASS" |
buildah login --username "$DOCKER_USER" --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:$EXTRATAG"
- 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:
- buildah logout "$IMAGE_NAME"
# pass artifacts to the trigger-simnet job
- echo "IMAGE_NAME=${IMAGE_NAME}" > ./artifacts/build.env
- echo "IMAGE_TAG=$(cat ./artifacts/EXTRATAG)" >> ./artifacts/build.env
artifacts:
reports:
# this artifact is used in trigger-simnet job
# https://docs.gitlab.com/ee/ci/multi_project_pipelines.html#with-variable-inheritance
dotenv: ./artifacts/build.env
- env REGISTRY_AUTH_FILE= buildah logout --all
publish-polkadot-image:
stage: build
<<: *build-push-image
variables:
<<: *image-variables
# scripts/docker/Dockerfile
DOCKERFILE: Dockerfile
IMAGE_NAME: docker.io/paritypr/synth-wave
rules:
# Don't run on releases - this is handled by the Github Action here:
# .github/workflows/publish-docker-release.yml
- if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1
when: never
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_COMMIT_REF_NAME == "master"
- if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs
- if: $CI_COMMIT_REF_NAME == "rococo-v1"
variables:
<<: *image-variables
IMAGE_NAME: docker.io/parity/rococo
DOCKER_USER: ${Docker_Hub_User_Parity}
DOCKER_PASS: ${Docker_Hub_Pass_Parity}
needs:
- job: test-build-linux-stable
artifacts: true
publish-adder-collator-image:
# service image for Simnet
stage: build
<<: *build-push-image
variables:
<<: *image-variables
# scripts/docker/collator.Dockerfile
DOCKERFILE: collator.Dockerfile
IMAGE_NAME: docker.io/paritypr/colander
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_COMMIT_REF_NAME == "master"
- if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs
- if: $CI_COMMIT_REF_NAME == "rococo-v1"
needs:
- job: build-adder-collator
artifacts: true
after_script:
- buildah logout "$IMAGE_NAME"
# pass artifacts to the trigger-simnet job
- echo "COLLATOR_IMAGE_TAG=$(cat ./artifacts/EXTRATAG)" > ./artifacts/collator.env
artifacts:
reports:
# this artifact is used in trigger-simnet job
dotenv: ./artifacts/collator.env
#### stage: publish
publish-s3-release: &publish-s3
rialto-bridge-node:
stage: publish
needs:
- job: test-build-linux-stable
artifacts: true
<<: *kubernetes-env
image: paritytech/awscli:latest
variables:
GIT_STRATEGY: none
PREFIX: "builds/polkadot/${ARCH}-${DOCKER_OS}"
rules:
# publishing binaries nightly
- if: $CI_PIPELINE_SOURCE == "schedule"
before_script:
- *check-versions
script:
- echo "uploading objects to https://releases.parity.io/${PREFIX}/${VERSION}"
- aws s3 sync --acl public-read ./artifacts/ s3://${AWS_BUCKET}/${PREFIX}/${VERSION}/
- echo "update objects at https://releases.parity.io/${PREFIX}/${EXTRATAG}"
- find ./artifacts -type f | while read file; do
name="${file#./artifacts/}";
aws s3api copy-object
--copy-source ${AWS_BUCKET}/${PREFIX}/${VERSION}/${name}
--bucket ${AWS_BUCKET} --key ${PREFIX}/${EXTRATAG}/${name};
done
- |
cat <<-EOM
|
| polkadot binary paths:
|
| - https://releases.parity.io/${PREFIX}/${EXTRATAG}/polkadot
| - https://releases.parity.io/${PREFIX}/${VERSION}/polkadot
|
EOM
after_script:
- aws s3 ls s3://${AWS_BUCKET}/${PREFIX}/${EXTRATAG}/
--recursive --human-readable --summarize
<<: *build-push-image
#### stage: deploy
rialto-parachain-collator:
stage: publish
<<: *build-push-image
deploy-polkasync-kusama:
stage: deploy
rules:
# former .rules-build
- if: $CI_COMMIT_REF_NAME == "rococo-v1"
when: never
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_COMMIT_REF_NAME == "master"
variables:
POLKADOT_CI_COMMIT_NAME: "${CI_COMMIT_REF_NAME}"
POLKADOT_CI_COMMIT_REF: "${CI_COMMIT_SHORT_SHA}"
allow_failure: true
trigger: "parity/infrastructure/parity-testnet"
millau-bridge-node:
stage: publish
<<: *build-push-image
trigger-simnet:
stage: deploy
image: paritytech/tools:latest
<<: *kubernetes-env
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_COMMIT_REF_NAME == "master"
- if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs
- if: $CI_COMMIT_REF_NAME == "rococo-v1"
needs:
- job: publish-polkadot-image
- job: publish-adder-collator-image
# `build.env` brings here `$IMAGE_NAME` and `$IMAGE_TAG` (`$EXTRATAG` here,
# i.e. `2643-0.8.29-5f689e0a-6b24dc54`).
# `collator.env` bears adder-collator unique build tag. In non-triggered builds it
# can be called by `master` tag.
# Simnet uses an image published on PRs with this exact version for triggered runs
# on commits. And parity/rococo:rococo-v1 for the runs not launched by this job.
variables:
TRGR_PROJECT: ${CI_PROJECT_NAME}
TRGR_REF: ${CI_COMMIT_REF_NAME}
# simnet project ID
DWNSTRM_ID: 332
script:
# API trigger for a simnet job, argument value is set in the project variables
- ./scripts/gitlab/trigger_pipeline.sh --simnet-version=${SIMNET_REF}
allow_failure: true
ethereum-poa-relay:
stage: publish
<<: *build-push-image
substrate-relay:
stage: publish
<<: *build-push-image
# FIXME: publish binaries
@@ -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}}
}
@@ -14,7 +14,7 @@
// 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}}
//! 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,7 +34,7 @@
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~}}
@@ -45,7 +45,7 @@ pub trait WeightInfo {
{{~/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|}}
-48
View File
@@ -1,48 +0,0 @@
%define debug_package %{nil}
Name: polkadot
Summary: Implementation of a https://polkadot.network node in Rust based on the Substrate framework.
Version: @@VERSION@@
Release: @@RELEASE@@%{?dist}
License: GPLv3
Group: Applications/System
Source0: %{name}-%{version}.tar.gz
Requires: systemd, shadow-utils
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
%description
%{summary}
%prep
%setup -q
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}
cp -a * %{buildroot}
%post
config_file="/etc/default/polkadot"
getent group polkadot >/dev/null || groupadd -r polkadot
getent passwd polkadot >/dev/null || \
useradd -r -g polkadot -d /home/polkadot -m -s /sbin/nologin \
-c "User account for running polkadot as a service" polkadot
if [ ! -e "$config_file" ]; then
echo 'POLKADOT_CLI_ARGS=""' > /etc/default/polkadot
fi
exit 0
%clean
rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
%{_bindir}/*
/usr/lib/systemd/system/polkadot.service
-28
View File
@@ -1,28 +0,0 @@
# Request an environment that provides sudo (that goes with larger containers)
# and a minimal language environment.
sudo: true
language: minimal
cache: cargo
branches:
only:
- master
env:
global:
- RUST_BACKTRACE=1
matrix:
- RUST_TOOLCHAIN=nightly TARGET=wasm
- RUST_TOOLCHAIN=stable TARGET=native
before_install:
# Check how much space we've got on this machine.
- df -h
script:
- ./ci/script.sh
after_script:
# Check how much free disk space left after the build
- df -h
-47
View File
@@ -1,47 +0,0 @@
# Using Parity Bridges Common dependency (`git subtree`).
In `./bridges` sub-directory you can find a `git subtree` imported version of:
[parity-bridges-common](https://github.com/paritytech/parity-bridges-common/) repository.
# How to fix broken Bridges code?
To fix Bridges code simply create a commit in current (`polkadot`) repo. Best if
the commit is isolated to changes in `./bridges` sub-directory, because it makes
it easier to import that change back to upstream repo.
# How to pull latest Bridges code or contribute back?
Note that it's totally fine to ping the Bridges Team to do that for you. The point
of adding the code as `git subtree` is to **reduce maintenance cost** for Polkadot
developers.
If you still would like to either update the code to match latest code from the repo
or create an upstream PR read below. The following commands should be run in the
current (`polkadot`) repo.
1. Add Bridges repo as a local remote:
```
$ git remote add -f bridges git@github.com:paritytech/parity-bridges-common.git
```
If you plan to contribute back, consider forking the repository on Github and adding
your personal fork as a remote as well.
```
$ git remote add -f my-bridges git@github.com:tomusdrw/parity-bridges-common.git
```
2. To update Bridges:
```
$ git fetch bridges master
$ git subtree pull --prefix=bridges bridges master --squash
````
We use `--squash` to avoid adding individual commits and rather squashing them
all into one.
3. Contributing back to Bridges (creating upstream PR)
```
$ git subtree push --prefix=bridges my-bridges master
```
This command will push changes to your personal fork of Bridges repo, from where
you can simply create a PR to the main repo.
+40 -12
View File
@@ -2,7 +2,11 @@
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
In the interest of fostering an open and welcoming environment, we as contributors and maintainers
pledge to making participation in our project and our community a harassment-free experience for
everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity
and expression, level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
@@ -19,34 +23,58 @@ Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Publishing others' private information, such as a physical or electronic address, without explicit
permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
### Facilitation, Not Strongarming
We recognise that this software is merely a tool for users to create and maintain their blockchain of preference. We see that blockchains are naturally community platforms with users being the ultimate decision makers. We assert that good software will maximise user agency by facilitate user-expression on the network. As such:
We recognise that this software is merely a tool for users to create and maintain their blockchain
of preference. We see that blockchains are naturally community platforms with users being the
ultimate decision makers. We assert that good software will maximise user agency by facilitate
user-expression on the network. As such:
* This project will strive to give users as much choice as is both reasonable and possible over what protocol they adhere to; but
* use of the project's technical forums, commenting systems, pull requests and issue trackers as a means to express individual protocol preferences is forbidden.
- This project will strive to give users as much choice as is both reasonable and possible over what
protocol they adhere to; but
- use of the project's technical forums, commenting systems, pull requests and issue trackers as a
means to express individual protocol preferences is forbidden.
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers are responsible for clarifying the standards of acceptable behavior and are
expected to take appropriate and fair corrective action in response to any instances of unacceptable
behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits,
code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or
to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
This Code of Conduct applies both within project spaces and in public spaces when an individual is
representing the project or its community. Examples of representing a project or community include
using an official project e-mail address, posting via an official social media account, or acting as
an appointed representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at <admin@parity.io>. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting
the project team at admin@parity.io. All complaints will be reviewed and investigated and will
result in a response that is deemed necessary and appropriate to the circumstances. The project team
is obligated to maintain confidentiality with regard to the reporter of an incident. Further
details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face
temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://contributor-covenant.org/version/1/4
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at
https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://contributor-covenant.org
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
-52
View File
@@ -1,52 +0,0 @@
# Contributing
`Substrate` projects is a **OPENISH Open Source Project**
## What?
Individuals making significant and valuable contributions are given commit-access to a project to contribute as they see fit. A project is more like an open wiki than a standard guarded open source project.
## Rules
There are a few basic ground-rules for contributors (including the maintainer(s) of the project):
- **No `--force` pushes** or modifying the Git history in any way. If you need to rebase, ensure you do it in your own repo.
- **Non-master branches**, prefixed with a short name moniker (e.g. `gav-my-feature`) must be used for ongoing work.
- **All modifications** must be made in a **pull-request** to solicit feedback from other contributors.
- A pull-request _must not be merged until CI_ has finished successfully.
- Contributors should adhere to the [house coding style](https://github.com/paritytech/polkadot/wiki/Style-Guide).
#### Merging pull requests once CI is successful:
- A pull request that does not alter any logic (e.g. comments, dependencies, docs) may be tagged [`insubstantial`](https://github.com/paritytech/substrate/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+label%3AA2-insubstantial) and merged by its author.
- A pull request with no large change to logic that is an urgent fix may be merged after a non-author contributor has reviewed it well.
- All other PRs should sit for 48 hours with the [`pleasereview`](https://github.com/paritytech/substrate/pulls?q=is%3Apr+is%3Aopen+label%3AA0-pleasereview) tag in order to garner feedback.
- No PR should be merged until all reviews' comments are addressed.
#### Reviewing pull requests:
When reviewing a pull request, the end-goal is to suggest useful changes to the author. Reviews should finish with approval unless there are issues that would result in:
- Buggy behaviour.
- Undue maintenance burden.
- Breaking with house coding style.
- Pessimisation (i.e. reduction of speed as measured in the projects benchmarks).
- Feature reduction (i.e. it removes some aspect of functionality that a significant minority of users rely on).
- Uselessness (i.e. it does not strictly add a feature or fix a known issue).
#### Reviews may not be used as an effective veto for a PR because:
- There exists a somewhat cleaner/better/faster way of accomplishing the same feature/fix.
- It does not fit well with some other contributors' longer-term vision for the project.
## Releases
Declaring formal releases remains the prerogative of the project maintainer(s).
## Changes to this arrangement
This is an experiment and feedback is welcome! This document may also be subject to pull-requests or changes by contributors where you believe you have something valuable to add or change.
## Heritage
These contributing guidelines are modified from the "OPEN Open Source Project" guidelines for the Level project: https://github.com/Level/community/blob/master/CONTRIBUTING.md
+4541 -3688
View File
File diff suppressed because it is too large Load Diff
+8 -129
View File
@@ -1,132 +1,11 @@
[[bin]]
name = "polkadot"
path = "src/main.rs"
[package]
name = "polkadot"
description = "Implementation of a https://polkadot.network node in Rust based on the Substrate framework."
license = "GPL-3.0-only"
version = "0.9.7"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
readme = "README.md"
[dependencies]
polkadot-cli = { path = "cli", features = [ "kusama-native", "westend-native", "rococo-native" ] }
color-eyre = { version = "0.5.11", default-features = false }
parity-util-mem = { version = "*", default-features = false, features = ["jemalloc-global"] }
[dev-dependencies]
assert_cmd = "1.0.2"
nix = "0.19.1"
tempfile = "3.2.0"
[workspace]
resolver = "2"
members = [
"cli",
"core-primitives",
"erasure-coding",
"primitives",
"runtime/common",
"runtime/common/slot_range_helper",
"runtime/parachains",
"runtime/polkadot",
"runtime/kusama",
"runtime/rococo",
"runtime/westend",
"runtime/test-runtime",
"statement-table",
"xcm",
"xcm/xcm-builder",
"xcm/xcm-executor",
"xcm/pallet-xcm",
"node/client",
"node/collation-generation",
"node/core/approval-voting",
"node/core/av-store",
"node/core/backing",
"node/core/bitfield-signing",
"node/core/candidate-validation",
"node/core/chain-api",
"node/core/chain-selection",
"node/core/dispute-coordinator",
"node/core/dispute-participation",
"node/core/parachains-inherent",
"node/core/provisioner",
"node/core/pvf",
"node/core/runtime-api",
"node/network/approval-distribution",
"node/network/bridge",
"node/network/protocol",
"node/network/statement-distribution",
"node/network/bitfield-distribution",
"node/network/availability-distribution",
"node/network/availability-recovery",
"node/network/collator-protocol",
"node/network/gossip-support",
"node/overseer",
"node/malus",
"node/primitives",
"node/service",
"node/subsystem",
"node/subsystem/dispatch-gen",
"node/subsystem-test-helpers",
"node/subsystem-util",
"node/jaeger",
"node/metered-channel",
"node/test/client",
"node/test/service",
"parachain/test-parachains",
"parachain/test-parachains/adder",
"parachain/test-parachains/adder/collator",
"bin/*/node",
"bin/*/runtime",
"fuzz/*",
"modules/*",
"primitives/*",
"relays/*",
]
# We want to be able to build the bridge relayer without pulling it (and all of its
# dependencies into the Polkadot workspace)
exclude = ["bridges/relays/bin-substrate", "bridges/bin/rialto/runtime", "bridges/bin/millau/runtime"]
[badges]
maintenance = { status = "actively-developed" }
# make sure dev builds with backtrace do
# not slow us down
[profile.dev.package.backtrace]
opt-level = 3
[profile.release]
# Polkadot runtime requires unwinding.
panic = "unwind"
[features]
runtime-benchmarks= [ "polkadot-cli/runtime-benchmarks" ]
try-runtime = [ "polkadot-cli/try-runtime" ]
# Configuration for building a .deb package - for use with `cargo-deb`
[package.metadata.deb]
name = "polkadot"
extended-description = "Implementation of a https://polkadot.network node in Rust based on the Substrate framework."
section = "misc"
maintainer = "martin@parity.io"
license-file = ["LICENSE", "0"]
# https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
maintainer-scripts = "scripts/packaging/deb-maintainer-scripts"
assets = [
["target/release/polkadot", "/usr/bin/", "755"],
["scripts/packaging/polkadot.service", "/lib/systemd/system/", "644"]
]
conf-files = [
"/etc/default/polkadot"
]
# Configuration for building an .rpm package - for use with `cargo-rpm`
[package.metadata.rpm]
package = "polkadot"
[package.metadata.rpm.cargo]
buildflags = ["--release"]
[package.metadata.rpm.targets]
polkadot = { path = "/usr/bin/polkadot" }
[package.metadata.rpm.files]
"../scripts/packaging/polkadot.service" = { path = "/usr/lib/systemd/system/polkadot.service", mode = "644" }
-15
View File
@@ -1,15 +0,0 @@
[{
"project_name": "Batch: Availability and Validity",
"owner": "rphmeier",
"matrix_room_id": "!wQXGIDhhJQSVXKqPwi:matrix.parity.io"
},
{
"project_name": "Batch: Codebase Restructure",
"owner": "rphmeier",
"matrix_room_id": "!wQXGIDhhJQSVXKqPwi:matrix.parity.io"
},
{
"project_name": "Cumulus",
"owner": "bkchr",
"matrix_room_id": "!wQXGIDhhJQSVXKqPwi:matrix.parity.io"
}]
+200 -204
View File
@@ -1,252 +1,248 @@
# Polkadot
# Parity Bridges Common
Implementation of a https://polkadot.network node in Rust based on the Substrate framework.
This is a collection of components for building bridges.
> **NOTE:** In 2018, we split our implementation of "Polkadot" from its development framework
> "Substrate". See the [Substrate][substrate-repo] repo for git history prior to 2018.
These components include Substrate pallets for syncing headers, passing arbitrary messages, as well
as libraries for building relayers to provide cross-chain communication capabilities.
[substrate-repo]: https://github.com/paritytech/substrate
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.
This repo contains runtimes for the Polkadot, Kusama, and Westend networks. The README provides
information about installing the `polkadot` binary and developing on the codebase. For more
specific guides, like how to be a validator, see the
[Polkadot Wiki](https://wiki.polkadot.network/docs/en/).
🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧
## Contents
- [Installation](#installation)
- [High-Level Architecture](#high-level-architecture)
- [Project Layout](#project-layout)
- [Running the Bridge](#running-the-bridge)
- [How to send a message](#how-to-send-a-message)
- [Community](#community)
## Installation
If you just wish to run a Polkadot node without compiling it yourself, you may
either run the latest binary from our
[releases](https://github.com/paritytech/polkadot/releases) page, or install
Polkadot from one of our package repositories.
Installation from the debian or rpm repositories will create a `systemd`
service that can be used to run a Polkadot node. This is disabled by default,
and can be started by running `systemctl start polkadot` on demand (use
`systemctl enable polkadot` to make it auto-start after reboot). By default, it
will run as the `polkadot` user. Command-line flags passed to the binary can
be customized by editing `/etc/default/polkadot`. This file will not be
overwritten on updating polkadot. You may also just run the node directly from
the command-line.
### Debian-based (Debian, Ubuntu)
Currently supports Debian 10 (Buster) and Ubuntu 20.04 (Focal), and
derivatives. Run the following commands as the `root` user.
```
# Import the security@parity.io GPG key
gpg --recv-keys --keyserver hkps://keys.mailvelope.com 9D4B2B6EB8F97156D19669A9FF0812D491B96798
gpg --export 9D4B2B6EB8F97156D19669A9FF0812D491B96798 > /usr/share/keyrings/parity.gpg
# Add the Parity repository and update the package index
echo 'deb [signed-by=/usr/share/keyrings/parity.gpg] https://releases.parity.io/deb release main' > /etc/apt/sources.list.d/parity.list
apt update
# Install the `parity-keyring` package - This will ensure the GPG key
# used by APT remains up-to-date
apt install parity-keyring
# Install polkadot
apt install polkadot
```
### RPM-based (Fedora, CentOS)
Currently supports Fedora 32 and CentOS 8, and derivatives.
```
# Install dnf-plugins-core (This might already be installed)
dnf install dnf-plugins-core
# Add the repository and enable it
dnf config-manager --add-repo https://releases.parity.io/rpm/polkadot.repo
dnf config-manager --set-enabled polkadot
# Install polkadot (You may have to confirm the import of the GPG key, which
# should have the following fingerprint: 9D4B2B6EB8F97156D19669A9FF0812D491B96798)
dnf install polkadot
```
## Building
### Install via Cargo
Make sure you have the support software installed from the **Build from Source** section
below this section.
If you want to install Polkadot in your PATH, you can do so with with:
To get up and running you need both stable and nightly Rust. Rust nightly is used to build the Web
Assembly (WASM) runtime for the node. You can configure the WASM support as so:
```bash
cargo install --git https://github.com/paritytech/polkadot --tag <version> polkadot --locked
rustup install nightly
rustup target add wasm32-unknown-unknown --toolchain nightly
```
### Build from Source
Once this is configured you can build and test the repo as follows:
If you'd like to build from source, first install Rust. You may need to add Cargo's bin directory
to your PATH environment variable. Restarting your computer will do this for you automatically.
```bash
curl https://sh.rustup.rs -sSf | sh
```
If you already have Rust installed, make sure you're using the latest version by running:
```bash
rustup update
```
Once done, finish installing the support software:
```bash
sudo apt install build-essential git clang libclang-dev pkg-config libssl-dev
```
Build the client by cloning this repository and running the following commands from the root
directory of the repo:
```bash
git checkout <latest tagged release>
./scripts/init.sh
cargo build --release
```
Note that compilation is a memory intensive process. We recommend having 4 GiB of physical RAM or swap available (keep in mind that if a build hits swap it tends to be very slow).
## Networks
This repo supports runtimes for Polkadot, Kusama, and Westend.
### Connect to Polkadot Mainnet
Connect to the global Polkadot Mainnet network by running:
```bash
./target/release/polkadot --chain=polkadot
```
You can see your node on [telemetry] (set a custom name with `--name "my custom name"`).
[telemetry]: https://telemetry.polkadot.io/#list/Polkadot
### Connect to the "Kusama" Canary Network
Connect to the global Kusama canary network by running:
```bash
./target/release/polkadot --chain=kusama
```
You can see your node on [telemetry] (set a custom name with `--name "my custom name"`).
[telemetry]: https://telemetry.polkadot.io/#list/Kusama
### Connect to the Westend Testnet
Connect to the global Westend testnet by running:
```bash
./target/release/polkadot --chain=westend
```
You can see your node on [telemetry] (set a custom name with `--name "my custom name"`).
[telemetry]: https://telemetry.polkadot.io/#list/Westend
### Obtaining DOTs
If you want to do anything on Polkadot, Kusama, or Westend, then you'll need to get an account and
some DOT, KSM, or WND tokens, respectively. See the
[claims instructions](https://claims.polkadot.network/) for Polkadot if you have DOTs to claim. For
Westend's WND tokens, see the faucet
[instructions](https://wiki.polkadot.network/docs/en/learn-DOT#getting-westies) on the Wiki.
## Hacking on Polkadot
If you'd actually like to hack on Polkadot, you can grab the source code and build it. Ensure you have
Rust and the support software installed. This script will install or update Rust and install the
required dependencies (this may take up to 30 minutes on Mac machines):
```bash
curl https://getsubstrate.io -sSf | bash -s -- --fast
```
Then, grab the Polkadot source code:
```bash
git clone https://github.com/paritytech/polkadot.git
cd polkadot
```
Then build the code. You will need to build in release mode (`--release`) to start a network. Only
use debug mode for development (faster compile times for development and testing).
```bash
./scripts/init.sh # Install WebAssembly. Update Rust
cargo build # Builds all native code
```
You can run the tests if you like:
```bash
git clone https://github.com/paritytech/parity-bridges-common.git
cd parity-bridges-common
cargo build --all
cargo test --all
```
You can start a development chain with:
Also you can build the repo with
[Parity CI Docker image](https://github.com/paritytech/scripts/tree/master/dockerfiles/bridges-ci):
```bash
cargo run -- --dev
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
```
Detailed logs may be shown by running the node with the following environment variables set:
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.
## High-Level Architecture
This repo has support for bridging foreign chains together using a combination of Substrate pallets
and external processes called relayers. A bridge chain is one that is able to follow the consensus
of a foreign chain independently. For example, consider the case below where we want to bridge two
Substrate based chains.
```
+---------------+ +---------------+
| | | |
| Rialto | | Millau |
| | | |
+-------+-------+ +-------+-------+
^ ^
| +---------------+ |
| | | |
+-----> | Bridge Relay | <-------+
| |
+---------------+
```
The Millau chain must be able to accept Rialto headers and verify their integrity. It does this by
using a runtime module designed to track GRANDPA finality. Since two blockchains can't interact
directly they need an external service, called a relayer, to communicate. The relayer will subscribe
to new Rialto headers via RPC and submit them to the Millau chain for verification.
Take a look at [Bridge High Level Documentation](./docs/high-level-overview.md) for more in-depth
description of the bridge interaction.
## Project Layout
Here's an overview of how the project is laid out. The main bits are the `node`, which is the actual
"blockchain", the `modules` which are used to build the blockchain's logic (a.k.a the runtime) and
the `relays` which are used to pass messages between chains.
```
├── bin // Node and Runtime for the various Substrate chains
│ └── ...
├── deployments // Useful tools for deploying test networks
│ └── ...
├── 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
│ └── ...
├── primitives // Code shared between modules, runtimes, and relays
│ └── ...
├── relays // Application for sending headers and messages between chains
│ └── ...
└── scripts // Useful development and maintenance scripts
```
## Running the Bridge
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 2 ways to run the bridge, described below:
- building & running from source
- running a Docker Compose setup (recommended).
### Using the Source
First you'll need to build the bridge nodes and relay. This can be done as follows:
```bash
RUST_LOG=debug RUST_BACKTRACE=1 cargo run----dev
# In `parity-bridges-common` folder
cargo build -p rialto-bridge-node
cargo build -p millau-bridge-node
cargo build -p substrate-relay
```
### Development
### Running a Dev network
You can run a simple single-node development "network" on your machine by running:
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
polkadot --dev
# In `parity-bridges-common` folder
./deployments/local-scripts/run-rialto-node.sh
./deployments/local-scripts/run-millau-node.sh
```
You can muck around by heading to https://polkadot.js.org/apps and choose "Local Node" from the
Settings menu.
### Local Two-node Testnet
If you want to see the multi-node consensus algorithm in action locally, then you can create a
local testnet. You'll need two terminals open. In one, run:
After the nodes are up we can run the header relayers.
```bash
polkadot --chain=polkadot-local --alice -d /tmp/alice
./deployments/local-scripts/relay-millau-to-rialto.sh
./deployments/local-scripts/relay-rialto-to-millau.sh
```
And in the other, run:
At this point you should see the relayer submitting headers from the Millau Substrate chain to the
Rialto Substrate chain.
```
# 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
```
Finally, we can run the message relayers.
```bash
polkadot --chain=polkadot-local --bob -d /tmp/bob --port 30334 --bootnodes '/ip4/127.0.0.1/tcp/30333/p2p/ALICE_BOOTNODE_ID_HERE'
./deployments/local-scripts/relay-messages-millau-to-rialto.sh
./deployments/local-scripts/relay-messages-rialto-to-millau.sh
```
Ensure you replace `ALICE_BOOTNODE_ID_HERE` with the node ID from the output of the first terminal.
You will also see the message lane relayers listening for new messages.
### Using Docker
[Using Docker](doc/docker.md)
```
# 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...) }
```
### Shell Completion
[Shell Completion](doc/shell-completion.md)
To send a message see the ["How to send a message" section](#how-to-send-a-message).
## Contributing
### Full Network Docker Compose Setup
### Contributing Guidelines
For a more sophisticated deployment which includes bidirectional header sync, message passing,
monitoring dashboards, etc. see the [Deployments README](./deployments/README.md).
[Contribution Guidelines](CONTRIBUTING.md)
You should note that you can find images for all the bridge components published on
[Docker Hub](https://hub.docker.com/u/paritytech).
### Contributor Code of Conduct
To run a Rialto node for example, you can use the following command:
[Code of Conduct](CODE_OF_CONDUCT.md)
```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
```
## License
### How to send a message
Polkadot is [GPL 3.0 licensed](LICENSE).
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)
## Important Notice
```bash
# In `parity-bridges-common` folder
./scripts/send-message-from-millau-rialto.sh remark
```
https://polkadot.network/testnetdisclaimer
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
Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat
server like, for example, Discord. Most discussions around Polkadot and Substrate happen
in various Element "rooms" (channels). So, joining Element might be a good idea, anyway.
If you are interested in information exchange and development of Polkadot related bridges please
feel free to join the [Polkadot Bridges](https://app.element.io/#/room/#bridges:web3.foundation)
Element channel.
The [Substrate Technical](https://app.element.io/#/room/#substrate-technical:matrix.org) Element
channel is most suited for discussions regarding Substrate itself.
-56
View File
@@ -1,56 +0,0 @@
Polkadot Release Process
------------------------
### Branches
* release-candidate branch: The branch used for staging of the next release.
Named like `release-v0.8.26`
* release branch: The branch to which successful release-candidates are merged
and tagged with the new version. Named literally `release`.
### Notes
* The release-candidate branch *must* be made in the paritytech/polkadot repo in
order for release automation to work correctly
* Any new pushes/merges to the release-candidate branch (for example,
refs/heads/release-v0.8.26) will result in the rc index being bumped (e.g., v0.8.26-rc1
to v0.8.26-rc2) and new wasms built.
### Release workflow
Below are the steps of the release workflow. Steps prefixed with NOACTION are
automated and require no human action.
1. To initiate the release process, branch master off to a release branch and push it to Github:
- `git checkout master; git pull; git checkout -b release-v0.8.26; git push origin refs/heads/release-v0.8.26`
2. NOACTION: The current HEAD of the release-candidate branch is tagged `v0.8.26-rc1`
3. NOACTION: A draft release and runtime WASMs are created for this
release-candidate automatically. A link to the draft release will be linked in
the internal polkadot matrix channel.
4. NOACTION: A new Github issue is created containing a checklist of manual
steps to be completed before we are confident with the release. This will be
linked in Matrix.
5. Complete the steps in the issue created in step 4, signing them off as
completed
6. (optional) If a fix is required to the release-candidate:
1. Merge the fix with `master` first
2. Cherry-pick the commit from `master` to `release-v0.8.26`, fixing any
merge conflicts. Try to avoid unnecessarily bumping crates.
3. Push the release-candidate branch to Github - this is now the new release-
candidate
4. Depending on the cherry-picked changes, it may be necessary to perform some
or all of the manual tests again.
7. Once happy with the release-candidate, perform the release using the release
script located at `scripts/release.sh` (or perform the steps in that script
manually):
- `./scripts/release.sh v0.8.26`
8. NOACTION: The HEAD of the `release` branch will be tagged with `v0.8.26`,
and a final draft release will be created on Github.
### Security releases
Occasionally there may be changes that need to be made to the most recently
released version of Polkadot, without taking *every* change to `master` since
the last release. For example, in the event of a security vulnerability being
found, where releasing a fixed version is a matter of some expediency. In cases
like this, the fix should first be merged with master, cherry-picked to a branch
forked from `release`, tested, and then finally merged with `release`. A
sensible versioning scheme for changes like this is `vX.Y.Z-1`.
-101
View File
@@ -1,101 +0,0 @@
# Security Policy
Parity Technologies is committed to resolving security vulnerabilities in our software quickly and carefully. We take the necessary steps to minimize risk, provide timely information, and deliver vulnerability fixes and mitigations required to address security issues.
## Reporting a Vulnerability
Security vulnerabilities in Parity software should be reported by email to security@parity.io. If you think your report might be eligible for the Parity Bug Bounty Program, your email should be sent to bugbounty@parity.io.
Your report should include the following:
- your name
- description of the vulnerability
- attack scenario (if any)
- components
- reproduction
- other details
Try to include as much information in your report as you can, including a description of the vulnerability, its potential impact, and steps for reproducing it. Be sure to use a descriptive subject line.
You'll receive a response to your email within two business days indicating the next steps in handling your report. We encourage finders to use encrypted communication channels to protect the confidentiality of vulnerability reports. You can encrypt your report using our public key. This key is [on MIT's key server](https://pgp.mit.edu/pks/lookup?op=get&search=0x5D0F03018D07DE73) server and reproduced below.
After the initial reply to your report, our team will endeavor to keep you informed of the progress being made towards a fix. These updates will be sent at least every five business days.
Thank you for taking the time to responsibly disclose any vulnerabilities you find.
## Responsible Investigation and Reporting
Responsible investigation and reporting includes, but isn't limited to, the following:
- Don't violate the privacy of other users, destroy data, etc.
- Dont defraud or harm Parity Technologies Ltd or its users during your research; you should make a good faith effort to not interrupt or degrade our services.
- Don't target our physical security measures, or attempt to use social engineering, spam, distributed denial of service (DDOS) attacks, etc.
- Initially report the bug only to us and not to anyone else.
- Give us a reasonable amount of time to fix the bug before disclosing it to anyone else, and give us adequate written warning before disclosing it to anyone else.
- In general, please investigate and report bugs in a way that makes a reasonable, good faith effort not to be disruptive or harmful to us or our users. Otherwise your actions might be interpreted as an attack rather than an effort to be helpful.
## Bug Bounty Program
Our Bug Bounty Program allows us to recognise and reward members of the Parity community for helping us find and address significant bugs, in accordance with the terms of the Parity Bug Bounty Program. A detailed description on eligibility, rewards, legal information and terms & conditions for contributors can be found on [our website](https://paritytech.io/bug-bounty.html).
## Plaintext PGP Key
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBF0vHwQBEADKui4qAo4bzdzRhMm+uhUpYGf8jjjmET3zJ8kKQIpp6JTsV+HJ
6m1We0QYeMRXoOYH1xVHBf2zNCuHS0nSQdUCQA7SHWsPB05STa2hvlR7fSdQnCCp
gnLOJWXvvedlRDIAhvqI6cwLdUlXgVSKEwrwmrpiBhh4NxI3qX+LyIa+Ovkchu2S
d/YCnE4GqojSGRfJYiGwe2N+sF7OfaoKhQuTrtdDExHrMU4cWnTXW2wyxTr4xkj9
jS2WeLVZWflvkDHT8JD9N6jNxBVEF/Qvjk83zI0kCOzkhek8x+YUgfLq3/rHOYbX
3pW21ccHYPacHjHWvKE+xRebjeEhJ4KxKHfCVjQcxybwDBqDka1AniZt4CQ7UORf
MU/ue2oSZ9nNg0uMdb/0AbQPZ04OlMcYPAPWzFL08nVPox9wT9uqlL6JtcOeC90h
oOeDmfgwmjMmdwWTRgt9qQjcbgXzVvuAzIGbzj1X3MdLspWdHs/d2+US4nji1TkN
oYIW7vE+xkd3aB+NZunIlm9Rwd/0mSgDg+DaNa5KceOLhq0/qKgcXC/RRU29I8II
tusRoR/oesGJGYTjh4k6PJkG+nvDPsoQrwYT44bhnniS1xYkxWYXF99JFI7LgMdD
e1SgKeIDVpvm873k82E6arp5655Wod1XOjaXBggCwFp84eKcEZEN+1qEWwARAQAB
tClQYXJpdHkgU2VjdXJpdHkgVGVhbSA8c2VjdXJpdHlAcGFyaXR5LmlvPokCVAQT
AQoAPhYhBJ1LK264+XFW0ZZpqf8IEtSRuWeYBQJdLx8EAhsDBQkDwmcABQsJCAcC
BhUKCQgLAgQWAgMBAh4BAheAAAoJEP8IEtSRuWeYL84QAI6NwnwS561DWYYRAd4y
ocGPr3CnwFSt1GjkSkRy3B+tMhzexBg1y7EbLRUefIrO4LwOlywtRk8tTRGgEI4i
5xRLHbOkeolfgCFSpOj5d8cMKCt5HEIv18hsv6dkrzlSYA5NLX/GRBEh3F/0sGny
vCXapfxa1cx72sU7631JBK7t2Tf+MfwxdfyFZ9TI9WdtP5AfVjgTkIVkEDFcZPTc
n3CYXqTYFIBCNUD8LP4iTi3xUt7pTGJQQoFT8l15nJCgzRYQ+tXpoTRlf+/LtXmw
6iidPV87E06jHdK9666rBouIabAtx7i0/4kwo+bSZ8DiSKRUaehiHGd212HSEmdF
jxquWE4pEzoUowYznhSIfR+WWIqRBHxEYarP4m98Hi+VXZ7Fw1ytzO8+BAKnLXnj
2W2+T9qJks5gqVEoaWNnqpvya6JA11QZvZ0w7Om2carDc2ILNm2Xx9J0mRUye8P0
KxcgqJuKNGFtugebQAsXagkxOKsdKna1PlDlxEfTf6AgI3ST8qSiMAwaaIMB/REF
VKUapGoslQX4tOCjibI2pzEgE//D8NAaSVu2A9+BUcFERdZRxsI7fydIXNeZ2R46
N2qfW+DP3YR/14QgdRxDItEavUoE1vByRXwIufKAkVemOZzIoFXKFsDeXwqTVW5i
6CXu6OddZ3QHDiT9TEbRny4QuQINBF0vKCwBEACnP5J7LEGbpxNBrPvGdxZUo0YA
U8RgeKDRPxJTvMo27V1IPZGaKRCRq8LBfg/eHhqZhQ7SLJBjBljd8kuT5dHDBTRe
jE1UIOhmnlSlrEJjAmpVO08irlGpq1o+8mGcvkBsR0poCVjeNeSnwYfRnR+c3GK5
Er6/JRqfN4mJvnEC9/Pbm6C7ql6YLKxC3yqzF97JL5brbbuozrW7nixY/yAI8619
VlBIMP7PAUbGcnSQyuV5b/Wr2Sgr6NJclnNSLjh2U9/Du6w/0tDGlMBts8HjRnWJ
BXbkTdQKCTaqgK68kTKSiN1/x+lynxHC2AavMpH/08Kopg2ZCzJowMKIgcB+4Z/I
DJKZWHWKumhaZMGXcWgzgcByog9IpamuROEZFJNEUAFf7YIncEckPSif4looiOdS
VurKZGvYXXaGSsZbGgHxI5CWu7ZxMdLBLvtOcCYmRQrG+g/h+PGU5BT0bNAfNTkm
V3/n1B/TWbpWRmB3AwT2emQivXHkaubGI0VivhaO43AuI9JWoqiMqFtxbuTeoxwD
xlu2Dzcp0v+AR4T5cIG9D5/+yiPc25aIY7cIKxuNFHIDL4td5fwSGC7vU6998PIG
2Y48TGBnw7zpEfDfMayqAeBjX0YU6PTNsvS5O6bP3j4ojTOUYD7Z8QdCvgISDID3
WMGAdmSwmCRvsQ/OJwARAQABiQI8BBgBCgAmFiEEnUsrbrj5cVbRlmmp/wgS1JG5
Z5gFAl0vKCwCGwwFCQB2pwAACgkQ/wgS1JG5Z5hdbw//ZqR+JcWm59NUIHjauETJ
sYDYhcAfa3txTacRn5uPz/TQiTd7wZ82+G8Et0ZnpEHy6eWyBqHpG0hiPhFBzxjY
nhjHl8jJeyo2mQIVJhzkL58BHBZk8WM2TlaU7VxZ6TYOmP2y3qf6FD6mCcrQ4Fml
E9f0lyVUoI/5Zs9oF0izRk8vkwaY3UvLM7XEY6nM8GnFG8kaiZMYmx26Zo7Uz31G
7EGGZFsrVDXfNhSJyz79Gyn+Lx9jOTdoR0sH/THYIIosE83awMGE6jKeuDYTbVWu
+ZtHQef+pRteki3wvNLJK+kC1y3BtHqDJS9Lqx0s8SCiVozlC+fZfC9hCtU7bXJK
0UJZ4qjSvj6whzfaNgOZAqJpmwgOnd8W/3YJk1DwUeX98FcU38MR23SOkx2EDdDE
77Kdu62vTs/tLmOTuyKBvYPaHaYulYjQTxurG+o8vhHtaL87ARvuq+83dj+nO5z3
5O9vkcVJYWjOEnJe7ZvCTxeLJehpCmHIbyUuDx5P24MWVbyXOxIlxNxTqlub5GlW
rQF6Qsa/0k9TRk7Htbct6fAA0/VahJS0g096MrTH8AxBXDNE8lIoNeGikVlaxK9Z
S+aannlWYIJymZ4FygIPPaRlzhAoXBuJd8OaR5giC7dS1xquxKOiQEXTGsLeGFaI
BZYiIhW7GG4ozvKDqyNm4eg=
=yKcB
-----END PGP PUBLIC KEY BLOCK-----
```
@@ -10,14 +10,13 @@ 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" }
@@ -45,7 +44,6 @@ sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "mast
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-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 +54,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",
]
@@ -16,8 +16,9 @@
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, 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};
@@ -70,10 +71,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 +79,8 @@ impl Alternative {
);
match self {
Alternative::Development => ChainSpec::from_genesis(
"Development",
"dev",
"Millau Development",
"millau_dev",
sc_service::ChainType::Development,
|| {
testnet_genesis(
@@ -107,8 +105,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 +135,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"),
)),
@@ -191,12 +191,8 @@ fn testnet_genesis(
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() },
grandpa: GrandpaConfig { authorities: Vec::new() },
sudo: SudoConfig { key: root_key },
session: SessionConfig {
keys: initial_authorities
@@ -211,15 +207,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());
}
@@ -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.
@@ -14,9 +14,11 @@
// 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_service::PartialComponents;
@@ -75,19 +77,18 @@ pub fn run() -> sc_cli::Result<()> {
));
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,69 +96,53 @@ 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 {
@@ -167,6 +152,6 @@ pub fn run() -> sc_cli::Result<()> {
}
.map_err(sc_cli::Error::Service)
})
}
},
}
}
@@ -21,8 +21,8 @@
// =====================================================================================
// 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;
// 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 :)
// =====================================================================================
// =====================================================================================
@@ -31,8 +31,7 @@
use millau_runtime::{self, opaque::Block, RuntimeApi};
use sc_client_api::{ExecutorProvider, RemoteBackend};
use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams};
use sc_executor::native_executor_instance;
pub use sc_executor::NativeExecutor;
pub use sc_executor::NativeElseWasmExecutor;
use sc_keystore::LocalKeystore;
use sc_service::{error::Error as ServiceError, Configuration, TaskManager};
@@ -41,15 +40,25 @@ use sp_consensus::SlotData;
use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;
use std::{sync::Arc, time::Duration};
// Our native executor instance.
native_executor_instance!(
pub Executor,
millau_runtime::api::dispatch,
millau_runtime::native_version,
frame_benchmarking::benchmarking::HostFunctions,
);
type Executor = NativeElseWasmExecutor<ExecutorDispatch>;
type FullClient = sc_service::TFullClient<Block, RuntimeApi, Executor>;
// Our native executor instance.
pub struct ExecutorDispatch;
impl sc_executor::NativeExecutionDispatch for ExecutorDispatch {
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
millau_runtime::api::dispatch(method, data)
}
fn native_version() -> sc_executor::NativeVersion {
millau_runtime::native_version()
}
}
type FullClient =
sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;
type FullBackend = sc_service::TFullBackend<Block>;
type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
@@ -61,10 +70,15 @@ pub fn new_partial(
FullClient,
FullBackend,
FullSelectChain,
sp_consensus::DefaultImportQueue<Block, FullClient>,
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>,
),
@@ -72,7 +86,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("Remote Keystores are not supported.".to_string()))
}
let telemetry = config
@@ -86,10 +100,18 @@ 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, Executor>(
config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
executor,
)?;
let client = Arc::new(client);
let telemetry = telemetry.map(|(worker, telemetry)| {
@@ -116,26 +138,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,
@@ -172,32 +198,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());
let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new(
backend.clone(),
grandpa_link.shared_authority_set().clone(),
vec![],
));
let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
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,
on_demand: None,
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();
@@ -224,8 +258,10 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
let shared_authority_set = grandpa_link.shared_authority_set().clone();
let shared_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| {
let mut io = jsonrpc_core::IoHandler::default();
@@ -244,7 +280,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
subscription_executor,
finality_proof_provider.clone(),
)));
io
Ok(io)
})
};
@@ -272,37 +308,40 @@ 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,
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(
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.
@@ -311,11 +350,8 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
// if the node isn't actively participating in consensus then it doesn't
// 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 grandpa_config = sc_finality_grandpa::Config {
// FIXME #1578 make this available through chainspec
@@ -347,9 +383,10 @@ 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)?);
task_manager.spawn_essential_handle().spawn_blocking(
"grandpa-voter",
sc_finality_grandpa::run_grandpa_voter(grandpa_config)?,
);
}
network_starter.start_network();
@@ -369,10 +406,17 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
})
.transpose()?;
let executor = NativeElseWasmExecutor::<ExecutorDispatch>::new(
config.wasm_method,
config.default_heap_pages,
config.max_runtime_instances,
);
let (client, backend, keystore_container, mut task_manager, on_demand) =
sc_service::new_light_parts::<Block, RuntimeApi, Executor>(
&config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
executor,
)?;
let mut telemetry = telemetry.map(|(worker, telemetry)| {
@@ -380,10 +424,7 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
telemetry
});
config
.network
.extra_sets
.push(sc_finality_grandpa::grandpa_peers_set_config());
config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config());
let select_chain = sc_consensus::LongestChain::new(backend.clone());
@@ -404,39 +445,54 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
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 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,
);
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()),
})?;
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,
})?;
let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new(
backend.clone(),
grandpa_link.shared_authority_set().clone(),
vec![],
));
let (network, system_rpc_tx, network_starter) =
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
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,
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 enable_grandpa = !config.disable_grandpa;
@@ -464,7 +520,7 @@ pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError>
transaction_pool,
task_manager: &mut task_manager,
on_demand: Some(on_demand),
rpc_extensions_builder: Box::new(|_, _| ()),
rpc_extensions_builder: Box::new(|_, _| Ok(())),
config,
client,
keystore: keystore_container.sync_keystore(),
@@ -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,38 @@ 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 }
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-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" }
@@ -78,6 +81,7 @@ std = [
"pallet-bridge-dispatch/std",
"pallet-bridge-grandpa/std",
"pallet-bridge-messages/std",
"pallet-bridge-token-swap/std",
"pallet-grandpa/std",
"pallet-randomness-collective-flip/std",
"pallet-session/std",
@@ -86,6 +90,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 +106,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",
]
@@ -34,18 +34,21 @@ 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 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_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, NumberFor, OpaqueKeys},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, MultiSignature, MultiSigner,
ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
@@ -62,8 +65,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 +92,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;
@@ -139,10 +141,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! {
@@ -157,7 +156,7 @@ parameter_types! {
impl frame_system::Config for Runtime {
/// The basic call filter to use in dispatchable.
type BaseCallFilter = ();
type BaseCallFilter = frame_support::traits::Everything;
/// The identifier used to distinguish between accounts.
type AccountId = AccountId;
/// The aggregated dispatch type that is available for extrinsics.
@@ -207,14 +206,20 @@ impl frame_system::Config for Runtime {
impl pallet_randomness_collective_flip::Config for Runtime {}
parameter_types! {
pub const MaxAuthorities: u32 = 10;
}
impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
type MaxAuthorities = MaxAuthorities;
type DisabledValidators = ();
}
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 = ();
type CallFilter = frame_support::traits::Everything;
type EncodedCall = crate::rialto_messages::FromRialtoEncodedCall;
type SourceChainAccountId = bp_rialto::AccountId;
type TargetChainAccountPublic = MultiSigner;
@@ -226,12 +231,16 @@ 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;
}
parameter_types! {
@@ -239,7 +248,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;
@@ -273,13 +282,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 {
@@ -302,7 +323,6 @@ impl pallet_session::Config for Runtime {
type SessionManager = pallet_shift_session_manager::Pallet<Runtime>;
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys;
type DisabledValidatorsThreshold = ();
// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
type WeightInfo = ();
}
@@ -353,10 +373,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;
@@ -378,16 +399,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!(
@@ -396,20 +446,30 @@ 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},
// 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},
}
);
@@ -440,8 +500,13 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signatu
/// 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>;
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPallets,
>;
impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
@@ -460,7 +525,7 @@ impl_runtime_apis! {
impl sp_api::Metadata<Block> for Runtime {
fn metadata() -> OpaqueMetadata {
Runtime::metadata().into()
OpaqueMetadata::new(Runtime::metadata().into())
}
}
@@ -495,8 +560,9 @@ impl_runtime_apis! {
fn validate_transaction(
source: TransactionSource,
tx: <Block as BlockT>::Extrinsic,
block_hash: <Block as BlockT>::Hash,
) -> TransactionValidity {
Executive::validate_transaction(source, tx)
Executive::validate_transaction(source, tx, block_hash)
}
}
@@ -512,7 +578,7 @@ impl_runtime_apis! {
}
fn authorities() -> Vec<AuraId> {
Aura::authorities()
Aura::authorities().to_vec()
}
}
@@ -541,6 +607,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()
}
@@ -609,20 +679,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 {
@@ -647,6 +708,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.
@@ -688,6 +810,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(
@@ -697,21 +820,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" }
@@ -0,0 +1,22 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed};
fn main() {
generate_cargo_keys();
rerun_if_git_head_changed();
}
@@ -0,0 +1,165 @@
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use cumulus_primitives_core::ParaId;
use rialto_parachain_runtime::{AccountId, AuraId, Signature};
use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};
use sc_service::ChainType;
use serde::{Deserialize, Serialize};
use sp_core::{sr25519, Pair, Public};
use sp_runtime::traits::{IdentifyAccount, Verify};
/// Specialized `ChainSpec` for the normal parachain runtime.
pub type ChainSpec =
sc_service::GenericChainSpec<rialto_parachain_runtime::GenesisConfig, Extensions>;
/// Helper function to generate a crypto pair from seed
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
TPublic::Pair::from_string(&format!("//{}", seed), None)
.expect("static values are valid; qed")
.public()
}
/// The extensions for the [`ChainSpec`].
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)]
#[serde(deny_unknown_fields)]
pub struct Extensions {
/// The relay chain of the Parachain.
pub relay_chain: String,
/// The id of the Parachain.
pub para_id: u32,
}
impl Extensions {
/// Try to get the extension from the given `ChainSpec`.
pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> {
sc_chain_spec::get_extension(chain_spec.extensions())
}
}
type AccountPublic = <Signature as Verify>::Signer;
/// Helper function to generate an account ID from seed
pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
where
AccountPublic: From<<TPublic::Pair as Pair>::Public>,
{
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
}
pub fn development_config(id: ParaId) -> ChainSpec {
// Give your base currency a unit name and decimal places
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "UNIT".into());
properties.insert("tokenDecimals".into(), 12.into());
ChainSpec::from_genesis(
// Name
"Development",
// ID
"dev",
ChainType::Local,
move || {
testnet_genesis(
get_account_id_from_seed::<sr25519::Public>("Alice"),
vec![get_from_seed::<AuraId>("Alice"), get_from_seed::<AuraId>("Bob")],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
],
id,
)
},
vec![],
None,
None,
None,
Extensions {
relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
para_id: id.into(),
},
)
}
pub fn local_testnet_config(id: ParaId) -> ChainSpec {
// Give your base currency a unit name and decimal places
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "UNIT".into());
properties.insert("tokenDecimals".into(), 12.into());
ChainSpec::from_genesis(
// Name
"Local Testnet",
// ID
"local_testnet",
ChainType::Local,
move || {
testnet_genesis(
get_account_id_from_seed::<sr25519::Public>("Alice"),
vec![get_from_seed::<AuraId>("Alice"), get_from_seed::<AuraId>("Bob")],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
id,
)
},
Vec::new(),
None,
None,
None,
Extensions {
relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
para_id: id.into(),
},
)
}
fn testnet_genesis(
root_key: AccountId,
initial_authorities: Vec<AuraId>,
endowed_accounts: Vec<AccountId>,
id: ParaId,
) -> rialto_parachain_runtime::GenesisConfig {
rialto_parachain_runtime::GenesisConfig {
system: rialto_parachain_runtime::SystemConfig {
code: rialto_parachain_runtime::WASM_BINARY
.expect("WASM binary was not build, please build it!")
.to_vec(),
changes_trie_config: Default::default(),
},
balances: rialto_parachain_runtime::BalancesConfig {
balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(),
},
sudo: rialto_parachain_runtime::SudoConfig { key: root_key },
parachain_info: rialto_parachain_runtime::ParachainInfoConfig { parachain_id: id },
aura: rialto_parachain_runtime::AuraConfig { authorities: initial_authorities },
aura_ext: Default::default(),
// parachain_system: Default::default(),
}
}
@@ -0,0 +1,137 @@
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::chain_spec;
use std::path::PathBuf;
use structopt::StructOpt;
/// Sub-commands supported by the collator.
#[derive(Debug, StructOpt)]
pub enum Subcommand {
/// Export the genesis state of the parachain.
#[structopt(name = "export-genesis-state")]
ExportGenesisState(ExportGenesisStateCommand),
/// Export the genesis wasm of the parachain.
#[structopt(name = "export-genesis-wasm")]
ExportGenesisWasm(ExportGenesisWasmCommand),
/// Build a chain specification.
BuildSpec(sc_cli::BuildSpecCmd),
/// Validate blocks.
CheckBlock(sc_cli::CheckBlockCmd),
/// Export blocks.
ExportBlocks(sc_cli::ExportBlocksCmd),
/// Export the state of a given block into a chain spec.
ExportState(sc_cli::ExportStateCmd),
/// Import blocks.
ImportBlocks(sc_cli::ImportBlocksCmd),
/// Remove the whole chain.
PurgeChain(cumulus_client_cli::PurgeChainCmd),
/// Revert the chain to a previous state.
Revert(sc_cli::RevertCmd),
/// The custom benchmark subcommmand benchmarking runtime pallets.
#[structopt(name = "benchmark", about = "Benchmark runtime pallets.")]
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
}
/// Command for exporting the genesis state of the parachain
#[derive(Debug, StructOpt)]
pub struct ExportGenesisStateCommand {
/// Output file name or stdout if unspecified.
#[structopt(parse(from_os_str))]
pub output: Option<PathBuf>,
/// Id of the parachain this state is for.
///
/// Default: 100
#[structopt(long, conflicts_with = "chain")]
pub parachain_id: Option<u32>,
/// Write output in binary. Default is to write in hex.
#[structopt(short, long)]
pub raw: bool,
/// The name of the chain for that the genesis state should be exported.
#[structopt(long, conflicts_with = "parachain-id")]
pub chain: Option<String>,
}
/// Command for exporting the genesis wasm file.
#[derive(Debug, StructOpt)]
pub struct ExportGenesisWasmCommand {
/// Output file name or stdout if unspecified.
#[structopt(parse(from_os_str))]
pub output: Option<PathBuf>,
/// Write output in binary. Default is to write in hex.
#[structopt(short, long)]
pub raw: bool,
/// The name of the chain for that the genesis wasm file should be exported.
#[structopt(long)]
pub chain: Option<String>,
}
#[derive(Debug, StructOpt)]
#[structopt(settings = &[
structopt::clap::AppSettings::GlobalVersion,
structopt::clap::AppSettings::ArgsNegateSubcommands,
structopt::clap::AppSettings::SubcommandsNegateReqs,
])]
pub struct Cli {
#[structopt(subcommand)]
pub subcommand: Option<Subcommand>,
#[structopt(flatten)]
pub run: cumulus_client_cli::RunCmd,
/// Relaychain arguments
#[structopt(raw = true)]
pub relaychain_args: Vec<String>,
}
#[derive(Debug)]
pub struct RelayChainCli {
/// The actual relay chain cli object.
pub base: polkadot_cli::RunCmd,
/// Optional chain id that should be passed to the relay chain.
pub chain_id: Option<String>,
/// The base path that should be used by the relay chain.
pub base_path: Option<PathBuf>,
}
impl RelayChainCli {
/// Parse the relay chain CLI parameters using the para chain `Configuration`.
pub fn new<'a>(
para_config: &sc_service::Configuration,
relay_chain_args: impl Iterator<Item = &'a String>,
) -> Self {
let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec);
let chain_id = extension.map(|e| e.relay_chain.clone());
let base_path = para_config.base_path.as_ref().map(|x| x.path().join("rialto-bridge-node"));
Self { base_path, chain_id, base: polkadot_cli::RunCmd::from_iter(relay_chain_args) }
}
}
@@ -0,0 +1,424 @@
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::{
chain_spec,
cli::{Cli, RelayChainCli, Subcommand},
service::{new_partial, ParachainRuntimeExecutor},
};
use codec::Encode;
use cumulus_client_service::genesis::generate_genesis_block;
use cumulus_primitives_core::ParaId;
use log::info;
use polkadot_parachain::primitives::AccountIdConversion;
use rialto_parachain_runtime::{Block, RuntimeApi};
use sc_cli::{
ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams,
NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli,
};
use sc_service::config::{BasePath, PrometheusConfig};
use sp_core::hexdisplay::HexDisplay;
use sp_runtime::traits::Block as BlockT;
use std::{io::Write, net::SocketAddr};
fn load_spec(
id: &str,
para_id: ParaId,
) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
Ok(match id {
"dev" => Box::new(chain_spec::development_config(para_id)),
"" | "local" => Box::new(chain_spec::local_testnet_config(para_id)),
path => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?),
})
}
impl SubstrateCli for Cli {
fn impl_name() -> String {
"Parachain Collator Template".into()
}
fn impl_version() -> String {
env!("SUBSTRATE_CLI_IMPL_VERSION").into()
}
fn description() -> String {
format!(
"Parachain Collator Template\n\nThe command-line arguments provided first will be \
passed to the parachain node, while the arguments provided after -- will be passed \
to the relaychain node.\n\n\
{} [parachain-args] -- [relaychain-args]",
Self::executable_name()
)
}
fn author() -> String {
env!("CARGO_PKG_AUTHORS").into()
}
fn support_url() -> String {
"https://github.com/substrate-developer-hub/substrate-parachain-template/issues/new".into()
}
fn copyright_start_year() -> i32 {
2017
}
fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
load_spec(id, self.run.parachain_id.unwrap_or(2000).into())
}
fn native_runtime_version(_: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {
&rialto_parachain_runtime::VERSION
}
}
impl SubstrateCli for RelayChainCli {
fn impl_name() -> String {
"Parachain Collator Template".into()
}
fn impl_version() -> String {
env!("SUBSTRATE_CLI_IMPL_VERSION").into()
}
fn description() -> String {
"Parachain Collator Template\n\nThe command-line arguments provided first will be \
passed to the parachain node, while the arguments provided after -- will be passed \
to the relaychain node.\n\n\
parachain-collator [parachain-args] -- [relaychain-args]"
.into()
}
fn author() -> String {
env!("CARGO_PKG_AUTHORS").into()
}
fn support_url() -> String {
"https://github.com/substrate-developer-hub/substrate-parachain-template/issues/new".into()
}
fn copyright_start_year() -> i32 {
2017
}
fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
polkadot_cli::Cli::from_iter([RelayChainCli::executable_name()].iter()).load_spec(id)
}
fn native_runtime_version(chain_spec: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {
polkadot_cli::Cli::native_runtime_version(chain_spec)
}
}
fn extract_genesis_wasm(chain_spec: &dyn sc_service::ChainSpec) -> Result<Vec<u8>> {
let mut storage = chain_spec.build_storage()?;
storage
.top
.remove(sp_core::storage::well_known_keys::CODE)
.ok_or_else(|| "Could not find wasm file in genesis state!".into())
}
macro_rules! construct_async_run {
(|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{
let runner = $cli.create_runner($cmd)?;
runner.async_run(|$config| {
let $components = new_partial::<
RuntimeApi,
ParachainRuntimeExecutor,
_
>(
&$config,
crate::service::parachain_build_import_queue,
)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
}}
}
/// Parse command line arguments into service configuration.
pub fn run() -> Result<()> {
let cli = Cli::from_args();
sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::Custom(
rialto_parachain_runtime::SS58Prefix::get() as u16,
));
match &cli.subcommand {
Some(Subcommand::BuildSpec(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
},
Some(Subcommand::CheckBlock(cmd)) => {
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, components.import_queue))
})
},
Some(Subcommand::ExportBlocks(cmd)) => {
construct_async_run!(|components, cli, cmd, config| Ok(
cmd.run(components.client, config.database)
))
},
Some(Subcommand::ExportState(cmd)) => {
construct_async_run!(|components, cli, cmd, config| Ok(
cmd.run(components.client, config.chain_spec)
))
},
Some(Subcommand::ImportBlocks(cmd)) => {
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, components.import_queue))
})
},
Some(Subcommand::PurgeChain(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| {
let polkadot_cli = RelayChainCli::new(
&config,
[RelayChainCli::executable_name()].iter().chain(cli.relaychain_args.iter()),
);
let polkadot_config = SubstrateCli::create_configuration(
&polkadot_cli,
&polkadot_cli,
config.tokio_handle.clone(),
)
.map_err(|err| format!("Relay chain argument error: {}", err))?;
cmd.run(config, polkadot_config)
})
},
Some(Subcommand::Revert(cmd)) => {
construct_async_run!(|components, cli, cmd, config| Ok(
cmd.run(components.client, components.backend)
))
},
Some(Subcommand::ExportGenesisState(params)) => {
let mut builder = sc_cli::LoggerBuilder::new("");
builder.with_profiling(sc_tracing::TracingReceiver::Log, "");
let _ = builder.init();
let block: Block = generate_genesis_block(&load_spec(
&params.chain.clone().unwrap_or_default(),
params.parachain_id.expect("Missing ParaId").into(),
)?)?;
let raw_header = block.header().encode();
let output_buf = if params.raw {
raw_header
} else {
format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes()
};
if let Some(output) = &params.output {
std::fs::write(output, output_buf)?;
} else {
std::io::stdout().write_all(&output_buf)?;
}
Ok(())
},
Some(Subcommand::ExportGenesisWasm(params)) => {
let mut builder = sc_cli::LoggerBuilder::new("");
builder.with_profiling(sc_tracing::TracingReceiver::Log, "");
let _ = builder.init();
let raw_wasm_blob =
extract_genesis_wasm(&*cli.load_spec(&params.chain.clone().unwrap_or_default())?)?;
let output_buf = if params.raw {
raw_wasm_blob
} else {
format!("0x{:?}", HexDisplay::from(&raw_wasm_blob)).into_bytes()
};
if let Some(output) = &params.output {
std::fs::write(output, output_buf)?;
} else {
std::io::stdout().write_all(&output_buf)?;
}
Ok(())
},
Some(Subcommand::Benchmark(cmd)) =>
if cfg!(feature = "runtime-benchmarks") {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run::<Block, ParachainRuntimeExecutor>(config))
} else {
Err("Benchmarking wasn't enabled when building the node. \
You can enable it with `--features runtime-benchmarks`."
.into())
},
None => {
let runner = cli.create_runner(&cli.run.normalize())?;
runner.run_node_until_exit(|config| async move {
let para_id =
chain_spec::Extensions::try_get(&*config.chain_spec).map(|e| e.para_id);
let polkadot_cli = RelayChainCli::new(
&config,
[RelayChainCli::executable_name()].iter().chain(cli.relaychain_args.iter()),
);
let id = ParaId::from(cli.run.parachain_id.or(para_id).expect("Missing ParaId"));
let parachain_account =
AccountIdConversion::<polkadot_primitives::v0::AccountId>::into_account(&id);
let block: Block =
generate_genesis_block(&config.chain_spec).map_err(|e| format!("{:?}", e))?;
let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode()));
let polkadot_config = SubstrateCli::create_configuration(
&polkadot_cli,
&polkadot_cli,
config.tokio_handle.clone(),
)
.map_err(|err| format!("Relay chain argument error: {}", err))?;
info!("Parachain id: {:?}", id);
info!("Parachain Account: {}", parachain_account);
info!("Parachain genesis state: {}", genesis_state);
info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" });
crate::service::start_node(config, polkadot_config, id)
.await
.map(|r| r.0)
.map_err(Into::into)
})
},
}
}
impl DefaultConfigurationValues for RelayChainCli {
fn p2p_listen_port() -> u16 {
30334
}
fn rpc_ws_listen_port() -> u16 {
9945
}
fn rpc_http_listen_port() -> u16 {
9934
}
fn prometheus_listen_port() -> u16 {
9616
}
}
impl CliConfiguration<Self> for RelayChainCli {
fn shared_params(&self) -> &SharedParams {
self.base.base.shared_params()
}
fn import_params(&self) -> Option<&ImportParams> {
self.base.base.import_params()
}
fn network_params(&self) -> Option<&NetworkParams> {
self.base.base.network_params()
}
fn keystore_params(&self) -> Option<&KeystoreParams> {
self.base.base.keystore_params()
}
fn base_path(&self) -> Result<Option<BasePath>> {
Ok(self
.shared_params()
.base_path()
.or_else(|| self.base_path.clone().map(Into::into)))
}
fn rpc_http(&self, default_listen_port: u16) -> Result<Option<SocketAddr>> {
self.base.base.rpc_http(default_listen_port)
}
fn rpc_ipc(&self) -> Result<Option<String>> {
self.base.base.rpc_ipc()
}
fn rpc_ws(&self, default_listen_port: u16) -> Result<Option<SocketAddr>> {
self.base.base.rpc_ws(default_listen_port)
}
fn prometheus_config(&self, default_listen_port: u16) -> Result<Option<PrometheusConfig>> {
self.base.base.prometheus_config(default_listen_port)
}
fn init<C: SubstrateCli>(&self) -> Result<()> {
unreachable!("PolkadotCli is never initialized; qed");
}
fn chain_id(&self, is_dev: bool) -> Result<String> {
let chain_id = self.base.base.chain_id(is_dev)?;
Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id })
}
fn role(&self, is_dev: bool) -> Result<sc_service::Role> {
self.base.base.role(is_dev)
}
fn transaction_pool(&self) -> Result<sc_service::config::TransactionPoolOptions> {
self.base.base.transaction_pool()
}
fn state_cache_child_ratio(&self) -> Result<Option<usize>> {
self.base.base.state_cache_child_ratio()
}
fn rpc_methods(&self) -> Result<sc_service::config::RpcMethods> {
self.base.base.rpc_methods()
}
fn rpc_ws_max_connections(&self) -> Result<Option<usize>> {
self.base.base.rpc_ws_max_connections()
}
fn rpc_cors(&self, is_dev: bool) -> Result<Option<Vec<String>>> {
self.base.base.rpc_cors(is_dev)
}
fn default_heap_pages(&self) -> Result<Option<u64>> {
self.base.base.default_heap_pages()
}
fn force_authoring(&self) -> Result<bool> {
self.base.base.force_authoring()
}
fn disable_grandpa(&self) -> Result<bool> {
self.base.base.disable_grandpa()
}
fn max_runtime_instances(&self) -> Result<Option<usize>> {
self.base.base.max_runtime_instances()
}
fn announce_block(&self) -> Result<bool> {
self.base.base.announce_block()
}
fn telemetry_endpoints(
&self,
chain_spec: &Box<dyn ChainSpec>,
) -> Result<Option<sc_telemetry::TelemetryEndpoints>> {
self.base.base.telemetry_endpoints(chain_spec)
}
}
@@ -0,0 +1,18 @@
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
pub mod chain_spec;
pub mod service;
@@ -0,0 +1,29 @@
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Substrate Parachain Node Template CLI
#![warn(missing_docs)]
mod chain_spec;
#[macro_use]
mod service;
mod cli;
mod command;
fn main() -> sc_cli::Result<()> {
command::run()
}
@@ -0,0 +1,496 @@
// Copyright 2020-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
// std
use std::sync::Arc;
// Local Runtime Types
use rialto_parachain_runtime::RuntimeApi;
// Cumulus Imports
use cumulus_client_consensus_aura::{
build_aura_consensus, BuildAuraConsensusParams, SlotProportion,
};
use cumulus_client_consensus_common::ParachainConsensus;
use cumulus_client_network::build_block_announce_validator;
use cumulus_client_service::{
prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams,
};
use cumulus_primitives_core::ParaId;
// Substrate Imports
use sc_client_api::ExecutorProvider;
use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch};
use sc_network::NetworkService;
use sc_service::{Configuration, PartialComponents, Role, TFullBackend, TFullClient, TaskManager};
use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};
use sp_api::ConstructRuntimeApi;
use sp_consensus::SlotData;
use sp_keystore::SyncCryptoStorePtr;
use sp_runtime::traits::BlakeTwo256;
use substrate_prometheus_endpoint::Registry;
// Runtime type overrides
type BlockNumber = u32;
type Header = sp_runtime::generic::Header<BlockNumber, sp_runtime::traits::BlakeTwo256>;
pub type Block = sp_runtime::generic::Block<Header, sp_runtime::OpaqueExtrinsic>;
type Hash = sp_core::H256;
pub type ParachainRuntimeExecutor = ExecutorDispatch;
// Our native executor instance.
pub struct ExecutorDispatch;
impl NativeExecutionDispatch for ExecutorDispatch {
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
rialto_parachain_runtime::api::dispatch(method, data)
}
fn native_version() -> sc_executor::NativeVersion {
rialto_parachain_runtime::native_version()
}
}
/// Starts a `ServiceBuilder` for a full service.
///
/// Use this macro if you don't actually need the full service, but just the builder in order to
/// be able to perform chain operations.
#[allow(clippy::type_complexity)]
pub fn new_partial<RuntimeApi, Executor, BIQ>(
config: &Configuration,
build_import_queue: BIQ,
) -> Result<
PartialComponents<
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
TFullBackend<Block>,
(),
sc_consensus::DefaultImportQueue<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
>,
sc_transaction_pool::FullPool<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
>,
(Option<Telemetry>, Option<TelemetryWorkerHandle>),
>,
sc_service::Error,
>
where
RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>
+ Send
+ Sync
+ 'static,
RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::Metadata<Block>
+ sp_session::SessionKeys<Block>
+ sp_api::ApiExt<
Block,
StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,
> + sp_offchain::OffchainWorkerApi<Block>
+ sp_block_builder::BlockBuilder<Block>,
sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,
Executor: NativeExecutionDispatch + 'static,
BIQ: FnOnce(
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
&Configuration,
Option<TelemetryHandle>,
&TaskManager,
) -> Result<
sc_consensus::DefaultImportQueue<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
>,
sc_service::Error,
>,
{
let telemetry = config
.telemetry_endpoints
.clone()
.filter(|x| !x.is_empty())
.map(|endpoints| -> Result<_, sc_telemetry::Error> {
let worker = TelemetryWorker::new(16)?;
let telemetry = worker.handle().new_telemetry(endpoints);
Ok((worker, telemetry))
})
.transpose()?;
let executor = sc_executor::NativeElseWasmExecutor::<Executor>::new(
config.wasm_method,
config.default_heap_pages,
config.max_runtime_instances,
);
let (client, backend, keystore_container, task_manager) =
sc_service::new_full_parts::<Block, RuntimeApi, _>(
config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
executor,
)?;
let client = Arc::new(client);
let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());
let telemetry = telemetry.map(|(worker, telemetry)| {
task_manager.spawn_handle().spawn("telemetry", worker.run());
telemetry
});
let transaction_pool = sc_transaction_pool::BasicPool::new_full(
config.transaction_pool.clone(),
config.role.is_authority().into(),
config.prometheus_registry(),
task_manager.spawn_essential_handle(),
client.clone(),
);
let import_queue = build_import_queue(
client.clone(),
config,
telemetry.as_ref().map(|telemetry| telemetry.handle()),
&task_manager,
)?;
let params = PartialComponents {
backend,
client,
import_queue,
keystore_container,
task_manager,
transaction_pool,
select_chain: (),
other: (telemetry, telemetry_worker_handle),
};
Ok(params)
}
/// Start a node with the given parachain `Configuration` and relay chain `Configuration`.
///
/// This is the actual implementation that is abstract over the executor and the runtime api.
#[sc_tracing::logging::prefix_logs_with("Parachain")]
async fn start_node_impl<RuntimeApi, Executor, RB, BIQ, BIC>(
parachain_config: Configuration,
polkadot_config: Configuration,
id: ParaId,
rpc_ext_builder: RB,
build_import_queue: BIQ,
build_consensus: BIC,
) -> sc_service::error::Result<(
TaskManager,
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
)>
where
RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>
+ Send
+ Sync
+ 'static,
RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::Metadata<Block>
+ sp_session::SessionKeys<Block>
+ sp_api::ApiExt<
Block,
StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,
> + sp_offchain::OffchainWorkerApi<Block>
+ sp_block_builder::BlockBuilder<Block>
+ cumulus_primitives_core::CollectCollationInfo<Block>,
sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,
Executor: NativeExecutionDispatch + 'static,
RB: Fn(
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
) -> jsonrpc_core::IoHandler<sc_rpc::Metadata>
+ Send
+ 'static,
BIQ: FnOnce(
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
&Configuration,
Option<TelemetryHandle>,
&TaskManager,
) -> Result<
sc_consensus::DefaultImportQueue<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
>,
sc_service::Error,
>,
BIC: FnOnce(
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
Option<&Registry>,
Option<TelemetryHandle>,
&TaskManager,
&polkadot_service::NewFull<polkadot_service::Client>,
Arc<
sc_transaction_pool::FullPool<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
>,
>,
Arc<NetworkService<Block, Hash>>,
SyncCryptoStorePtr,
bool,
) -> Result<Box<dyn ParachainConsensus<Block>>, sc_service::Error>,
{
if matches!(parachain_config.role, Role::Light) {
return Err("Light client not supported!".into())
}
let parachain_config = prepare_node_config(parachain_config);
let params = new_partial::<RuntimeApi, Executor, BIQ>(&parachain_config, build_import_queue)?;
let (mut telemetry, telemetry_worker_handle) = params.other;
let relay_chain_full_node =
cumulus_client_service::build_polkadot_full_node(polkadot_config, telemetry_worker_handle)
.map_err(|e| match e {
polkadot_service::Error::Sub(x) => x,
s => format!("{}", s).into(),
})?;
let client = params.client.clone();
let backend = params.backend.clone();
let block_announce_validator = build_block_announce_validator(
relay_chain_full_node.client.clone(),
id,
Box::new(relay_chain_full_node.network.clone()),
relay_chain_full_node.backend.clone(),
);
let force_authoring = parachain_config.force_authoring;
let validator = parachain_config.role.is_authority();
let prometheus_registry = parachain_config.prometheus_registry().cloned();
let transaction_pool = params.transaction_pool.clone();
let mut task_manager = params.task_manager;
let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue);
let (network, system_rpc_tx, start_network) =
sc_service::build_network(sc_service::BuildNetworkParams {
config: &parachain_config,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue: import_queue.clone(),
on_demand: None,
block_announce_validator_builder: Some(Box::new(|_| block_announce_validator)),
warp_sync: None,
})?;
let rpc_client = client.clone();
let rpc_extensions_builder = Box::new(move |_, _| Ok(rpc_ext_builder(rpc_client.clone())));
sc_service::spawn_tasks(sc_service::SpawnTasksParams {
on_demand: None,
remote_blockchain: None,
rpc_extensions_builder,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
task_manager: &mut task_manager,
config: parachain_config,
keystore: params.keystore_container.sync_keystore(),
backend: backend.clone(),
network: network.clone(),
system_rpc_tx,
telemetry: telemetry.as_mut(),
})?;
let announce_block = {
let network = network.clone();
Arc::new(move |hash, data| network.announce_block(hash, data))
};
if validator {
let parachain_consensus = build_consensus(
client.clone(),
prometheus_registry.as_ref(),
telemetry.as_ref().map(|t| t.handle()),
&task_manager,
&relay_chain_full_node,
transaction_pool,
network,
params.keystore_container.sync_keystore(),
force_authoring,
)?;
let spawner = task_manager.spawn_handle();
let params = StartCollatorParams {
para_id: id,
block_status: client.clone(),
announce_block,
client: client.clone(),
task_manager: &mut task_manager,
relay_chain_full_node,
spawner,
parachain_consensus,
import_queue,
};
start_collator(params).await?;
} else {
let params = StartFullNodeParams {
client: client.clone(),
announce_block,
task_manager: &mut task_manager,
para_id: id,
relay_chain_full_node,
};
start_full_node(params)?;
}
start_network.start_network();
Ok((task_manager, client))
}
/// Build the import queue for the the parachain runtime.
#[allow(clippy::type_complexity)]
pub fn parachain_build_import_queue(
client: Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ParachainRuntimeExecutor>>>,
config: &Configuration,
telemetry: Option<TelemetryHandle>,
task_manager: &TaskManager,
) -> Result<
sc_consensus::DefaultImportQueue<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ParachainRuntimeExecutor>>,
>,
sc_service::Error,
> {
let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;
cumulus_client_consensus_aura::import_queue::<
sp_consensus_aura::sr25519::AuthorityPair,
_,
_,
_,
_,
_,
_,
>(cumulus_client_consensus_aura::ImportQueueParams {
block_import: client.clone(),
client: client.clone(),
create_inherent_data_providers: move |_, _| async move {
let time = sp_timestamp::InherentDataProvider::from_system_time();
let slot =
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*time,
slot_duration.slot_duration(),
);
Ok((time, slot))
},
registry: config.prometheus_registry(),
can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),
spawner: &task_manager.spawn_essential_handle(),
telemetry,
})
.map_err(Into::into)
}
/// Start a normal parachain node.
pub async fn start_node(
parachain_config: Configuration,
polkadot_config: Configuration,
id: ParaId,
) -> sc_service::error::Result<(
TaskManager,
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ParachainRuntimeExecutor>>>,
)> {
start_node_impl::<RuntimeApi, ParachainRuntimeExecutor, _, _, _>(
parachain_config,
polkadot_config,
id,
|_| Default::default(),
parachain_build_import_queue,
|client,
prometheus_registry,
telemetry,
task_manager,
relay_chain_node,
transaction_pool,
sync_oracle,
keystore,
force_authoring| {
let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;
let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(
task_manager.spawn_handle(),
client.clone(),
transaction_pool,
prometheus_registry,
telemetry.clone(),
);
let relay_chain_backend = relay_chain_node.backend.clone();
let relay_chain_client = relay_chain_node.client.clone();
Ok(build_aura_consensus::<
sp_consensus_aura::sr25519::AuthorityPair,
_,
_,
_,
_,
_,
_,
_,
_,
_,
>(BuildAuraConsensusParams {
proposer_factory,
create_inherent_data_providers: move |_, (relay_parent, validation_data)| {
let parachain_inherent =
cumulus_primitives_parachain_inherent::ParachainInherentData::create_at_with_client(
relay_parent,
&relay_chain_client,
&*relay_chain_backend,
&validation_data,
id,
);
async move {
let time = sp_timestamp::InherentDataProvider::from_system_time();
let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*time,
slot_duration.slot_duration(),
);
let parachain_inherent = parachain_inherent.ok_or_else(|| {
Box::<dyn std::error::Error + Send + Sync>::from(
"Failed to create parachain inherent",
)
})?;
Ok((time, slot, parachain_inherent))
}
},
block_import: client.clone(),
relay_chain_client: relay_chain_node.client.clone(),
relay_chain_backend: relay_chain_node.backend.clone(),
para_client: client,
backoff_authoring_blocks: Option::<()>::None,
sync_oracle,
keystore,
force_authoring,
slot_duration,
// We got around 500ms for proposing
block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32),
telemetry,
max_block_proposal_slot_portion: None,
}))
},
)
.await
}
@@ -0,0 +1,122 @@
[package]
name = "rialto-parachain-runtime"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/parity-bridges-common/"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[build-dependencies]
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
[dependencies]
codec = { package = 'parity-scale-codec', version = '2.0.0', default-features = false, features = ['derive']}
log = { version = "0.4.14", default-features = false }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
serde = { version = '1.0', optional = true, features = ['derive'] }
# Bridge depedencies
bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false }
# Substrate Dependencies
## Substrate Primitive Dependencies
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
## Substrate FRAME Dependencies
frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
## Substrate Pallet Dependencies
pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
# Cumulus Dependencies
cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false }
# Polkadot Dependencies
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false }
[features]
default = ['std']
runtime-benchmarks = [
'sp-runtime/runtime-benchmarks',
'frame-benchmarking',
'frame-support/runtime-benchmarks',
'frame-system-benchmarking',
'frame-system/runtime-benchmarks',
'pallet-balances/runtime-benchmarks',
'pallet-timestamp/runtime-benchmarks',
]
std = [
"bp-rialto-parachain/std",
"codec/std",
"log/std",
"scale-info/std",
"serde",
"sp-api/std",
"sp-std/std",
"sp-io/std",
"sp-core/std",
"sp-runtime/std",
"sp-version/std",
"sp-offchain/std",
"sp-session/std",
"sp-block-builder/std",
"sp-transaction-pool/std",
"sp-inherents/std",
"frame-support/std",
"frame-executive/std",
"frame-system/std",
"pallet-balances/std",
"pallet-randomness-collective-flip/std",
"pallet-timestamp/std",
"pallet-sudo/std",
"pallet-transaction-payment/std",
"parachain-info/std",
"cumulus-pallet-aura-ext/std",
"cumulus-pallet-parachain-system/std",
"cumulus-pallet-xcmp-queue/std",
"cumulus-pallet-xcm/std",
"cumulus-primitives-core/std",
"cumulus-primitives-timestamp/std",
"cumulus-primitives-utility/std",
"xcm/std",
"xcm-builder/std",
"xcm-executor/std",
"pallet-aura/std",
"sp-consensus-aura/std",
]
@@ -0,0 +1,25 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use substrate_wasm_builder::WasmBuilder;
fn main() {
WasmBuilder::new()
.with_current_project()
.export_heap_base()
.import_memory()
.build()
}
@@ -0,0 +1,646 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! The Rialto parachain runtime. This can be compiled with `#[no_std]`, ready for Wasm.
//!
//! Originally a copy of runtime from https://github.com/substrate-developer-hub/substrate-parachain-template.
#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit = "256"]
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{AccountIdLookup, Block as BlockT},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
// A few exports that help ease life for downstream crates.
pub use frame_support::{
construct_runtime, match_type, parameter_types,
traits::{Everything, IsInVec, Randomness},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
DispatchClass, IdentityFee, Weight,
},
StorageValue,
};
pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall;
pub use pallet_timestamp::Call as TimestampCall;
pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
pub use sp_runtime::{MultiAddress, Perbill, Permill};
pub use bp_rialto_parachain::{
AccountId, Balance, BlockLength, BlockNumber, BlockWeights, Hash, Hasher as Hashing, Header,
Index, Signature, MAXIMUM_BLOCK_WEIGHT,
};
// Polkadot & XCM imports
use pallet_xcm::XcmPassthrough;
use polkadot_parachain::primitives::Sibling;
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset,
ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, UsingComponents,
};
use xcm_executor::{Config, XcmExecutor};
/// The address format for describing accounts.
pub type Address = MultiAddress<AccountId, ()>;
/// Block type as expected by this runtime.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// A Block signed with a Justification
pub type SignedBlock = generic::SignedBlock<Block>;
/// BlockId type as expected by this runtime.
pub type BlockId = generic::BlockId<Block>;
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (
frame_system::CheckSpecVersion<Runtime>,
frame_system::CheckGenesis<Runtime>,
frame_system::CheckEra<Runtime>,
frame_system::CheckNonce<Runtime>,
frame_system::CheckWeight<Runtime>,
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
/// Extrinsic type that has already been checked.
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
/// Executive: handles dispatch to the various modules.
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPallets,
>;
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: Aura,
}
}
/// This runtime version.
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("template-parachain"),
impl_name: create_runtime_str!("template-parachain"),
authoring_version: 1,
spec_version: 1,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
};
/// This determines the average expected block time that we are targeting.
/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`.
/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked
/// up by `pallet_aura` to implement `fn slot_duration()`.
///
/// Change this to adjust the block time.
pub const MILLISECS_PER_BLOCK: u64 = 12000;
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
pub const EPOCH_DURATION_IN_BLOCKS: u32 = 10 * MINUTES;
// Time is measured by number of blocks.
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;
// Unit = the base number of indivisible units for balances
pub const UNIT: Balance = 1_000_000_000_000;
pub const MILLIUNIT: Balance = 1_000_000_000;
pub const MICROUNIT: Balance = 1_000_000;
// 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks.
pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4);
/// The version information used to identify this runtime when compiled natively.
#[cfg(feature = "std")]
pub fn native_version() -> NativeVersion {
NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
}
parameter_types! {
pub const BlockHashCount: BlockNumber = 250;
pub const Version: RuntimeVersion = VERSION;
pub const SS58Prefix: u8 = 48;
}
// Configure FRAME pallets to include in runtime.
impl frame_system::Config for Runtime {
/// The identifier used to distinguish between accounts.
type AccountId = AccountId;
/// The aggregated dispatch type that is available for extrinsics.
type Call = Call;
/// The lookup mechanism to get account ID from whatever is passed in dispatchers.
type Lookup = AccountIdLookup<AccountId, ()>;
/// The index type for storing how many extrinsics an account has signed.
type Index = Index;
/// The index type for blocks.
type BlockNumber = BlockNumber;
/// The type for hashing blocks and tries.
type Hash = Hash;
/// The hashing algorithm used.
type Hashing = Hashing;
/// The header type.
type Header = generic::Header<BlockNumber, Hashing>;
/// The ubiquitous event type.
type Event = Event;
/// The ubiquitous origin type.
type Origin = Origin;
/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
type BlockHashCount = BlockHashCount;
/// Runtime version.
type Version = Version;
/// Converts a module to an index of this module in the runtime.
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<Balance>;
/// What to do if a new account is created.
type OnNewAccount = ();
/// What to do if an account is fully reaped from the system.
type OnKilledAccount = ();
/// The weight of database operations that the runtime can invoke.
type DbWeight = ();
/// The basic call filter to use in dispatchable.
type BaseCallFilter = Everything;
/// Weight information for the extrinsics of this pallet.
type SystemWeightInfo = ();
/// Block & extrinsics weights: base values and limits.
type BlockWeights = BlockWeights;
/// The maximum length of a block (in bytes).
type BlockLength = BlockLength;
/// This is used as an identifier of the chain. 42 is the generic substrate prefix.
type SS58Prefix = SS58Prefix;
/// The action to take on a Runtime Upgrade
type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
}
parameter_types! {
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
}
impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the Unix epoch.
type Moment = u64;
type OnTimestampSet = ();
type MinimumPeriod = MinimumPeriod;
type WeightInfo = ();
}
parameter_types! {
pub const ExistentialDeposit: u128 = MILLIUNIT;
pub const TransferFee: u128 = MILLIUNIT;
pub const CreationFee: u128 = MILLIUNIT;
pub const TransactionByteFee: u128 = MICROUNIT;
pub const OperationalFeeMultiplier: u8 = 5;
pub const MaxLocks: u32 = 50;
pub const MaxReserves: u32 = 50;
}
impl pallet_balances::Config for Runtime {
/// The type for recording an account's balance.
type Balance = Balance;
/// The ubiquitous event type.
type Event = Event;
type DustRemoval = ();
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
type MaxLocks = MaxLocks;
type MaxReserves = MaxReserves;
type ReserveIdentifier = [u8; 8];
}
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, ()>;
type TransactionByteFee = TransactionByteFee;
type OperationalFeeMultiplier = OperationalFeeMultiplier;
type WeightToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = ();
}
impl pallet_sudo::Config for Runtime {
type Call = Call;
type Event = Event;
}
parameter_types! {
pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
}
impl cumulus_pallet_parachain_system::Config for Runtime {
type Event = Event;
type OnValidationData = ();
type SelfParaId = parachain_info::Pallet<Runtime>;
type OutboundXcmpMessageSource = XcmpQueue;
type DmpMessageHandler = DmpQueue;
type ReservedDmpWeight = ReservedDmpWeight;
type XcmpMessageHandler = XcmpQueue;
type ReservedXcmpWeight = ReservedXcmpWeight;
}
impl parachain_info::Config for Runtime {}
impl cumulus_pallet_aura_ext::Config for Runtime {}
impl pallet_randomness_collective_flip::Config for Runtime {}
parameter_types! {
pub const RelayLocation: MultiLocation = MultiLocation::parent();
pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
}
/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
/// `Transact` in order to determine the dispatch Origin.
pub type LocationToAccountId = (
// The parent (Relay-chain) origin converts to the default `AccountId`.
ParentIsDefault<AccountId>,
// Sibling parachain origins convert to AccountId via the `ParaId::into`.
SiblingParachainConvertsVia<Sibling, AccountId>,
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
AccountId32Aliases<RelayNetwork, AccountId>,
);
/// Means for transacting assets on this chain.
pub type LocalAssetTransactor = CurrencyAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
IsConcrete<RelayLocation>,
// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We don't track any teleports.
(),
>;
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with XCM `Transact`. There is an `OriginKind` which can
/// biases the kind of local `Origin` it will become.
pub type XcmOriginToTransactDispatchOrigin = (
// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
// foreign chains who want to have a local sovereign account on this chain which they control.
SovereignSignedViaLocation<LocationToAccountId, Origin>,
// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
// recognised.
RelayChainAsNative<RelayOrigin, Origin>,
// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
// recognised.
SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,
// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
// transaction from the Root origin.
ParentAsSuperuser<Origin>,
// Native signed account converter; this just converts an `AccountId32` origin into a normal
// `Origin::Signed` origin of the same 32-byte value.
SignedAccountId32AsNative<RelayNetwork, Origin>,
// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
XcmPassthrough<Origin>,
);
parameter_types! {
// One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.
pub UnitWeightCost: Weight = 1_000_000;
// One UNIT buys 1 second of weight.
pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT);
pub const MaxInstructions: u32 = 100;
pub const MaxAuthorities: u32 = 100_000;
}
match_type! {
pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }
};
}
pub type Barrier = (
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom<Everything>,
AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>,
// ^^^ Parent & its unit plurality gets free execution
);
pub struct XcmConfig;
impl Config for XcmConfig {
type Call = Call;
type XcmSender = XcmRouter;
// How to withdraw and deposit an asset.
type AssetTransactor = LocalAssetTransactor;
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = NativeAsset;
type IsTeleporter = NativeAsset; // <- should be enough to allow teleportation of UNIT
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
type Trader = UsingComponents<IdentityFee<Balance>, RelayLocation, AccountId, Balances, ()>;
type ResponseHandler = PolkadotXcm;
type AssetTrap = PolkadotXcm;
type AssetClaims = PolkadotXcm;
type SubscriptionService = PolkadotXcm;
}
/// No local origins on this chain are allowed to dispatch XCM sends/executions.
pub type LocalOriginToLocation = SignedToAccountId32<Origin, AccountId, RelayNetwork>;
/// The means for routing XCM messages which are not for local execution into the right message
/// queues.
pub type XcmRouter = (
// Two routers - use UMP to communicate with the relay chain:
cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,
// ..and XCMP to communicate with the sibling chains.
XcmpQueue,
);
impl pallet_xcm::Config for Runtime {
type Event = Event;
type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
type XcmRouter = XcmRouter;
type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
type XcmExecuteFilter = Everything;
type XcmExecutor = XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Everything;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
type LocationInverter = LocationInverter<Ancestry>;
type Origin = Origin;
type Call = Call;
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
}
impl cumulus_pallet_xcm::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
}
impl cumulus_pallet_xcmp_queue::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
type ChannelInfo = ParachainSystem;
type VersionWrapper = ();
}
impl cumulus_pallet_dmp_queue::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
}
impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
type DisabledValidators = ();
type MaxAuthorities = MaxAuthorities;
}
// /// Configure the pallet template in pallets/template.
// impl template::Config for Runtime {
// type Event = Event;
// }
// Create the runtime by composing the FRAME pallets that were previously configured.
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = generic::Block<Header, sp_runtime::OpaqueExtrinsic>,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Storage, Config, Event<T>},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},
TransactionPayment: pallet_transaction_payment::{Pallet, Storage},
ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event<T>} = 20,
ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,
Aura: pallet_aura::{Pallet, Config<T>},
AuraExt: cumulus_pallet_aura_ext::{Pallet, Config},
// XCM helpers.
XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,
DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
// //Template
// TemplatePallet: template::{Pallet, Call, Storage, Event<T>},
}
);
impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn execute_block(block: Block) {
Executive::execute_block(block)
}
fn initialize_block(header: &<Block as BlockT>::Header) {
Executive::initialize_block(header)
}
}
impl sp_api::Metadata<Block> for Runtime {
fn metadata() -> OpaqueMetadata {
OpaqueMetadata::new(Runtime::metadata().into())
}
}
impl sp_block_builder::BlockBuilder<Block> for Runtime {
fn apply_extrinsic(
extrinsic: <Block as BlockT>::Extrinsic,
) -> ApplyExtrinsicResult {
Executive::apply_extrinsic(extrinsic)
}
fn finalize_block() -> <Block as BlockT>::Header {
Executive::finalize_block()
}
fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
data.create_extrinsics()
}
fn check_inherents(
block: Block,
data: sp_inherents::InherentData,
) -> sp_inherents::CheckInherentsResult {
data.check_extrinsics(&block)
}
}
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(
source: TransactionSource,
tx: <Block as BlockT>::Extrinsic,
block_hash: <Block as BlockT>::Hash,
) -> TransactionValidity {
Executive::validate_transaction(source, tx, block_hash)
}
}
impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
fn offchain_worker(header: &<Block as BlockT>::Header) {
Executive::offchain_worker(header)
}
}
impl sp_session::SessionKeys<Block> for Runtime {
fn decode_session_keys(
encoded: Vec<u8>,
) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
SessionKeys::decode_into_raw_public_keys(&encoded)
}
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
SessionKeys::generate(seed)
}
}
impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
fn slot_duration() -> sp_consensus_aura::SlotDuration {
sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
}
fn authorities() -> Vec<AuraId> {
Aura::authorities().to_vec()
}
}
impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
fn collect_collation_info() -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info()
}
}
impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
fn account_nonce(account: AccountId) -> Index {
System::account_nonce(account)
}
}
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
fn query_info(
uxt: <Block as BlockT>::Extrinsic,
len: u32,
) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
TransactionPayment::query_info(uxt, len)
}
fn query_fee_details(
uxt: <Block as BlockT>::Extrinsic,
len: u32,
) -> pallet_transaction_payment::FeeDetails<Balance> {
TransactionPayment::query_fee_details(uxt, len)
}
}
#[cfg(feature = "runtime-benchmarks")]
impl frame_benchmarking::Benchmark<Block> for Runtime {
fn dispatch_benchmark(
config: frame_benchmarking::BenchmarkConfig
) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {
use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};
use frame_system_benchmarking::Pallet as SystemBench;
impl frame_system_benchmarking::Config for Runtime {}
let whitelist: Vec<TrackedStorageKey> = vec![
// Block Number
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),
// Total Issuance
hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),
// Execution Phase
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),
// Event Count
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),
// System Events
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),
];
let mut batches = Vec::<BenchmarkBatch>::new();
let params = (&config, &whitelist);
add_benchmark!(params, batches, frame_system, SystemBench::<Runtime>);
add_benchmark!(params, batches, pallet_balances, Balances);
add_benchmark!(params, batches, pallet_timestamp, Timestamp);
if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
Ok(batches)
}
}
}
struct CheckInherents;
impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
fn check_inherents(
block: &Block,
relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
) -> sp_inherents::CheckInherentsResult {
let relay_chain_slot = relay_state_proof
.read_slot()
.expect("Could not read the relay chain slot from the proof");
let inherent_data =
cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
relay_chain_slot,
sp_std::time::Duration::from_secs(6),
)
.create_inherent_data()
.expect("Could not create the timestamp inherent data");
inherent_data.check_extrinsics(block)
}
}
cumulus_pallet_parachain_system::register_validate_block!(
Runtime = Runtime,
BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
CheckInherents = CheckInherents,
);
+112
View File
@@ -0,0 +1,112 @@
[package]
name = "rialto-bridge-node"
description = "Substrate node compatible with Rialto runtime"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
build = "build.rs"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/parity-bridges-common/"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies]
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-runtime = { path = "../../../primitives/runtime" }
bp-rialto = { path = "../../../primitives/chain-rialto" }
pallet-bridge-messages = { path = "../../../modules/messages" }
rialto-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" }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment-rpc-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-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-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 (parachain) Dependencies
polkadot-approval-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-availability-bitfield-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-availability-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-availability-recovery = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-collator-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-dispute-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-gossip-support = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-network-bridge = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-collation-generation = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-approval-voting = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-av-store = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-backing = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-bitfield-signing = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-candidate-validation = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-chain-api = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-chain-selection = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-dispute-participation = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-parachains-inherent = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-provisioner = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-runtime-api = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-core-dispute-coordinator = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-network-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-node-subsystem-util = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-overseer = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-statement-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
[build-dependencies]
substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
[features]
default = []
runtime-benchmarks = [
"rialto-runtime/runtime-benchmarks",
]
@@ -15,12 +15,15 @@
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
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, BridgeKovanConfig, BridgeMillauMessagesConfig,
BridgeRialtoPoaConfig, 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 +59,17 @@ 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, 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::<GrandpaId>(s),
get_from_seed::<ValidatorId>(s),
get_from_seed::<AssignmentId>(s),
get_from_seed::<AuthorityDiscoveryId>(s),
)
}
@@ -71,10 +79,7 @@ impl Alternative {
let properties = Some(
json!({
"tokenDecimals": 9,
"tokenSymbol": "RLT",
"bridgeIds": {
"Millau": bp_runtime::MILLAU_CHAIN_ID,
}
"tokenSymbol": "RLT"
})
.as_object()
.expect("Map given; qed")
@@ -82,8 +87,8 @@ impl Alternative {
);
match self {
Alternative::Development => ChainSpec::from_genesis(
"Development",
"dev",
"Rialto Development",
"rialto_dev",
sc_service::ChainType::Development,
|| {
testnet_genesis(
@@ -108,8 +113,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 +143,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 +181,25 @@ impl Alternative {
}
}
fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys {
SessionKeys { aura, grandpa }
fn session_keys(
babe: BabeId,
grandpa: GrandpaId,
para_validator: ValidatorId,
para_assignment: AssignmentId,
authority_discovery: AuthorityDiscoveryId,
) -> SessionKeys {
SessionKeys { babe, grandpa, para_validator, para_assignment, authority_discovery }
}
fn testnet_genesis(
initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>,
initial_authorities: Vec<(
AccountId,
BabeId,
GrandpaId,
ValidatorId,
AssignmentId,
AuthorityDiscoveryId,
)>,
root_key: AccountId,
endowed_accounts: Vec<AccountId>,
_enable_println: bool,
@@ -192,21 +212,82 @@ fn testnet_genesis(
balances: BalancesConfig {
balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(),
},
aura: AuraConfig {
babe: BabeConfig {
authorities: Vec::new(),
epoch_config: Some(rialto_runtime::BABE_GENESIS_EPOCH_CONFIG),
},
bridge_rialto_poa: load_rialto_poa_bridge_config(),
bridge_kovan: load_kovan_bridge_config(),
grandpa: GrandpaConfig {
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(),
),
)
})
.collect::<Vec<_>>(),
},
authority_discovery: Default::default(),
hrmp: Default::default(),
// this configuration is exact copy of configuration from Polkadot repo
// (see /node/service/src/chain_spec.rs:default_parachains_host_configuration)
configuration: ConfigurationConfig {
config: polkadot_runtime_parachains::configuration::HostConfiguration {
validation_upgrade_frequency: 1u32,
validation_upgrade_delay: 1,
code_retention_period: 1200,
max_code_size: polkadot_primitives::v1::MAX_CODE_SIZE,
max_pov_size: polkadot_primitives::v1::MAX_POV_SIZE,
max_head_data_size: 32 * 1024,
group_rotation_frequency: 20,
chain_availability_period: 4,
thread_availability_period: 4,
max_upward_queue_count: 8,
max_upward_queue_size: 1024 * 1024,
max_downward_message_size: 1024,
// this is approximatelly 4ms.
//
// Same as `4 * frame_support::weights::WEIGHT_PER_MILLIS`. We don't bother with
// an import since that's a made up number and should be replaced with a constant
// obtained by benchmarking anyway.
ump_service_total_weight: 4 * 1_000_000_000,
max_upward_message_size: 1024 * 1024,
max_upward_message_num_per_candidate: 5,
hrmp_sender_deposit: 0,
hrmp_recipient_deposit: 0,
hrmp_channel_max_capacity: 8,
hrmp_channel_max_total_size: 8 * 1024,
hrmp_max_parachain_inbound_channels: 4,
hrmp_max_parathread_inbound_channels: 4,
hrmp_channel_max_message_size: 1024 * 1024,
hrmp_max_parachain_outbound_channels: 4,
hrmp_max_parathread_outbound_channels: 4,
hrmp_max_message_num_per_candidate: 5,
dispute_period: 6,
no_show_slots: 2,
n_delay_tranches: 25,
needed_approvals: 2,
relay_vrf_modulo_samples: 2,
zeroth_delay_tranche_width: 0,
..Default::default()
},
},
paras: Default::default(),
bridge_millau_messages: BridgeMillauMessagesConfig {
owner: Some(get_account_id_from_seed::<sr25519::Public>("MillauMessagesOwner")),
..Default::default()
},
}
}
@@ -229,9 +310,7 @@ fn load_kovan_bridge_config() -> BridgeKovanConfig {
#[test]
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());
}
@@ -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,
}
@@ -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;
@@ -74,19 +75,18 @@ pub fn run() -> sc_cli::Result<()> {
));
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<()> {
+319
View File
@@ -0,0 +1,319 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! This is almost 1:1 copy of `node/service/src/overseer.rs` file from Polkadot repository.
//! The only exception is that we don't support db upgrades => no `upgrade.rs` module.
// this warning comes from `polkadot_overseer::AllSubsystems` type
#![allow(clippy::type_complexity)]
use crate::service::{AuthorityDiscoveryApi, Error};
use rialto_runtime::{opaque::Block, Hash};
use lru::LruCache;
use polkadot_availability_distribution::IncomingRequestReceivers;
use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig;
use polkadot_node_core_av_store::Config as AvailabilityConfig;
use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig;
use polkadot_node_core_chain_selection::Config as ChainSelectionConfig;
use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig;
use polkadot_node_network_protocol::request_response::{v1 as request_v1, IncomingRequestReceiver};
use polkadot_overseer::{
metrics::Metrics as OverseerMetrics, BlockInfo, MetricsTrait, Overseer, OverseerBuilder,
OverseerConnector, OverseerHandle,
};
use polkadot_primitives::v1::ParachainHost;
use sc_authority_discovery::Service as AuthorityDiscoveryService;
use sc_client_api::AuxStore;
use sc_keystore::LocalKeystore;
use sp_api::ProvideRuntimeApi;
use sp_blockchain::HeaderBackend;
use sp_consensus_babe::BabeApi;
use sp_core::traits::SpawnNamed;
use std::sync::Arc;
use substrate_prometheus_endpoint::Registry;
pub use polkadot_approval_distribution::ApprovalDistribution as ApprovalDistributionSubsystem;
pub use polkadot_availability_bitfield_distribution::BitfieldDistribution as BitfieldDistributionSubsystem;
pub use polkadot_availability_distribution::AvailabilityDistributionSubsystem;
pub use polkadot_availability_recovery::AvailabilityRecoverySubsystem;
pub use polkadot_collator_protocol::{CollatorProtocolSubsystem, ProtocolSide};
pub use polkadot_dispute_distribution::DisputeDistributionSubsystem;
pub use polkadot_gossip_support::GossipSupport as GossipSupportSubsystem;
pub use polkadot_network_bridge::NetworkBridge as NetworkBridgeSubsystem;
pub use polkadot_node_collation_generation::CollationGenerationSubsystem;
pub use polkadot_node_core_approval_voting::ApprovalVotingSubsystem;
pub use polkadot_node_core_av_store::AvailabilityStoreSubsystem;
pub use polkadot_node_core_backing::CandidateBackingSubsystem;
pub use polkadot_node_core_bitfield_signing::BitfieldSigningSubsystem;
pub use polkadot_node_core_candidate_validation::CandidateValidationSubsystem;
pub use polkadot_node_core_chain_api::ChainApiSubsystem;
pub use polkadot_node_core_chain_selection::ChainSelectionSubsystem;
pub use polkadot_node_core_dispute_coordinator::DisputeCoordinatorSubsystem;
pub use polkadot_node_core_dispute_participation::DisputeParticipationSubsystem;
pub use polkadot_node_core_provisioner::ProvisioningSubsystem as ProvisionerSubsystem;
pub use polkadot_node_core_runtime_api::RuntimeApiSubsystem;
pub use polkadot_statement_distribution::StatementDistribution as StatementDistributionSubsystem;
/// Arguments passed for overseer construction.
pub struct OverseerGenArgs<'a, Spawner, RuntimeClient>
where
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
Spawner: 'static + SpawnNamed + Clone + Unpin,
{
/// Set of initial relay chain leaves to track.
pub leaves: Vec<BlockInfo>,
/// The keystore to use for i.e. validator keys.
pub keystore: Arc<LocalKeystore>,
/// Runtime client generic, providing the `ProvieRuntimeApi` trait besides others.
pub runtime_client: Arc<RuntimeClient>,
/// The underlying key value store for the parachains.
pub parachains_db: Arc<dyn kvdb::KeyValueDB>,
/// Underlying network service implementation.
pub network_service: Arc<sc_network::NetworkService<Block, Hash>>,
/// Underlying authority discovery service.
pub authority_discovery_service: AuthorityDiscoveryService,
/// POV request receiver
pub pov_req_receiver: IncomingRequestReceiver<request_v1::PoVFetchingRequest>,
pub chunk_req_receiver: IncomingRequestReceiver<request_v1::ChunkFetchingRequest>,
pub collation_req_receiver: IncomingRequestReceiver<request_v1::CollationFetchingRequest>,
pub available_data_req_receiver:
IncomingRequestReceiver<request_v1::AvailableDataFetchingRequest>,
pub statement_req_receiver: IncomingRequestReceiver<request_v1::StatementFetchingRequest>,
pub dispute_req_receiver: IncomingRequestReceiver<request_v1::DisputeRequest>,
/// Prometheus registry, commonly used for production systems, less so for test.
pub registry: Option<&'a Registry>,
/// Task spawner to be used throughout the overseer and the APIs it provides.
pub spawner: Spawner,
/// Configuration for the approval voting subsystem.
pub approval_voting_config: ApprovalVotingConfig,
/// Configuration for the availability store subsystem.
pub availability_config: AvailabilityConfig,
/// Configuration for the candidate validation subsystem.
pub candidate_validation_config: CandidateValidationConfig,
/// Configuration for the chain selection subsystem.
pub chain_selection_config: ChainSelectionConfig,
/// Configuration for the dispute coordinator subsystem.
pub dispute_coordinator_config: DisputeCoordinatorConfig,
}
/// Obtain a prepared `OverseerBuilder`, that is initialized
/// with all default values.
pub fn prepared_overseer_builder<Spawner, RuntimeClient>(
OverseerGenArgs {
leaves,
keystore,
runtime_client,
parachains_db,
network_service,
authority_discovery_service,
pov_req_receiver,
chunk_req_receiver,
collation_req_receiver: _,
available_data_req_receiver,
statement_req_receiver,
dispute_req_receiver,
registry,
spawner,
approval_voting_config,
availability_config,
candidate_validation_config,
chain_selection_config,
dispute_coordinator_config,
}: OverseerGenArgs<'_, Spawner, RuntimeClient>,
) -> Result<
OverseerBuilder<
Spawner,
Arc<RuntimeClient>,
CandidateValidationSubsystem,
CandidateBackingSubsystem<Spawner>,
StatementDistributionSubsystem,
AvailabilityDistributionSubsystem,
AvailabilityRecoverySubsystem,
BitfieldSigningSubsystem<Spawner>,
BitfieldDistributionSubsystem,
ProvisionerSubsystem<Spawner>,
RuntimeApiSubsystem<RuntimeClient>,
AvailabilityStoreSubsystem,
NetworkBridgeSubsystem<
Arc<sc_network::NetworkService<Block, Hash>>,
AuthorityDiscoveryService,
>,
ChainApiSubsystem<RuntimeClient>,
CollationGenerationSubsystem,
CollatorProtocolSubsystem,
ApprovalDistributionSubsystem,
ApprovalVotingSubsystem,
GossipSupportSubsystem<AuthorityDiscoveryService>,
DisputeCoordinatorSubsystem,
DisputeParticipationSubsystem,
DisputeDistributionSubsystem<AuthorityDiscoveryService>,
ChainSelectionSubsystem,
>,
Error,
>
where
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
Spawner: 'static + SpawnNamed + Clone + Unpin,
{
use polkadot_node_subsystem_util::metrics::Metrics;
use std::iter::FromIterator;
let metrics = <OverseerMetrics as MetricsTrait>::register(registry)?;
let builder = Overseer::builder()
.availability_distribution(AvailabilityDistributionSubsystem::new(
keystore.clone(),
IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver },
Metrics::register(registry)?,
))
.availability_recovery(AvailabilityRecoverySubsystem::with_chunks_only(
available_data_req_receiver,
Metrics::register(registry)?,
))
.availability_store(AvailabilityStoreSubsystem::new(
parachains_db.clone(),
availability_config,
Metrics::register(registry)?,
))
.bitfield_distribution(BitfieldDistributionSubsystem::new(Metrics::register(registry)?))
.bitfield_signing(BitfieldSigningSubsystem::new(
spawner.clone(),
keystore.clone(),
Metrics::register(registry)?,
))
.candidate_backing(CandidateBackingSubsystem::new(
spawner.clone(),
keystore.clone(),
Metrics::register(registry)?,
))
.candidate_validation(CandidateValidationSubsystem::with_config(
candidate_validation_config,
Metrics::register(registry)?, // candidate-validation metrics
Metrics::register(registry)?, // validation host metrics
))
.chain_api(ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?))
.collation_generation(CollationGenerationSubsystem::new(Metrics::register(registry)?))
.collator_protocol(CollatorProtocolSubsystem::new(ProtocolSide::Validator {
keystore: keystore.clone(),
eviction_policy: Default::default(),
metrics: Metrics::register(registry)?,
}))
.network_bridge(NetworkBridgeSubsystem::new(
network_service.clone(),
authority_discovery_service.clone(),
Box::new(network_service.clone()),
Metrics::register(registry)?,
))
.provisioner(ProvisionerSubsystem::new(spawner.clone(), (), Metrics::register(registry)?))
.runtime_api(RuntimeApiSubsystem::new(
runtime_client.clone(),
Metrics::register(registry)?,
spawner.clone(),
))
.statement_distribution(StatementDistributionSubsystem::new(
keystore.clone(),
statement_req_receiver,
Metrics::register(registry)?,
))
.approval_distribution(ApprovalDistributionSubsystem::new(Metrics::register(registry)?))
.approval_voting(ApprovalVotingSubsystem::with_config(
approval_voting_config,
parachains_db.clone(),
keystore.clone(),
Box::new(network_service),
Metrics::register(registry)?,
))
.gossip_support(GossipSupportSubsystem::new(
keystore.clone(),
authority_discovery_service.clone(),
))
.dispute_coordinator(DisputeCoordinatorSubsystem::new(
parachains_db.clone(),
dispute_coordinator_config,
keystore.clone(),
Metrics::register(registry)?,
))
.dispute_participation(DisputeParticipationSubsystem::new())
.dispute_distribution(DisputeDistributionSubsystem::new(
keystore,
dispute_req_receiver,
authority_discovery_service,
Metrics::register(registry)?,
))
.chain_selection(ChainSelectionSubsystem::new(chain_selection_config, parachains_db))
.leaves(Vec::from_iter(
leaves
.into_iter()
.map(|BlockInfo { hash, parent_hash: _, number }| (hash, number)),
))
.activation_external_listeners(Default::default())
.span_per_active_leaf(Default::default())
.active_leaves(Default::default())
.supports_parachains(runtime_client)
.known_leaves(LruCache::new(KNOWN_LEAVES_CACHE_SIZE))
.metrics(metrics)
.spawner(spawner);
Ok(builder)
}
/// Trait for the `fn` generating the overseer.
///
/// Default behavior is to create an unmodified overseer, as `RealOverseerGen`
/// would do.
pub trait OverseerGen {
/// Overwrite the full generation of the overseer, including the subsystems.
fn generate<Spawner, RuntimeClient>(
&self,
connector: OverseerConnector,
args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
) -> Result<(Overseer<Spawner, Arc<RuntimeClient>>, OverseerHandle), Error>
where
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
Spawner: 'static + SpawnNamed + Clone + Unpin,
{
let gen = RealOverseerGen;
RealOverseerGen::generate::<Spawner, RuntimeClient>(&gen, connector, args)
}
// It would be nice to make `create_subsystems` part of this trait,
// but the amount of generic arguments that would be required as
// as consequence make this rather annoying to implement and use.
}
use polkadot_overseer::KNOWN_LEAVES_CACHE_SIZE;
/// The regular set of subsystems.
pub struct RealOverseerGen;
impl OverseerGen for RealOverseerGen {
fn generate<Spawner, RuntimeClient>(
&self,
connector: OverseerConnector,
args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
) -> Result<(Overseer<Spawner, Arc<RuntimeClient>>, OverseerHandle), Error>
where
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
Spawner: 'static + SpawnNamed + Clone + Unpin,
{
prepared_overseer_builder(args)?
.build_with_connector(connector)
.map_err(|e| e.into())
}
}
@@ -1,41 +1,36 @@
// Copyright 2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Polkadot is free software: you can redistribute it and/or modify
// 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.
// Polkadot is distributed in the hope that it will be useful,
// 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.
//! A RocksDB instance for storing parachain data; availability data, and approvals.
// 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/>.
#[cfg(feature = "full-node")]
use {
std::io,
std::path::PathBuf,
std::sync::Arc,
//! 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.
kvdb::KeyValueDB,
};
use kvdb::KeyValueDB;
use std::{io, path::PathBuf, sync::Arc};
mod upgrade;
#[cfg(any(test,feature = "full-node"))]
mod columns {
pub const NUM_COLUMNS: u32 = 3;
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.
#[cfg(any(test,feature = "full-node"))]
#[derive(Debug, Clone)]
pub struct ColumnsConfig {
/// The column used by the av-store for data.
@@ -44,14 +39,19 @@ pub struct ColumnsConfig {
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.
#[cfg(any(test,feature = "full-node"))]
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.
@@ -67,45 +67,38 @@ pub struct CacheSizes {
impl Default for CacheSizes {
fn default() -> Self {
CacheSizes {
availability_data: 25,
availability_meta: 1,
approval_data: 5,
}
CacheSizes { availability_data: 25, availability_meta: 1, approval_data: 5 }
}
}
#[cfg(feature = "full-node")]
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.
#[cfg(feature = "full-node")]
pub fn open_creating(
root: PathBuf,
cache_sizes: CacheSizes,
) -> io::Result<Arc<dyn KeyValueDB>> {
use kvdb_rocksdb::{DatabaseConfig, Database};
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
let _ = db_config
.memory_budget
.insert(columns::COL_AVAILABILITY_DATA, cache_sizes.availability_data);
let _ = db_config.memory_budget
let _ = db_config
.memory_budget
.insert(columns::COL_AVAILABILITY_META, cache_sizes.availability_meta);
let _ = db_config.memory_budget
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),
))?;
let path_str = path
.to_str()
.ok_or_else(|| other_io_error(format!("Bad database path: {:?}", path)))?;
std::fs::create_dir_all(&path_str)?;
upgrade::try_upgrade_db(&path)?;
let db = Database::open(&db_config, &path_str)?;
let db = Database::open(&db_config, path_str)?;
Ok(Arc::new(db))
}
+768
View File
@@ -0,0 +1,768 @@
// 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/>.
//! Rialto chain node service.
//!
//! The code is mostly copy of `service/src/lib.rs` file from Polkadot repository
//! without optional functions.
// this warning comes from Error enum (sc_cli::Error in particular) && it isn't easy to use box
// there
#![allow(clippy::large_enum_variant)]
// this warning comes from `sc_service::PartialComponents` type
#![allow(clippy::type_complexity)]
use crate::overseer::{OverseerGen, OverseerGenArgs};
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::IncomingRequest;
use polkadot_overseer::{BlockInfo, OverseerConnector};
use polkadot_primitives::v1::BlockId;
use rialto_runtime::{self, opaque::Block, RuntimeApi};
use sc_client_api::ExecutorProvider;
use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch};
use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider;
use sc_service::{config::PrometheusConfig, Configuration, TaskManager};
use sc_telemetry::{Telemetry, TelemetryWorker};
use sp_api::{ConstructRuntimeApi, HeaderT};
use sp_consensus::SelectChain;
use sp_runtime::traits::{BlakeTwo256, Block as BlockT};
use std::{sync::Arc, time::Duration};
use substrate_prometheus_endpoint::Registry;
pub use polkadot_overseer::Handle;
pub use polkadot_primitives::v1::ParachainHost;
pub use sc_client_api::AuxStore;
pub use sp_authority_discovery::AuthorityDiscoveryApi;
pub use sp_blockchain::HeaderBackend;
pub use sp_consensus_babe::BabeApi;
pub type Executor = NativeElseWasmExecutor<ExecutorDispatch>;
// Our native executor instance.
pub struct ExecutorDispatch;
impl sc_executor::NativeExecutionDispatch for ExecutorDispatch {
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
rialto_runtime::api::dispatch(method, data)
}
fn native_version() -> sc_executor::NativeVersion {
rialto_runtime::native_version()
}
}
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
Io(#[from] std::io::Error),
#[error(transparent)]
Cli(#[from] sc_cli::Error),
#[error(transparent)]
Blockchain(#[from] sp_blockchain::Error),
#[error(transparent)]
Consensus(#[from] sp_consensus::Error),
#[error(transparent)]
Service(#[from] sc_service::Error),
#[error(transparent)]
Telemetry(#[from] sc_telemetry::Error),
#[error("Failed to create an overseer")]
Overseer(#[from] polkadot_overseer::SubsystemError),
#[error(transparent)]
Prometheus(#[from] substrate_prometheus_endpoint::PrometheusError),
#[error("Authorities require the real overseer implementation")]
AuthoritiesRequireRealOverseer,
#[error("Creating a custom database is required for validators")]
DatabasePathRequired,
}
type FullClient = sc_service::TFullClient<Block, RuntimeApi, Executor>;
type FullBackend = sc_service::TFullBackend<Block>;
type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
type FullGrandpaBlockImport =
sc_finality_grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, FullSelectChain>;
type FullTransactionPool = sc_transaction_pool::FullPool<Block, FullClient>;
type FullBabeBlockImport =
sc_consensus_babe::BabeBlockImport<Block, FullClient, FullGrandpaBlockImport>;
type FullBabeLink = sc_consensus_babe::BabeLink<Block>;
type FullGrandpaLink = sc_finality_grandpa::LinkHalf<Block, FullClient, FullSelectChain>;
/// A set of APIs that polkadot-like runtimes must implement.
///
/// This is the copy of `polkadot_service::RuntimeApiCollection` with some APIs removed
/// (right now - MMR and BEEFY).
pub trait RequiredApiCollection:
sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::ApiExt<Block>
+ sp_consensus_babe::BabeApi<Block>
+ sp_finality_grandpa::GrandpaApi<Block>
+ polkadot_primitives::v1::ParachainHost<Block>
+ sp_block_builder::BlockBuilder<Block>
+ frame_system_rpc_runtime_api::AccountNonceApi<
Block,
bp_rialto::AccountId,
rialto_runtime::Index,
> + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, bp_rialto::Balance>
+ sp_api::Metadata<Block>
+ sp_offchain::OffchainWorkerApi<Block>
+ sp_session::SessionKeys<Block>
+ sp_authority_discovery::AuthorityDiscoveryApi<Block>
where
<Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
{
}
impl<Api> RequiredApiCollection for Api
where
Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::ApiExt<Block>
+ sp_consensus_babe::BabeApi<Block>
+ sp_finality_grandpa::GrandpaApi<Block>
+ polkadot_primitives::v1::ParachainHost<Block>
+ sp_block_builder::BlockBuilder<Block>
+ frame_system_rpc_runtime_api::AccountNonceApi<
Block,
bp_rialto::AccountId,
rialto_runtime::Index,
> + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, bp_rialto::Balance>
+ sp_api::Metadata<Block>
+ sp_offchain::OffchainWorkerApi<Block>
+ sp_session::SessionKeys<Block>
+ sp_authority_discovery::AuthorityDiscoveryApi<Block>,
<Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
{
}
// If we're using prometheus, use a registry with a prefix of `polkadot`.
fn set_prometheus_registry(config: &mut Configuration) -> Result<(), Error> {
if let Some(PrometheusConfig { registry, .. }) = config.prometheus_config.as_mut() {
*registry = Registry::new_custom(Some("polkadot".into()), None)?;
}
Ok(())
}
pub fn new_partial(
config: &mut Configuration,
) -> Result<
sc_service::PartialComponents<
FullClient,
FullBackend,
FullSelectChain,
sc_consensus::DefaultImportQueue<Block, FullClient>,
FullTransactionPool,
(
impl Fn(
sc_rpc::DenyUnsafe,
sc_rpc::SubscriptionTaskExecutor,
) -> Result<jsonrpc_core::IoHandler<sc_service::RpcMetadata>, sc_service::Error>,
(FullBabeBlockImport, FullGrandpaLink, FullBabeLink),
sc_finality_grandpa::SharedVoterState,
std::time::Duration,
Option<Telemetry>,
),
>,
Error,
>
where
RuntimeApi: ConstructRuntimeApi<Block, FullClient> + Send + Sync + 'static,
<RuntimeApi as ConstructRuntimeApi<Block, FullClient>>::RuntimeApi:
RequiredApiCollection<StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>,
ExecutorDispatch: NativeExecutionDispatch + 'static,
{
set_prometheus_registry(config)?;
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 = NativeElseWasmExecutor::<ExecutorDispatch>::new(
config.wasm_method,
config.default_heap_pages,
config.max_runtime_instances,
);
let (client, backend, keystore_container, task_manager) =
sc_service::new_full_parts::<Block, RuntimeApi, Executor>(
config,
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());
telemetry
});
let select_chain = sc_consensus::LongestChain::new(backend.clone());
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 (grandpa_block_import, grandpa_link) =
sc_finality_grandpa::block_import_with_authority_set_hard_forks(
client.clone(),
&(client.clone() as Arc<_>),
select_chain.clone(),
Vec::new(),
telemetry.as_ref().map(|x| x.handle()),
)?;
let justification_import = grandpa_block_import.clone();
let babe_config = sc_consensus_babe::Config::get_or_compute(&*client)?;
let (block_import, babe_link) =
sc_consensus_babe::block_import(babe_config.clone(), grandpa_block_import, client.clone())?;
let slot_duration = babe_link.config().slot_duration();
let import_queue = sc_consensus_babe::import_queue(
babe_link.clone(),
block_import.clone(),
Some(Box::new(justification_import)),
client.clone(),
select_chain.clone(),
move |_, ()| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let slot =
sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp,
slot_duration,
);
Ok((timestamp, slot))
},
&task_manager.spawn_essential_handle(),
config.prometheus_registry(),
sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),
telemetry.as_ref().map(|x| x.handle()),
)?;
let justification_stream = grandpa_link.justification_stream();
let shared_authority_set = grandpa_link.shared_authority_set().clone();
let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty();
let import_setup = (block_import, grandpa_link, babe_link);
let rpc_setup = shared_voter_state.clone();
let slot_duration = babe_config.slot_duration();
let rpc_extensions_builder = {
let client = client.clone();
let transaction_pool = transaction_pool.clone();
let backend = backend.clone();
move |deny_unsafe,
subscription_executor: sc_rpc::SubscriptionTaskExecutor|
-> Result<jsonrpc_core::IoHandler<sc_service::RpcMetadata>, sc_service::Error> {
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler};
use substrate_frame_rpc_system::{FullSystem, SystemApi};
let backend = backend.clone();
let client = client.clone();
let pool = transaction_pool.clone();
let shared_voter_state = shared_voter_state.clone();
let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(
backend,
Some(shared_authority_set.clone()),
);
let mut io = jsonrpc_core::IoHandler::default();
io.extend_with(SystemApi::to_delegate(FullSystem::new(
client.clone(),
pool,
deny_unsafe,
)));
io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client)));
io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new(
shared_authority_set.clone(),
shared_voter_state,
justification_stream.clone(),
subscription_executor,
finality_proof_provider,
)));
Ok(io)
}
};
Ok(sc_service::PartialComponents {
client,
backend,
task_manager,
keystore_container,
select_chain,
import_queue,
transaction_pool,
other: (rpc_extensions_builder, import_setup, rpc_setup, slot_duration, telemetry),
})
}
pub struct NewFull<C> {
pub task_manager: TaskManager,
pub client: C,
pub overseer_handle: Option<Handle>,
pub network: Arc<sc_network::NetworkService<Block, <Block as BlockT>::Hash>>,
pub rpc_handlers: sc_service::RpcHandlers,
pub backend: Arc<FullBackend>,
}
/// The maximum number of active leaves we forward to the [`Overseer`] on start up.
const MAX_ACTIVE_LEAVES: usize = 4;
/// Returns the active leaves the overseer should start with.
async fn active_leaves(
select_chain: &sc_consensus::LongestChain<FullBackend, Block>,
client: &FullClient,
) -> Result<Vec<BlockInfo>, Error>
where
RuntimeApi: ConstructRuntimeApi<Block, FullClient> + Send + Sync + 'static,
<RuntimeApi as ConstructRuntimeApi<Block, FullClient>>::RuntimeApi:
RequiredApiCollection<StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>,
ExecutorDispatch: NativeExecutionDispatch + 'static,
{
let best_block = select_chain.best_chain().await?;
let mut leaves = select_chain
.leaves()
.await
.unwrap_or_default()
.into_iter()
.filter_map(|hash| {
let number = client.number(hash).ok()??;
// Only consider leaves that are in maximum an uncle of the best block.
if number < best_block.number().saturating_sub(1) || hash == best_block.hash() {
return None
}
let parent_hash = client.header(&BlockId::Hash(hash)).ok()??.parent_hash;
Some(BlockInfo { hash, parent_hash, number })
})
.collect::<Vec<_>>();
// Sort by block number and get the maximum number of leaves
leaves.sort_by_key(|b| b.number);
leaves.push(BlockInfo {
hash: best_block.hash(),
parent_hash: *best_block.parent_hash(),
number: *best_block.number(),
});
Ok(leaves.into_iter().rev().take(MAX_ACTIVE_LEAVES).collect())
}
// Create a new full node.
pub fn new_full(
mut config: Configuration,
program_path: Option<std::path::PathBuf>,
overseer_gen: impl OverseerGen,
) -> Result<NewFull<Arc<FullClient>>, Error>
where
RuntimeApi: ConstructRuntimeApi<Block, FullClient> + Send + Sync + 'static,
<RuntimeApi as ConstructRuntimeApi<Block, FullClient>>::RuntimeApi:
RequiredApiCollection<StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>,
ExecutorDispatch: NativeExecutionDispatch + 'static,
{
let is_collator = false;
let role = config.role.clone();
let force_authoring = config.force_authoring;
let backoff_authoring_blocks =
Some(sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging::default());
let disable_grandpa = config.disable_grandpa;
let name = config.network.node_name.clone();
let sc_service::PartialComponents {
client,
backend,
mut task_manager,
keystore_container,
select_chain,
import_queue,
transaction_pool,
other: (rpc_extensions_builder, import_setup, rpc_setup, slot_duration, mut telemetry),
} = new_partial(&mut config)?;
let prometheus_registry = config.prometheus_registry().cloned();
let overseer_connector = OverseerConnector::default();
let shared_voter_state = rpc_setup;
let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht;
// Note: GrandPa is pushed before the Polkadot-specific protocols. This doesn't change
// anything in terms of behaviour, but makes the logs more consistent with the other
// Substrate nodes.
config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config());
{
use polkadot_network_bridge::{peer_sets_info, IsAuthority};
let is_authority = if role.is_authority() { IsAuthority::Yes } else { IsAuthority::No };
config.network.extra_sets.extend(peer_sets_info(is_authority));
}
let (pov_req_receiver, cfg) = IncomingRequest::get_config_receiver();
config.network.request_response_protocols.push(cfg);
let (chunk_req_receiver, cfg) = IncomingRequest::get_config_receiver();
config.network.request_response_protocols.push(cfg);
let (collation_req_receiver, cfg) = IncomingRequest::get_config_receiver();
config.network.request_response_protocols.push(cfg);
let (available_data_req_receiver, cfg) = IncomingRequest::get_config_receiver();
config.network.request_response_protocols.push(cfg);
let (statement_req_receiver, cfg) = IncomingRequest::get_config_receiver();
config.network.request_response_protocols.push(cfg);
let (dispute_req_receiver, cfg) = IncomingRequest::get_config_receiver();
config.network.request_response_protocols.push(cfg);
let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new(
backend.clone(),
import_setup.1.shared_authority_set().clone(),
vec![],
));
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,
warp_sync: Some(warp_sync),
})?;
if config.offchain_worker.enabled {
let _ = sc_service::build_offchain_workers(
&config,
task_manager.spawn_handle(),
client.clone(),
network.clone(),
);
}
let parachains_db = crate::parachains_db::open_creating(
config.database.path().ok_or(Error::DatabasePathRequired)?.into(),
crate::parachains_db::CacheSizes::default(),
)?;
let availability_config = AvailabilityConfig {
col_data: crate::parachains_db::REAL_COLUMNS.col_availability_data,
col_meta: crate::parachains_db::REAL_COLUMNS.col_availability_meta,
};
let approval_voting_config = ApprovalVotingConfig {
col_data: crate::parachains_db::REAL_COLUMNS.col_approval_data,
slot_duration_millis: slot_duration.as_millis() as u64,
};
let candidate_validation_config = CandidateValidationConfig {
artifacts_cache_path: config
.database
.path()
.ok_or(Error::DatabasePathRequired)?
.join("pvf-artifacts"),
program_path: match program_path {
None => std::env::current_exe()?,
Some(p) => p,
},
};
let chain_selection_config = ChainSelectionConfig {
col_data: crate::parachains_db::REAL_COLUMNS.col_chain_selection_data,
stagnant_check_interval: polkadot_node_core_chain_selection::StagnantCheckInterval::never(),
};
let dispute_coordinator_config = DisputeCoordinatorConfig {
col_data: crate::parachains_db::REAL_COLUMNS.col_dispute_coordinator_data,
};
let rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams {
config,
backend: backend.clone(),
client: client.clone(),
keystore: keystore_container.sync_keystore(),
network: network.clone(),
rpc_extensions_builder: Box::new(rpc_extensions_builder),
transaction_pool: transaction_pool.clone(),
task_manager: &mut task_manager,
on_demand: None,
remote_blockchain: None,
system_rpc_tx,
telemetry: telemetry.as_mut(),
})?;
let (block_import, link_half, babe_link) = import_setup;
let overseer_client = client.clone();
let spawner = task_manager.spawn_handle();
let active_leaves = futures::executor::block_on(active_leaves(&select_chain, &*client))?;
let authority_discovery_service = if role.is_authority() || is_collator {
use futures::StreamExt;
use sc_network::Event;
let authority_discovery_role = if role.is_authority() {
sc_authority_discovery::Role::PublishAndDiscover(keystore_container.keystore())
} else {
// don't publish our addresses when we're only a collator
sc_authority_discovery::Role::Discover
};
let dht_event_stream =
network.event_stream("authority-discovery").filter_map(|e| async move {
match e {
Event::Dht(e) => Some(e),
_ => None,
}
});
let (worker, service) = sc_authority_discovery::new_worker_and_service_with_config(
sc_authority_discovery::WorkerConfig {
publish_non_global_ips: auth_disc_publish_non_global_ips,
..Default::default()
},
client.clone(),
network.clone(),
Box::pin(dht_event_stream),
authority_discovery_role,
prometheus_registry.clone(),
);
task_manager.spawn_handle().spawn("authority-discovery-worker", worker.run());
Some(service)
} else {
None
};
// we'd say let overseer_handler =
// authority_discovery_service.map(|authority_discovery_service|, ...), but in that case we
// couldn't use ? to propagate errors
let local_keystore = keystore_container.local_keystore();
let maybe_params =
local_keystore.and_then(move |k| authority_discovery_service.map(|a| (a, k)));
let overseer_handle = if let Some((authority_discovery_service, keystore)) = maybe_params {
let (overseer, overseer_handle) = overseer_gen
.generate::<sc_service::SpawnTaskHandle, FullClient>(
overseer_connector,
OverseerGenArgs {
leaves: active_leaves,
keystore,
runtime_client: overseer_client.clone(),
parachains_db,
availability_config,
approval_voting_config,
network_service: network.clone(),
authority_discovery_service,
registry: prometheus_registry.as_ref(),
spawner,
candidate_validation_config,
available_data_req_receiver,
chain_selection_config,
chunk_req_receiver,
collation_req_receiver,
dispute_coordinator_config,
dispute_req_receiver,
pov_req_receiver,
statement_req_receiver,
},
)?;
let handle = Handle::new(overseer_handle);
{
let handle = handle.clone();
task_manager.spawn_essential_handle().spawn_blocking(
"overseer",
Box::pin(async move {
use futures::{pin_mut, select, FutureExt};
let forward = polkadot_overseer::forward_events(overseer_client, handle);
let forward = forward.fuse();
let overseer_fut = overseer.run().fuse();
pin_mut!(overseer_fut);
pin_mut!(forward);
select! {
_ = forward => (),
_ = overseer_fut => (),
complete => (),
}
}),
);
}
Some(handle)
} else {
None
};
if role.is_authority() {
let can_author_with =
sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone());
let proposer = sc_basic_authorship::ProposerFactory::new(
task_manager.spawn_handle(),
client.clone(),
transaction_pool,
prometheus_registry.as_ref(),
telemetry.as_ref().map(|x| x.handle()),
);
let client_clone = client.clone();
let overseer_handle =
overseer_handle.as_ref().ok_or(Error::AuthoritiesRequireRealOverseer)?.clone();
let slot_duration = babe_link.config().slot_duration();
let babe_config = sc_consensus_babe::BabeParams {
keystore: keystore_container.sync_keystore(),
client: client.clone(),
select_chain,
block_import,
env: proposer,
sync_oracle: network.clone(),
justification_sync_link: network.clone(),
create_inherent_data_providers: move |parent, ()| {
let client_clone = client_clone.clone();
let overseer_handle = overseer_handle.clone();
async move {
let parachain = polkadot_node_core_parachains_inherent::ParachainsInherentDataProvider::create(
&*client_clone,
overseer_handle,
parent,
)
.await
.map_err(Box::new)?;
let uncles = sc_consensus_uncles::create_uncles_inherent_data_provider(
&*client_clone,
parent,
)?;
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let slot = sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp,
slot_duration,
);
Ok((timestamp, slot, uncles, parachain))
}
},
force_authoring,
backoff_authoring_blocks,
babe_link,
can_author_with,
block_proposal_slot_portion: sc_consensus_babe::SlotProportion::new(2f32 / 3f32),
max_block_proposal_slot_portion: None,
telemetry: telemetry.as_ref().map(|x| x.handle()),
};
let babe = sc_consensus_babe::start_babe(babe_config)?;
task_manager.spawn_essential_handle().spawn_blocking("babe", babe);
}
// 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_opt =
if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None };
let config = sc_finality_grandpa::Config {
// FIXME substrate#1578 make this available through chainspec
gossip_duration: Duration::from_millis(1000),
justification_period: 512,
name: Some(name),
observer_enabled: false,
keystore: keystore_opt,
local_role: role,
telemetry: telemetry.as_ref().map(|x| x.handle()),
};
let enable_grandpa = !disable_grandpa;
if enable_grandpa {
// start the full GRANDPA voter
// NOTE: unlike in substrate we are currently running the full
// GRANDPA voter protocol for all full nodes (regardless of whether
// they're validators or not). at this point the full voter should
// provide better guarantees of block and vote data availability than
// the observer.
// add a custom voting rule to temporarily stop voting for new blocks
// after the given pause block is finalized and restarting after the
// given delay.
let builder = sc_finality_grandpa::VotingRulesBuilder::default();
let voting_rule = builder.build();
let grandpa_config = sc_finality_grandpa::GrandpaParams {
config,
link: link_half,
network: network.clone(),
voting_rule,
prometheus_registry,
shared_voter_state,
telemetry: telemetry.as_ref().map(|x| x.handle()),
};
task_manager.spawn_essential_handle().spawn_blocking(
"grandpa-voter",
sc_finality_grandpa::run_grandpa_voter(grandpa_config)?,
);
}
network_starter.start_network();
Ok(NewFull { task_manager, client, overseer_handle, network, rpc_handlers, backend })
}
pub fn build_full(
config: Configuration,
overseer_gen: impl OverseerGen,
) -> Result<NewFull<Arc<FullClient>>, Error> {
new_full(config, None, overseer_gen)
}
@@ -8,11 +8,12 @@ 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
@@ -34,38 +35,44 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager"
# 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 }
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-grandpa = { 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" }
@@ -89,7 +96,8 @@ 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-bridge-dispatch/std",
@@ -97,16 +105,20 @@ std = [
"pallet-bridge-grandpa/std",
"pallet-bridge-messages/std",
"pallet-grandpa/std",
"pallet-randomness-collective-flip/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",
@@ -22,7 +22,8 @@ use pallet_bridge_eth_poa::{ValidatorsConfiguration, ValidatorsSource};
use sp_std::vec;
pub use crate::kovan::{
genesis_header, genesis_validators, BridgeAuraConfiguration, FinalityVotesCachingInterval, PruningStrategy,
genesis_header, genesis_validators, BridgeAuraConfiguration, FinalityVotesCachingInterval,
PruningStrategy,
};
frame_support::parameter_types! {
@@ -28,19 +28,21 @@
//! 5) receive tokens by providing proof-of-inclusion of PoA transaction.
use bp_currency_exchange::{
Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, Result as ExchangeResult,
Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction,
Result as ExchangeResult,
};
use bp_eth_poa::{transaction_decode_rlp, RawTransaction, RawTransactionReceipt};
use codec::{Decode, Encode};
use frame_support::RuntimeDebug;
use hex_literal::hex;
use scale_info::TypeInfo;
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)]
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
pub struct EthereumTransactionInclusionProof {
/// Hash of the block with transaction.
pub block: sp_core::H256,
@@ -55,9 +57,9 @@ pub struct EthereumTransactionInclusionProof {
///
/// The assumption is that this pair will never appear more than once in
/// transactions included into finalized blocks. This is obviously true
/// for any existing eth-like chain (that keep current tx format), because
/// for any existing eth-like chain (that keep current TX format), because
/// otherwise transaction can be replayed over and over.
#[derive(Encode, Decode, PartialEq, RuntimeDebug)]
#[derive(Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
pub struct EthereumTransactionTag {
/// Account that has locked funds.
pub account: [u8; 20],
@@ -65,7 +67,7 @@ pub struct EthereumTransactionTag {
pub nonce: sp_core::U256,
}
/// Eth transaction from runtime perspective.
/// Ethereum transaction from runtime perspective.
pub struct EthTransaction;
impl MaybeLockFundsTransaction for EthTransaction {
@@ -87,7 +89,7 @@ impl MaybeLockFundsTransaction for EthTransaction {
tx.unsigned.to,
);
return Err(ExchangeError::InvalidTransaction);
return Err(ExchangeError::InvalidTransaction)
}
let mut recipient_raw = sp_core::H256::default();
@@ -100,8 +102,8 @@ impl MaybeLockFundsTransaction for EthTransaction {
len,
);
return Err(ExchangeError::InvalidRecipient);
}
return Err(ExchangeError::InvalidRecipient)
},
}
let amount = tx.unsigned.value.low_u128();
@@ -112,7 +114,7 @@ impl MaybeLockFundsTransaction for EthTransaction {
tx.unsigned.value,
);
return Err(ExchangeError::InvalidAmount);
return Err(ExchangeError::InvalidAmount)
}
Ok(LockFundsTransaction {
@@ -128,7 +130,7 @@ impl MaybeLockFundsTransaction for EthTransaction {
/// 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>(
pub(crate) fn prepare_environment_for_claim<T: pallet_bridge_eth_poa::Config<I>, I: 'static>(
transactions: &[(RawTransaction, RawTransactionReceipt)],
) -> bp_eth_poa::H256 {
use bp_eth_poa::compute_merkle_root;
@@ -161,7 +163,7 @@ pub(crate) fn prepare_ethereum_transaction(
// chain id is 0x11
// sender secret is 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7
let chain_id = 0x11;
let signer = secp256k1::SecretKey::parse(&hex!(
let signer = libsecp256k1::SecretKey::parse(&hex!(
"4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7"
))
.unwrap();
@@ -213,10 +215,7 @@ mod tests {
#[test]
fn invalid_transaction_rejected() {
assert_eq!(
EthTransaction::parse(&Vec::new()),
Err(ExchangeError::InvalidTransaction),
);
assert_eq!(EthTransaction::parse(&Vec::new()), Err(ExchangeError::InvalidTransaction),);
}
#[test]
@@ -21,8 +21,8 @@ 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,
AuraConfiguration, ChainTime as TChainTime, PruningStrategy as BridgePruningStrategy,
ValidatorsConfiguration, ValidatorsSource,
};
use sp_std::prelude::*;
@@ -34,7 +34,7 @@ frame_support::parameter_types! {
kovan_validators_configuration();
}
/// Max number of finalized headers to keep. It is equivalent of ~24 hours of
/// Max number of finalized headers to keep. It is equivalent of around 24 hours of
/// finalized blocks on current Kovan chain.
const FINALIZED_HEADERS_TO_KEEP: u64 = 20_000;
@@ -102,11 +102,14 @@ pub fn genesis_header() -> AuraHeader {
timestamp: 0,
number: 0,
author: Default::default(),
transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(),
transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
.into(),
uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
.into(),
extra_data: vec![],
state_root: hex!("2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2").into(),
receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
.into(),
log_bloom: Default::default(),
gas_used: Default::default(),
gas_limit: 6000000.into(),
@@ -114,8 +117,9 @@ pub fn genesis_header() -> AuraHeader {
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,
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,
],
],
}
@@ -153,12 +157,17 @@ 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);
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;
return None
}
proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone())
@@ -36,24 +36,28 @@ pub mod exchange;
pub mod benches;
pub mod kovan;
pub mod millau_messages;
pub mod parachains;
pub mod rialto_poa;
use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge};
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 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_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::traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{AccountIdLookup, Block as BlockT, 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;
@@ -97,7 +101,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;
@@ -127,8 +131,11 @@ pub mod opaque {
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: Aura,
pub babe: Babe,
pub grandpa: Grandpa,
pub para_validator: Initializer,
pub para_assignment: SessionInfo,
pub authority_discovery: AuthorityDiscovery,
}
}
@@ -146,10 +153,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! {
@@ -164,13 +168,13 @@ parameter_types! {
impl frame_system::Config for Runtime {
/// The basic call filter to use in dispatchable.
type BaseCallFilter = ();
type BaseCallFilter = frame_support::traits::Everything;
/// 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 = 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.
@@ -212,10 +216,41 @@ 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,
};
impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
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_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;
@@ -262,9 +297,9 @@ impl pallet_bridge_currency_exchange::Config<KovanCurrencyExchange> for Runtime
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 = ();
type CallFilter = frame_support::traits::Everything;
type EncodedCall = crate::millau_messages::FromMillauEncodedCall;
type SourceChainAccountId = bp_millau::AccountId;
type TargetChainAccountPublic = MultiSigner;
@@ -278,13 +313,18 @@ 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);
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
// I'm dropping deposited here explicitly to illustrate the fact that it'll update
// `TotalIssuance` on drop
let deposited_amount = deposited.peek();
drop(deposited);
@@ -302,7 +342,7 @@ impl bp_currency_exchange::DepositInto for DepositInto {
);
Ok(())
}
},
_ if deposited_amount == 0 => {
log::error!(
target: "runtime",
@@ -312,7 +352,7 @@ impl bp_currency_exchange::DepositInto for DepositInto {
);
Err(bp_currency_exchange::Error::DepositFailed)
}
},
_ => {
log::error!(
target: "runtime",
@@ -324,7 +364,7 @@ impl bp_currency_exchange::DepositInto for DepositInto {
// we can't return DepositFailed error here, because storage changes were made
Err(bp_currency_exchange::Error::DepositPartiallyFailed)
}
},
}
}
}
@@ -332,10 +372,14 @@ impl bp_currency_exchange::DepositInto for DepositInto {
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;
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 = ();
@@ -346,9 +390,9 @@ parameter_types! {
}
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 = ();
@@ -380,13 +424,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 {
@@ -394,25 +450,23 @@ 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;
type DisabledValidatorsThreshold = ();
// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78)
type WeightInfo = ();
}
impl pallet_authority_discovery::Config for Runtime {
type MaxAuthorities = MaxAuthorities;
}
parameter_types! {
/// This is a pretty unscientific cap.
///
@@ -461,10 +515,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;
@@ -485,16 +540,20 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
type TargetHeaderChain = crate::millau_messages::Millau;
type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier;
type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments<
Runtime,
pallet_balances::Pallet<Runtime>,
GetDeliveryConfirmationTransactionFee,
RootAccountForPayments,
>;
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!(
@@ -503,28 +562,56 @@ construct_runtime!(
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>},
// Must be before session.
Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
TransactionPayment: pallet_transaction_payment::{Pallet, Storage},
// Consensus support.
AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config},
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>},
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event},
ShiftSessionManager: pallet_shift_session_manager::{Pallet},
// Eth-PoA chains bridge modules.
BridgeRialtoPoa: pallet_bridge_eth_poa::<Instance1>::{Pallet, Call, Config, Storage, ValidateUnsigned},
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},
// 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>},
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},
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>},
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>},
ShiftSessionManager: pallet_shift_session_manager::{Pallet},
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.
@@ -550,8 +637,13 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signatu
/// 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>;
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPallets,
>;
impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
@@ -570,7 +662,7 @@ impl_runtime_apis! {
impl sp_api::Metadata<Block> for Runtime {
fn metadata() -> OpaqueMetadata {
Runtime::metadata().into()
OpaqueMetadata::new(Runtime::metadata().into())
}
}
@@ -668,8 +760,9 @@ impl_runtime_apis! {
fn validate_transaction(
source: TransactionSource,
tx: <Block as BlockT>::Extrinsic,
block_hash: <Block as BlockT>::Hash,
) -> TransactionValidity {
Executive::validate_transaction(source, tx)
Executive::validate_transaction(source, tx, block_hash)
}
}
@@ -679,13 +772,145 @@ 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 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>()
}
}
@@ -714,6 +939,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()
}
@@ -760,20 +989,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 {
@@ -801,6 +1021,32 @@ impl_runtime_apis! {
#[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;
use pallet_bridge_currency_exchange::benchmarking::Pallet as BridgeCurrencyExchangeBench;
use pallet_bridge_messages::benchmarking::Pallet as MessagesBench;
let mut list = Vec::<BenchmarkList>::new();
list_benchmark!(list, extra, pallet_bridge_eth_poa, BridgeRialtoPoa);
list_benchmark!(
list,
extra,
pallet_bridge_currency_exchange, BridgeCurrencyExchangeBench::<Runtime, KovanCurrencyExchange>
);
list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::<Runtime, WithMillauMessagesInstance>);
list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeMillauGrandpa);
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> {
@@ -930,7 +1176,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();
@@ -950,14 +1196,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;
@@ -1003,9 +1247,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(
@@ -1031,6 +1274,7 @@ impl_runtime_apis! {
}
}
add_benchmark!(params, batches, pallet_bridge_eth_poa, BridgeRialtoPoa);
add_benchmark!(
params,
batches,
@@ -1054,8 +1298,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,
@@ -1082,7 +1326,8 @@ mod tests {
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();
let mut ext: sp_io::TestExternalities =
SystemConfig::default().build_storage::<Runtime>().unwrap().into();
ext.execute_with(|| {
// initially issuance is zero
assert_eq!(
@@ -1094,7 +1339,10 @@ mod tests {
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);
<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(),
@@ -1125,6 +1373,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(
@@ -1134,21 +1383,25 @@ mod tests {
bp_rialto::max_extrinsic_size(),
bp_rialto::max_extrinsic_weight(),
max_incoming_message_proof_size,
messages::target::maximal_incoming_message_dispatch_weight(bp_rialto::max_extrinsic_weight()),
messages::target::maximal_incoming_message_dispatch_weight(
bp_rialto::max_extrinsic_weight(),
),
);
let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint(
bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _,
bp_millau::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_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _,
bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _,
)
.unwrap_or(u32::MAX);
pallet_bridge_messages::ensure_able_to_receive_confirmation::<Weights>(
bp_rialto::max_extrinsic_size(),
bp_rialto::max_extrinsic_weight(),
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(),
);
}
@@ -1156,7 +1409,9 @@ mod tests {
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);
<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(),
@@ -1164,7 +1419,9 @@ mod tests {
)
.unwrap();
assert_eq!(
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(&existing_account),
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(
&existing_account
),
initial_amount + additional_amount,
);
additional_amount
@@ -1183,10 +1440,18 @@ mod tests {
)
.unwrap();
assert_eq!(
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(&new_account),
<pallet_balances::Pallet<Runtime> as Currency<AccountId>>::free_balance(
&new_account
),
initial_amount + additional_amount,
);
additional_amount
});
}
#[test]
fn call_size() {
const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests
assert!(core::mem::size_of::<Call>() <= MAX_CALL_SIZE);
}
}
@@ -31,25 +31,34 @@ use frame_support::{
weights::{DispatchClass, Weight},
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,158 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Parachains support in Rialto runtime.
use crate::{AccountId, Balance, Balances, BlockNumber, Event, Origin, Registrar, Runtime, Slots};
use frame_support::{parameter_types, weights::Weight};
use frame_system::EnsureRoot;
use polkadot_primitives::v1::ValidatorIndex;
use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots};
use polkadot_runtime_parachains::{
configuration as parachains_configuration, dmp as parachains_dmp, hrmp as parachains_hrmp,
inclusion as parachains_inclusion, initializer as parachains_initializer,
origin as parachains_origin, paras as parachains_paras,
paras_inherent as parachains_paras_inherent, scheduler as parachains_scheduler,
session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump,
};
/// Special `RewardValidators` that does nothing ;)
pub struct RewardValidators;
impl polkadot_runtime_parachains::inclusion::RewardValidators for RewardValidators {
fn reward_backing(_: impl IntoIterator<Item = ValidatorIndex>) {}
fn reward_bitfields(_: impl IntoIterator<Item = ValidatorIndex>) {}
}
// all required parachain modules from `polkadot-runtime-parachains` crate
impl parachains_configuration::Config for Runtime {
type WeightInfo = parachains_configuration::TestWeightInfo;
}
impl parachains_dmp::Config for Runtime {}
impl parachains_hrmp::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Currency = Balances;
}
impl parachains_inclusion::Config for Runtime {
type Event = Event;
type RewardValidators = RewardValidators;
type DisputesHandler = ();
}
impl parachains_initializer::Config for Runtime {
type Randomness = pallet_babe::RandomnessFromOneEpochAgo<Runtime>;
type ForceOrigin = EnsureRoot<AccountId>;
type WeightInfo = ();
}
impl parachains_origin::Config for Runtime {}
impl parachains_paras::Config for Runtime {
type Origin = Origin;
type Event = Event;
type WeightInfo = parachains_paras::TestWeightInfo;
}
impl parachains_paras_inherent::Config for Runtime {}
impl parachains_scheduler::Config for Runtime {}
impl parachains_session_info::Config for Runtime {}
impl parachains_shared::Config for Runtime {}
parameter_types! {
pub const FirstMessageFactorPercent: u64 = 100;
}
impl parachains_ump::Config for Runtime {
type Event = Event;
type UmpSink = ();
type FirstMessageFactorPercent = FirstMessageFactorPercent;
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
}
// required onboarding pallets. We're not going to use auctions or crowdloans, so they're missing
parameter_types! {
pub const ParaDeposit: Balance = 0;
pub const DataDepositPerByte: Balance = 0;
}
impl paras_registrar::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Currency = Balances;
type OnSwap = Slots;
type ParaDeposit = ParaDeposit;
type DataDepositPerByte = DataDepositPerByte;
type WeightInfo = paras_registrar::TestWeightInfo;
}
parameter_types! {
pub const LeasePeriod: BlockNumber = 10 * bp_rialto::MINUTES;
}
impl slots::Config for Runtime {
type Event = Event;
type Currency = Balances;
type Registrar = Registrar;
type LeasePeriod = LeasePeriod;
type WeightInfo = slots::TestWeightInfo;
type LeaseOffset = ();
}
impl paras_sudo_wrapper::Config for Runtime {}
pub struct ZeroWeights;
impl polkadot_runtime_common::paras_registrar::WeightInfo for ZeroWeights {
fn reserve() -> Weight {
0
}
fn register() -> Weight {
0
}
fn force_register() -> Weight {
0
}
fn deregister() -> Weight {
0
}
fn swap() -> Weight {
0
}
}
impl polkadot_runtime_common::slots::WeightInfo for ZeroWeights {
fn force_lease() -> Weight {
0
}
fn manage_lease_period_start(_c: u32, _t: u32) -> Weight {
0
}
fn clear_all_leases() -> Weight {
0
}
fn trigger_onboard() -> Weight {
0
}
}
@@ -23,8 +23,8 @@ use bp_header_chain::InclusionProofVerifier;
use frame_support::RuntimeDebug;
use hex_literal::hex;
use pallet_bridge_eth_poa::{
AuraConfiguration, ChainTime as TChainTime, PruningStrategy as TPruningStrategy, ValidatorsConfiguration,
ValidatorsSource,
AuraConfiguration, ChainTime as TChainTime, PruningStrategy as TPruningStrategy,
ValidatorsConfiguration, ValidatorsSource,
};
use sp_std::prelude::*;
@@ -79,11 +79,14 @@ pub fn genesis_header() -> AuraHeader {
timestamp: 0,
number: 0,
author: Default::default(),
transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(),
transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
.into(),
uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
.into(),
extra_data: vec![],
state_root: hex!("a992d04c791620ed7ed96555a80cf0568355bb4bee2656f46899a4372f25f248").into(),
receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
.into(),
log_bloom: Default::default(),
gas_used: Default::default(),
gas_limit: 0x222222.into(),
@@ -128,12 +131,17 @@ 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);
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;
return None
}
proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone())
@@ -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"] }
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"] }
# Bridge dependencies
@@ -23,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"]
@@ -44,6 +45,7 @@ std = [
"pallet-bridge-grandpa/std",
"pallet-bridge-messages/std",
"pallet-transaction-payment/std",
"scale-info/std",
"sp-core/std",
"sp-runtime/std",
"sp-state-machine/std",
@@ -19,4 +19,5 @@
#![cfg_attr(not(feature = "std"), no_std)]
pub mod messages;
pub mod messages_api;
pub mod messages_benchmarking;
@@ -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)
-177
View File
@@ -1,177 +0,0 @@
90
annualised/MS
Apache-2.0/M
AccountId/MS
api/SM
auth
auths/SM
API/SM
APIs
arg
args
aren
async
Best/MS
benchmarking/MS
BlockId
BFT/M
bitfield/MS
blake2/MS
blockchain/MS
borked
BridgeStorage
BlockNumber
BTC/S
CLI/MS
Chain1
Chain2
ChainSpec
ChainTime
chain_getBlock
choosen
config/MS
crypto/MS
customizable/B
debian/M
decodable/MS
DOT/S
doesn
dispatchables
ed25519
enum/MS
ERC-20
ethereum/MS
externality/MS
extrinsic/MS
extrinsics
fedora/M
FN
FinalizationError
GiB/S
GPL/M
GPLv3/M
Handler/MS
HeaderA
HeaderId
https
implementers
inherent/MS
initialize/RG
instantiate/B
intrinsic/MS
intrinsics
InitiateChange
isn
io
js
keccak256/M
KSM/S
Lane1
Lane2
Lane3
LaneId
kusama/S
KYC/M
keccak
Kovan
merkle/MS
MessageNonce
MessageNonces
Merklized
MaybeOrphan
MaybeExtra
MetricsParams
MessagePayload
misbehavior/SM
misbehaviors
MIN_SIZE
MIT/M
max_value
multivalidator/SM
natively
OldHeader
nonces
number
no_std
ok
oneshot/MS
others'
OutboundMessages
parablock/MS
parachain/MS
parameterize/D
pallet_message_lane
polkadot/MS
pov-block/MS
PoA
PoV/MS
precommit
promethius
promethius'
prune_end
prune_depth
provisioner/MS
redhat/M
repo/MS
receival
RPC/MS
RLP
runtime/MS
Runtime1
Runtime2
rustc/MS
ServiceFactory/MS
SignedExtension
SIZE_FACTOR
sr25519
SS58
SS58Prefix
src
S|N
SURI
source
struct/MS
Submitter1
submitters/MS
subsystem/MS
subsystems'
shouldn
synchronizer
taskmanager/MS
teleport/RG
teleportation/SM
teleporter/SM
teleporters
testnet/MS
trie/MS
trustless/Y
ThisChain
TCP
ubuntu/M
union/MSG
undeliverable
unfinalized
unpruned
unservable/B
unsynced
ve
vec
Vec
validator/SM
verifier
w3f/MS
wasm/M
WND/S
XCM/S
XCMP/M
include/BG
isolate/BG
Instance1
Instance2
Instance42
Pre
Rialto
stringified
Stringified
millau
Millau
-13
View File
@@ -1,13 +0,0 @@
[hunspell]
lang = "en_US"
search_dirs = ["."]
extra_dictionaries = ["lingua.dic"]
skip_os_lookups = true
use_builtin = true
[hunspell.quirks]
# `Type`'s
# 5x
transform_regex = ["^'([^\\s])'$", "^[0-9]+(?:\\.[0-9]*)?x$", "^'s$", "^\\+$", "[><+-]"]
allow_concatenation = true
allow_dashes = true
-1
View File
@@ -1 +0,0 @@
**/target/
-16
View File
@@ -1,16 +0,0 @@
root = true
[*]
indent_style=tab
indent_size=tab
tab_width=4
end_of_line=lf
charset=utf-8
trim_trailing_whitespace=true
max_line_length=100
insert_final_newline=true
[*.{yml,md,yaml,sh}]
indent_style=space
indent_size=2
tab_width=8
end_of_line=lf
-42
View File
@@ -1,42 +0,0 @@
version: 2
updates:
- package-ecosystem: cargo
directory: "/"
schedule:
interval: weekly
time: "03:00"
timezone: Europe/Berlin
open-pull-requests-limit: 20
ignore:
- dependency-name: frame-*
versions:
- ">= 0"
- dependency-name: node-inspect
versions:
- ">= 0"
- dependency-name: pallet-*
versions:
- ">= 0"
- dependency-name: sc-*
versions:
- ">= 0"
- dependency-name: sp-*
versions:
- ">= 0"
- dependency-name: substrate-*
versions:
- ">= 0"
- dependency-name: vergen
versions:
- 4.0.1
- 4.0.2
- 4.1.0
- 4.2.0
- dependency-name: jsonrpc-core
versions:
- 17.0.0
- dependency-name: finality-grandpa
versions:
- 0.13.0
- 0.14.0
rebase-strategy: disabled
-25
View File
@@ -1,25 +0,0 @@
**/target/
**/.env
**/.env2
**/rust-toolchain
hfuzz_target
hfuzz_workspace
**/Cargo.lock
**/*.rs.bk
*.o
*.so
*.rlib
*.dll
.gdb_history
*.exe
.DS_Store
.idea
.vscode
*.iml
*.swp
*.swo
-276
View File
@@ -1,276 +0,0 @@
stages:
- lint
- check
- test
- build
- publish
workflow:
rules:
- if: $CI_COMMIT_TAG
- if: $CI_COMMIT_BRANCH
variables: &default-vars
GIT_STRATEGY: fetch
GIT_DEPTH: 100
CARGO_INCREMENTAL: 0
ARCH: "x86_64"
CI_IMAGE: "paritytech/bridges-ci:production"
RUST_BACKTRACE: full
default:
cache: {}
.collect-artifacts: &collect-artifacts
artifacts:
name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
when: on_success
expire_in: 7 days
paths:
- artifacts/
.kubernetes-build: &kubernetes-build
tags:
- kubernetes-parity-build
interruptible: true
.docker-env: &docker-env
image: "${CI_IMAGE}"
before_script:
- rustup show
- cargo --version
- rustup +nightly show
- cargo +nightly --version
- sccache -s
retry:
max: 2
when:
- runner_system_failure
- unknown_failure
- api_failure
interruptible: true
tags:
- linux-docker
.test-refs: &test-refs
rules:
# FIXME: This is the cause why pipelines wouldn't start. The problem might be in our custom
# mirroring. This should be investigated further, but for now let's have the working
# pipeline.
# - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH
# changes:
# - '**.md'
# - diagrams/*
# - docs/*
# when: never
- if: $CI_PIPELINE_SOURCE == "pipeline"
- if: $CI_PIPELINE_SOURCE == "web"
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_COMMIT_REF_NAME == "master"
- if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs
- if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1
.build-refs: &build-refs
rules:
# won't run on the CI image update pipeline
- if: $CI_PIPELINE_SOURCE == "pipeline"
when: never
- if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1
# 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
- if: $CI_PIPELINE_SOURCE == "schedule" && $PIPELINE == "nightly"
.nightly-test: &nightly-test
rules:
# 2. another is triggered by scripts repo $CI_PIPELINE_SOURCE == "pipeline" it's for the CI image
# update, it also runs all the nightly checks.
- if: $CI_PIPELINE_SOURCE == "pipeline"
#### stage: lint
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
fmt:
stage: lint
<<: *docker-env
<<: *test-refs
script:
- cargo fmt --all -- --check
spellcheck:
stage: lint
<<: *docker-env
<<: *test-refs
script:
- cargo spellcheck check -m 1 -vv $(find modules/currency-exchange/src -name "*.rs")
#### stage: check
check:
stage: check
<<: *docker-env
<<: *test-refs
script: &check-script
- time cargo check --verbose --workspace
# Check Rialto benchmarks runtime
- time cargo check -p rialto-runtime --features runtime-benchmarks --verbose
# Check Millau benchmarks runtime
- time cargo check -p millau-runtime --features runtime-benchmarks --verbose
check-nightly:
stage: check
<<: *docker-env
<<: *nightly-test
script:
- rustup default nightly
- *check-script
#### stage: test
test:
stage: test
<<: *docker-env
<<: *test-refs
script: &test-script
- time cargo test --verbose --workspace
test-nightly:
stage: test
<<: *docker-env
<<: *nightly-test
script:
- rustup default nightly
- *test-script
deny:
stage: test
<<: *docker-env
<<: *nightly-test
<<: *collect-artifacts
script:
- cargo deny check advisories --hide-inclusion-graph
- cargo deny check bans sources --hide-inclusion-graph
after_script:
- mkdir -p ./artifacts
- echo "___Complete logs can be found in the artifacts___"
- cargo deny check advisories 2> advisories.log
- cargo deny check bans sources 2> bans_sources.log
# this job is allowed to fail, only licenses check is important
allow_failure: true
deny-licenses:
stage: test
<<: *docker-env
<<: *test-refs
<<: *collect-artifacts
script:
- cargo deny check licenses --hide-inclusion-graph
after_script:
- mkdir -p ./artifacts
- echo "___Complete logs can be found in the artifacts___"
- cargo deny check licenses 2> licenses.log
#### stage: build
build:
stage: build
<<: *docker-env
<<: *build-refs
<<: *collect-artifacts
# master
script: &build-script
- 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/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/
- mv -v ./ci.Dockerfile ./artifacts/
build-nightly:
stage: build
<<: *docker-env
<<: *collect-artifacts
<<: *nightly-test
script:
- rustup default nightly
- *build-script
#### stage: publish
.build-push-image: &build-push-image
<<: *kubernetes-build
image: quay.io/buildah/stable
<<: *build-refs
variables: &image-variables
GIT_STRATEGY: none
DOCKERFILE: ci.Dockerfile
IMAGE_NAME: docker.io/paritytech/$CI_JOB_NAME
needs:
- job: build
artifacts: true
before_script: &check-versions
- if [[ "${CI_COMMIT_TAG}" ]]; then
VERSION=${CI_COMMIT_TAG};
elif [[ "${CI_COMMIT_REF_NAME}" ]]; then
VERSION=$(echo ${CI_COMMIT_REF_NAME} | sed -r 's#/+#-#g');
fi
- echo "Effective tags = ${VERSION} sha-${CI_COMMIT_SHORT_SHA} latest"
script:
- test "${Docker_Hub_User_Parity}" -a "${Docker_Hub_Pass_Parity}" ||
( echo "no docker credentials provided"; exit 1 )
- cd ./artifacts
- buildah bud
--format=docker
--build-arg VCS_REF="${CI_COMMIT_SHORT_SHA}"
--build-arg BUILD_DATE="$(date +%d-%m-%Y)"
--build-arg PROJECT="${CI_JOB_NAME}"
--build-arg VERSION="${VERSION}"
--tag "${IMAGE_NAME}:${VERSION}"
--tag "${IMAGE_NAME}:sha-${CI_COMMIT_SHORT_SHA}"
--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
- 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"
rialto-bridge-node:
stage: publish
<<: *build-push-image
millau-bridge-node:
stage: publish
<<: *build-push-image
ethereum-poa-relay:
stage: publish
<<: *build-push-image
substrate-relay:
stage: publish
<<: *build-push-image
# FIXME: publish binaries
-80
View File
@@ -1,80 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers
pledge to making participation in our project and our community a harassment-free experience for
everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity
and expression, level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit
permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
### Facilitation, Not Strongarming
We recognise that this software is merely a tool for users to create and maintain their blockchain
of preference. We see that blockchains are naturally community platforms with users being the
ultimate decision makers. We assert that good software will maximise user agency by facilitate
user-expression on the network. As such:
- This project will strive to give users as much choice as is both reasonable and possible over what
protocol they adhere to; but
- use of the project's technical forums, commenting systems, pull requests and issue trackers as a
means to express individual protocol preferences is forbidden.
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are
expected to take appropriate and fair corrective action in response to any instances of unacceptable
behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits,
code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or
to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is
representing the project or its community. Examples of representing a project or community include
using an official project e-mail address, posting via an official social media account, or acting as
an appointed representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting
the project team at admin@parity.io. All complaints will be reviewed and investigated and will
result in a response that is deemed necessary and appropriate to the circumstances. The project team
is obligated to maintain confidentiality with regard to the reporter of an incident. Further
details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face
temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at
https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
-10202
View File
File diff suppressed because it is too large Load Diff
-675
View File
@@ -1,675 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
-216
View File
@@ -1,216 +0,0 @@
# Parity Bridges Common
This is a collection of components for building bridges.
These components include Substrate pallets for syncing headers, passing arbitrary messages, as well
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.
🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧
## Contents
- [Installation](#installation)
- [High-Level Architecture](#high-level-architecture)
- [Project Layout](#project-layout)
- [Running the Bridge](#running-the-bridge)
- [How to send a message](#how-to-send-a-message)
- [Community](#community)
## Installation
To get up and running you need both stable and nightly Rust. Rust nightly is used to build the Web
Assembly (WASM) runtime for the node. You can configure the WASM support as so:
```bash
rustup install nightly
rustup target add wasm32-unknown-unknown --toolchain nightly
```
Once this is configured you can build and test the repo as follows:
```
git clone https://github.com/paritytech/parity-bridges-common.git
cd parity-bridges-common
cargo build --all
cargo test --all
```
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.
## High-Level Architecture
This repo has support for bridging foreign chains together using a combination of Substrate pallets
and external processes called relayers. A bridge chain is one that is able to follow the consensus
of a foreign chain independently. For example, consider the case below where we want to bridge two
Substrate based chains.
```
+---------------+ +---------------+
| | | |
| Rialto | | Millau |
| | | |
+-------+-------+ +-------+-------+
^ ^
| +---------------+ |
| | | |
+-----> | Bridge Relay | <-------+
| |
+---------------+
```
The Millau chain must be able to accept Rialto headers and verify their integrity. It does this by
using a runtime module designed to track GRANDPA finality. Since two blockchains can't interact
directly they need an external service, called a relayer, to communicate. The relayer will subscribe
to new Rialto headers via RPC and submit them to the Millau chain for verification.
Take a look at [Bridge High Level Documentation](./docs/high-level-overview.md) for more in-depth
description of the bridge interaction.
## Project Layout
Here's an overview of how the project is laid out. The main bits are the `node`, which is the actual
"blockchain", the `modules` which are used to build the blockchain's logic (a.k.a the runtime) and
the `relays` which are used to pass messages between chains.
```
├── bin // Node and Runtime for the various Substrate chains
│ └── ...
├── deployments // Useful tools for deploying test networks
│ └── ...
├── 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
│ └── ...
├── primitives // Code shared between modules, runtimes, and relays
│ └── ...
├── relays // Application for sending headers and messages between chains
│ └── ...
└── scripts // Useful development and maintenance scripts
```
## Running the Bridge
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:
- building & running from source,
- building or using Docker images for each individual component,
- running a Docker Compose setup (recommended).
### Using the Source
First you'll need to build the bridge nodes and relay. This can be done as follows:
```bash
# In `parity-bridges-common` folder
cargo build -p rialto-bridge-node
cargo build -p millau-bridge-node
cargo build -p substrate-relay
```
### Running
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.
```bash
# In `parity-bridges-common` folder
./deployments/local-scripts/run-rialto-node.sh
./deployments/local-scripts/run-millau-node.sh
./deployments/local-scripts/relay-millau-to-rialto.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
```
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:
```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 \
```
You should now see the relayer submitting headers from the Millau chain to the Rialto chain.
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
```
_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.
### 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).
### 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.
## Community
Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat
server like, for example, Discord. Most discussions around Polkadot and Substrate happen
in various Element "rooms" (channels). So, joining Element might be a good idea, anyway.
If you are interested in information exchange and development of Polkadot related bridges please
feel free to join the [Polkadot Bridges](https://app.element.io/#/room/#bridges:web3.foundation)
Element channel.
The [Substrate Technical](https://app.element.io/#/room/#substrate-technical:matrix.org) Element
channel is most suited for discussions regarding Substrate itself.
@@ -1,62 +0,0 @@
[package]
name = "rialto-bridge-node"
description = "Substrate node compatible with Rialto runtime"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
build = "build.rs"
homepage = "https://substrate.dev"
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"
structopt = "0.3.21"
serde_json = "1.0.59"
# Bridge dependencies
bp-messages = { path = "../../../primitives/messages" }
bp-runtime = { path = "../../../primitives/runtime" }
bp-rialto = { path = "../../../primitives/chain-rialto" }
pallet-bridge-messages = { path = "../../../modules/messages" }
rialto-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" }
node-inspect = { 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"] }
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-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-keystore = { 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-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-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" }
[build-dependencies]
substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
[features]
default = []
runtime-benchmarks = [
"rialto-runtime/runtime-benchmarks",
]
@@ -1,483 +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/>.
//! Service and ServiceFactory implementation. Specialized wrapper over substrate service.
// =====================================================================================
// =====================================================================================
// =====================================================================================
// 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 :)
// =====================================================================================
// =====================================================================================
// =====================================================================================
//! Service and ServiceFactory implementation. Specialized wrapper over substrate service.
use rialto_runtime::{self, opaque::Block, RuntimeApi};
use sc_client_api::{ExecutorProvider, RemoteBackend};
use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams};
use sc_executor::native_executor_instance;
pub use sc_executor::NativeExecutor;
use sc_keystore::LocalKeystore;
use sc_service::{error::Error as ServiceError, Configuration, TaskManager};
use sc_telemetry::{Telemetry, TelemetryWorker};
use sp_consensus::SlotData;
use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;
use std::{sync::Arc, time::Duration};
// Our native executor instance.
native_executor_instance!(
pub Executor,
rialto_runtime::api::dispatch,
rialto_runtime::native_version,
frame_benchmarking::benchmarking::HostFunctions,
);
type FullClient = sc_service::TFullClient<Block, RuntimeApi, Executor>;
type FullBackend = sc_service::TFullBackend<Block>;
type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
#[allow(clippy::type_complexity)]
pub fn new_partial(
config: &Configuration,
) -> Result<
sc_service::PartialComponents<
FullClient,
FullBackend,
FullSelectChain,
sp_consensus::DefaultImportQueue<Block, FullClient>,
sc_transaction_pool::FullPool<Block, FullClient>,
(
sc_finality_grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, FullSelectChain>,
sc_finality_grandpa::LinkHalf<Block, FullClient, FullSelectChain>,
Option<Telemetry>,
),
>,
ServiceError,
> {
if config.keystore_remote.is_some() {
return Err(ServiceError::Other("Remote Keystores are not supported.".to_string()));
}
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, task_manager) = sc_service::new_full_parts::<Block, RuntimeApi, Executor>(
config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
)?;
let client = Arc::new(client);
let telemetry = telemetry.map(|(worker, telemetry)| {
task_manager.spawn_handle().spawn("telemetry", worker.run());
telemetry
});
let select_chain = sc_consensus::LongestChain::new(backend.clone());
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 (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import(
client.clone(),
&(client.clone() as Arc<_>),
select_chain.clone(),
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.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,
);
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,
backend,
task_manager,
import_queue,
keystore_container,
select_chain,
transaction_pool,
other: (grandpa_block_import, grandpa_link, telemetry),
})
}
fn remote_keystore(_url: &str) -> 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`
Err("Remote Keystore not supported.")
}
/// Builds a new service for a full client.
pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError> {
let sc_service::PartialComponents {
client,
backend,
mut task_manager,
import_queue,
mut keystore_container,
select_chain,
transaction_pool,
other: (block_import, grandpa_link, mut telemetry),
} = new_partial(&config)?;
if let Some(url) = &config.keystore_remote {
match remote_keystore(url) {
Ok(k) => keystore_container.set_remote_keystore(k),
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());
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,
})?;
if config.offchain_worker.enabled {
sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone());
}
let role = config.role.clone();
let force_authoring = config.force_authoring;
let backoff_authoring_blocks: Option<()> = None;
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 rpc_extensions_builder = {
use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider;
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler};
use sc_rpc::DenyUnsafe;
use substrate_frame_rpc_system::{FullSystem, SystemApi};
let backend = backend.clone();
let client = client.clone();
let pool = transaction_pool.clone();
let justification_stream = grandpa_link.justification_stream();
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()));
Box::new(move |_, subscription_executor| {
let mut io = jsonrpc_core::IoHandler::default();
io.extend_with(SystemApi::to_delegate(FullSystem::new(
client.clone(),
pool.clone(),
DenyUnsafe::No,
)));
io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(
client.clone(),
)));
io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new(
shared_authority_set.clone(),
shared_voter_state.clone(),
justification_stream.clone(),
subscription_executor,
finality_proof_provider.clone(),
)));
io
})
};
let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams {
network: network.clone(),
client: client.clone(),
keystore: keystore_container.sync_keystore(),
task_manager: &mut task_manager,
transaction_pool: transaction_pool.clone(),
rpc_extensions_builder,
on_demand: None,
remote_blockchain: None,
backend,
system_rpc_tx,
config,
telemetry: telemetry.as_mut(),
})?;
if role.is_authority() {
let proposer_factory = sc_basic_authorship::ProposerFactory::new(
task_manager.spawn_handle(),
client.clone(),
transaction_pool,
prometheus_registry.as_ref(),
telemetry.as_ref().map(|x| x.handle()),
);
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 slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp,
raw_slot_duration,
);
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()),
})?;
// 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);
}
// 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 grandpa_config = sc_finality_grandpa::Config {
// FIXME #1578 make this available through chainspec
gossip_duration: Duration::from_millis(333),
justification_period: 512,
name: Some(name),
observer_enabled: false,
keystore,
local_role: role,
telemetry: telemetry.as_ref().map(|x| x.handle()),
};
if enable_grandpa {
// start the full GRANDPA voter
// NOTE: non-authorities could run the GRANDPA observer protocol, but at
// this point the full voter should provide better guarantees of block
// and vote data availability than the observer. The observer has not
// been tested extensively yet and having most nodes in a network run it
// could lead to finality stalls.
let grandpa_config = sc_finality_grandpa::GrandpaParams {
config: grandpa_config,
link: grandpa_link,
network,
voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(),
prometheus_registry,
shared_voter_state,
telemetry: telemetry.as_ref().map(|x| x.handle()),
};
// 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())?,
);
}
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)
}
@@ -1,140 +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/>.
//! Primitives that may be used at (bridges) runtime level.
#![cfg_attr(not(feature = "std"), no_std)]
use codec::Encode;
use sp_core::hash::H256;
use sp_io::hashing::blake2_256;
use sp_std::convert::TryFrom;
pub use chain::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf};
pub use storage_proof::{Error as StorageProofError, StorageProofChecker};
#[cfg(feature = "std")]
pub use storage_proof::craft_valid_storage_proof;
pub mod messages;
mod chain;
mod storage_proof;
/// Use this when something must be shared among all instances.
pub const NO_INSTANCE_ID: ChainId = [0, 0, 0, 0];
/// Bridge-with-Rialto instance id.
pub const RIALTO_CHAIN_ID: ChainId = *b"rlto";
/// Bridge-with-Millau instance id.
pub const MILLAU_CHAIN_ID: ChainId = *b"mlau";
/// Bridge-with-Polkadot instance id.
pub const POLKADOT_CHAIN_ID: ChainId = *b"pdot";
/// Bridge-with-Kusama instance id.
pub const KUSAMA_CHAIN_ID: ChainId = *b"ksma";
/// Bridge-with-Rococo instance id.
pub const ROCOCO_CHAIN_ID: ChainId = *b"roco";
/// Bridge-with-Wococo instance id.
pub const WOCOCO_CHAIN_ID: ChainId = *b"woco";
/// Call-dispatch module prefix.
pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/dispatch";
/// A unique prefix for entropy when generating cross-chain account IDs.
pub const ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/account";
/// A unique prefix for entropy when generating a cross-chain account ID for the Root account.
pub const ROOT_ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/root";
/// Unique identifier of the chain.
///
/// In addition to its main function (identifying the chain), this type may also be used to
/// identify module instance. We have a bunch of pallets that may be used in different bridges. E.g.
/// messages pallet may be deployed twice in the same runtime to bridge ThisChain with Chain1 and Chain2.
/// Sometimes we need to be able to identify deployed instance dynamically. This type may be used for that.
pub type ChainId = [u8; 4];
/// Type of accounts on the source chain.
pub enum SourceAccount<T> {
/// An account that belongs to Root (privileged origin).
Root,
/// A non-priviledged account.
///
/// The embedded account ID may or may not have a private key depending on the "owner" of the
/// account (private key, pallet, proxy, etc.).
Account(T),
}
/// Derive an account ID from a foreign account ID.
///
/// This function returns an encoded Blake2 hash. It is the responsibility of the caller to ensure
/// this can be successfully decoded into an AccountId.
///
/// The `bridge_id` is used to provide extra entropy when producing account IDs. This helps prevent
/// AccountId collisions between different bridges on a single target chain.
///
/// Note: If the same `bridge_id` is used across different chains (for example, if one source chain
/// is bridged to multiple target chains), then all the derived accounts would be the same across
/// the different chains. This could negatively impact users' privacy across chains.
pub fn derive_account_id<AccountId>(bridge_id: ChainId, id: SourceAccount<AccountId>) -> H256
where
AccountId: Encode,
{
match id {
SourceAccount::Root => (ROOT_ACCOUNT_DERIVATION_PREFIX, bridge_id).using_encoded(blake2_256),
SourceAccount::Account(id) => (ACCOUNT_DERIVATION_PREFIX, bridge_id, id).using_encoded(blake2_256),
}
.into()
}
/// Derive the account ID of the shared relayer fund account.
///
/// This account is used to collect fees for relayers that are passing messages across the bridge.
///
/// The account ID can be the same across different instances of `pallet-bridge-messages` if the same
/// `bridge_id` is used.
pub fn derive_relayer_fund_account_id(bridge_id: ChainId) -> H256 {
("relayer-fund-account", bridge_id).using_encoded(blake2_256).into()
}
/// Anything that has size.
pub trait Size {
/// Return approximate size of this object (in bytes).
///
/// This function should be lightweight. The result should not necessary be absolutely
/// accurate.
fn size_hint(&self) -> u32;
}
impl Size for () {
fn size_hint(&self) -> u32 {
0
}
}
/// Pre-computed size.
pub struct PreComputedSize(pub usize);
impl Size for PreComputedSize {
fn size_hint(&self) -> u32 {
u32::try_from(self.0).unwrap_or(u32::MAX)
}
}
@@ -1,237 +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/>.
//! Millau-to-Rialto messages sync entrypoint.
use crate::messages_lane::{
select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate,
};
use crate::messages_source::SubstrateMessagesSource;
use crate::messages_target::SubstrateMessagesTarget;
use bp_messages::MessageNonce;
use bp_runtime::{MILLAU_CHAIN_ID, RIALTO_CHAIN_ID};
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use codec::Encode;
use frame_support::dispatch::GetDispatchInfo;
use messages_relay::message_lane::MessageLane;
use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams};
use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams};
use relay_substrate_client::{
metrics::{FloatStorageValueMetric, StorageProofOverheadMetric},
Chain, TransactionSignScheme,
};
use sp_core::{Bytes, Pair};
use std::{ops::RangeInclusive, time::Duration};
/// Millau-to-Rialto message lane.
pub type MillauMessagesToRialto =
SubstrateMessageLaneToSubstrate<Millau, MillauSigningParams, Rialto, RialtoSigningParams>;
impl SubstrateMessageLane for MillauMessagesToRialto {
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD;
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD;
const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD;
const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD;
const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD;
type SourceChain = Millau;
type TargetChain = Rialto;
fn source_transactions_author(&self) -> bp_millau::AccountId {
(*self.source_sign.public().as_array_ref()).into()
}
fn make_messages_receiving_proof_transaction(
&self,
transaction_nonce: <Millau as Chain>::Index,
_generated_at_block: RialtoHeaderId,
proof: <Self as MessageLane>::MessagesReceivingProof,
) -> Bytes {
let (relayers_state, proof) = proof;
let call: millau_runtime::Call =
millau_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into();
let call_weight = call.get_dispatch_info().weight;
let genesis_hash = *self.source_client.genesis_hash();
let transaction = Millau::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call);
log::trace!(
target: "bridge",
"Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}",
call_weight,
bp_millau::max_extrinsic_weight(),
transaction.encode().len(),
bp_millau::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
fn target_transactions_author(&self) -> bp_rialto::AccountId {
(*self.target_sign.public().as_array_ref()).into()
}
fn make_messages_delivery_transaction(
&self,
transaction_nonce: <Rialto as Chain>::Index,
_generated_at_header: MillauHeaderId,
_nonces: RangeInclusive<MessageNonce>,
proof: <Self as MessageLane>::MessagesProof,
) -> Bytes {
let (dispatch_weight, proof) = proof;
let FromBridgedChainMessagesProof {
ref nonces_start,
ref nonces_end,
..
} = proof;
let messages_count = nonces_end - nonces_start + 1;
let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof(
self.relayer_id_at_source.clone(),
proof,
messages_count as _,
dispatch_weight,
)
.into();
let call_weight = call.get_dispatch_info().weight;
let genesis_hash = *self.target_client.genesis_hash();
let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
log::trace!(
target: "bridge",
"Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}",
call_weight,
bp_rialto::max_extrinsic_weight(),
transaction.encode().len(),
bp_rialto::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
}
/// Millau node as messages source.
type MillauSourceClient =
SubstrateMessagesSource<Millau, MillauMessagesToRialto, millau_runtime::WithRialtoMessagesInstance>;
/// Rialto node as messages target.
type RialtoTargetClient =
SubstrateMessagesTarget<Rialto, MillauMessagesToRialto, rialto_runtime::WithMillauMessagesInstance>;
/// Run Millau-to-Rialto messages sync.
pub async fn run(
params: MessagesRelayParams<Millau, MillauSigningParams, Rialto, RialtoSigningParams>,
) -> Result<(), String> {
let stall_timeout = Duration::from_secs(5 * 60);
let relayer_id_at_millau = (*params.source_sign.public().as_array_ref()).into();
let lane_id = params.lane_id;
let source_client = params.source_client;
let lane = MillauMessagesToRialto {
source_client: source_client.clone(),
source_sign: params.source_sign,
target_client: params.target_client.clone(),
target_sign: params.target_sign,
relayer_id_at_source: relayer_id_at_millau,
};
// 2/3 is reserved for proofs and tx overhead
let max_messages_size_in_single_batch = bp_rialto::max_extrinsic_size() / 3;
// TODO: use Millau weights after https://github.com/paritytech/parity-bridges-common/issues/390
let (max_messages_in_single_batch, max_messages_weight_in_single_batch) =
select_delivery_transaction_limits::<pallet_bridge_messages::weights::RialtoWeight<millau_runtime::Runtime>>(
bp_rialto::max_extrinsic_weight(),
bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
);
log::info!(
target: "bridge",
"Starting Millau -> Rialto messages relay.\n\t\
Millau relayer account id: {:?}\n\t\
Max messages in single transaction: {}\n\t\
Max messages size in single transaction: {}\n\t\
Max messages weight in single transaction: {}",
lane.relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
);
messages_relay::message_lane_loop::run(
messages_relay::message_lane_loop::Params {
lane: lane_id,
source_tick: Millau::AVERAGE_BLOCK_INTERVAL,
target_tick: Rialto::AVERAGE_BLOCK_INTERVAL,
reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY,
stall_timeout,
delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams {
max_unrewarded_relayer_entries_at_target: bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
max_unconfirmed_nonces_at_target: bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
max_messages_in_single_batch,
max_messages_weight_in_single_batch,
max_messages_size_in_single_batch,
relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic,
},
},
MillauSourceClient::new(
source_client.clone(),
lane.clone(),
lane_id,
RIALTO_CHAIN_ID,
params.target_to_source_headers_relay,
),
RialtoTargetClient::new(
params.target_client,
lane,
lane_id,
MILLAU_CHAIN_ID,
params.source_to_target_headers_relay,
),
relay_utils::relay_metrics(
Some(messages_relay::message_lane_loop::metrics_prefix::<
MillauMessagesToRialto,
>(&lane_id)),
params.metrics_params,
)
.standalone_metric(|registry, prefix| {
StorageProofOverheadMetric::new(
registry,
prefix,
source_client.clone(),
"millau_storage_proof_overhead".into(),
"Millau storage proof overhead".into(),
)
})?
.standalone_metric(|registry, prefix| {
FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new(
registry,
prefix,
source_client,
sp_core::storage::StorageKey(
millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec(),
),
Some(millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE),
"millau_rialto_to_millau_conversion_rate".into(),
"Rialto to Millau tokens conversion rate (used by Rialto)".into(),
)
})?
.into_params(),
futures::future::pending(),
)
.await
}
@@ -1,236 +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/>.
//! Rialto-to-Millau messages sync entrypoint.
use crate::messages_lane::{
select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate,
};
use crate::messages_source::SubstrateMessagesSource;
use crate::messages_target::SubstrateMessagesTarget;
use bp_messages::MessageNonce;
use bp_runtime::{MILLAU_CHAIN_ID, RIALTO_CHAIN_ID};
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use codec::Encode;
use frame_support::dispatch::GetDispatchInfo;
use messages_relay::message_lane::MessageLane;
use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams};
use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams};
use relay_substrate_client::{
metrics::{FloatStorageValueMetric, StorageProofOverheadMetric},
Chain, TransactionSignScheme,
};
use sp_core::{Bytes, Pair};
use std::{ops::RangeInclusive, time::Duration};
/// Rialto-to-Millau message lane.
pub type RialtoMessagesToMillau =
SubstrateMessageLaneToSubstrate<Rialto, RialtoSigningParams, Millau, MillauSigningParams>;
impl SubstrateMessageLane for RialtoMessagesToMillau {
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD;
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD;
const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD;
const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD;
const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD;
type SourceChain = Rialto;
type TargetChain = Millau;
fn source_transactions_author(&self) -> bp_rialto::AccountId {
(*self.source_sign.public().as_array_ref()).into()
}
fn make_messages_receiving_proof_transaction(
&self,
transaction_nonce: <Rialto as Chain>::Index,
_generated_at_block: MillauHeaderId,
proof: <Self as MessageLane>::MessagesReceivingProof,
) -> Bytes {
let (relayers_state, proof) = proof;
let call: rialto_runtime::Call =
rialto_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into();
let call_weight = call.get_dispatch_info().weight;
let genesis_hash = *self.source_client.genesis_hash();
let transaction = Rialto::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call);
log::trace!(
target: "bridge",
"Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}",
call_weight,
bp_rialto::max_extrinsic_weight(),
transaction.encode().len(),
bp_rialto::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
fn target_transactions_author(&self) -> bp_millau::AccountId {
(*self.target_sign.public().as_array_ref()).into()
}
fn make_messages_delivery_transaction(
&self,
transaction_nonce: <Millau as Chain>::Index,
_generated_at_header: RialtoHeaderId,
_nonces: RangeInclusive<MessageNonce>,
proof: <Self as MessageLane>::MessagesProof,
) -> Bytes {
let (dispatch_weight, proof) = proof;
let FromBridgedChainMessagesProof {
ref nonces_start,
ref nonces_end,
..
} = proof;
let messages_count = nonces_end - nonces_start + 1;
let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof(
self.relayer_id_at_source.clone(),
proof,
messages_count as _,
dispatch_weight,
)
.into();
let call_weight = call.get_dispatch_info().weight;
let genesis_hash = *self.target_client.genesis_hash();
let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
log::trace!(
target: "bridge",
"Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}",
call_weight,
bp_millau::max_extrinsic_weight(),
transaction.encode().len(),
bp_millau::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
}
/// Rialto node as messages source.
type RialtoSourceClient =
SubstrateMessagesSource<Rialto, RialtoMessagesToMillau, rialto_runtime::WithMillauMessagesInstance>;
/// Millau node as messages target.
type MillauTargetClient =
SubstrateMessagesTarget<Millau, RialtoMessagesToMillau, millau_runtime::WithRialtoMessagesInstance>;
/// Run Rialto-to-Millau messages sync.
pub async fn run(
params: MessagesRelayParams<Rialto, RialtoSigningParams, Millau, MillauSigningParams>,
) -> Result<(), String> {
let stall_timeout = Duration::from_secs(5 * 60);
let relayer_id_at_rialto = (*params.source_sign.public().as_array_ref()).into();
let lane_id = params.lane_id;
let source_client = params.source_client;
let lane = RialtoMessagesToMillau {
source_client: source_client.clone(),
source_sign: params.source_sign,
target_client: params.target_client.clone(),
target_sign: params.target_sign,
relayer_id_at_source: relayer_id_at_rialto,
};
// 2/3 is reserved for proofs and tx overhead
let max_messages_size_in_single_batch = bp_millau::max_extrinsic_size() / 3;
let (max_messages_in_single_batch, max_messages_weight_in_single_batch) =
select_delivery_transaction_limits::<pallet_bridge_messages::weights::RialtoWeight<rialto_runtime::Runtime>>(
bp_millau::max_extrinsic_weight(),
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
);
log::info!(
target: "bridge",
"Starting Rialto -> Millau messages relay.\n\t\
Rialto relayer account id: {:?}\n\t\
Max messages in single transaction: {}\n\t\
Max messages size in single transaction: {}\n\t\
Max messages weight in single transaction: {}",
lane.relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
);
messages_relay::message_lane_loop::run(
messages_relay::message_lane_loop::Params {
lane: lane_id,
source_tick: Rialto::AVERAGE_BLOCK_INTERVAL,
target_tick: Millau::AVERAGE_BLOCK_INTERVAL,
reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY,
stall_timeout,
delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams {
max_unrewarded_relayer_entries_at_target: bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
max_unconfirmed_nonces_at_target: bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
max_messages_in_single_batch,
max_messages_weight_in_single_batch,
max_messages_size_in_single_batch,
relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic,
},
},
RialtoSourceClient::new(
source_client.clone(),
lane.clone(),
lane_id,
MILLAU_CHAIN_ID,
params.target_to_source_headers_relay,
),
MillauTargetClient::new(
params.target_client,
lane,
lane_id,
RIALTO_CHAIN_ID,
params.source_to_target_headers_relay,
),
relay_utils::relay_metrics(
Some(messages_relay::message_lane_loop::metrics_prefix::<
RialtoMessagesToMillau,
>(&lane_id)),
params.metrics_params,
)
.standalone_metric(|registry, prefix| {
StorageProofOverheadMetric::new(
registry,
prefix,
source_client.clone(),
"rialto_storage_proof_overhead".into(),
"Rialto storage proof overhead".into(),
)
})?
.standalone_metric(|registry, prefix| {
FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new(
registry,
prefix,
source_client,
sp_core::storage::StorageKey(
rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec(),
),
Some(rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE),
"rialto_millau_to_rialto_conversion_rate".into(),
"Millau to Rialto tokens conversion rate (used by Millau)".into(),
)
})?
.into_params(),
futures::future::pending(),
)
.await
}
@@ -1,227 +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/>.
//! Rococo-to-Wococo messages sync entrypoint.
use crate::messages_lane::{
select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate,
};
use crate::messages_source::SubstrateMessagesSource;
use crate::messages_target::SubstrateMessagesTarget;
use bp_messages::MessageNonce;
use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID};
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use codec::Encode;
use messages_relay::message_lane::MessageLane;
use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams};
use relay_substrate_client::{metrics::StorageProofOverheadMetric, Chain, TransactionSignScheme};
use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo};
use sp_core::{Bytes, Pair};
use std::{ops::RangeInclusive, time::Duration};
/// Rococo-to-Wococo message lane.
pub type RococoMessagesToWococo =
SubstrateMessageLaneToSubstrate<Rococo, RococoSigningParams, Wococo, WococoSigningParams>;
impl SubstrateMessageLane for RococoMessagesToWococo {
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD;
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD;
const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_rococo::FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD;
const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD;
const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD;
type SourceChain = Rococo;
type TargetChain = Wococo;
fn source_transactions_author(&self) -> bp_rococo::AccountId {
(*self.source_sign.public().as_array_ref()).into()
}
fn make_messages_receiving_proof_transaction(
&self,
transaction_nonce: <Rococo as Chain>::Index,
_generated_at_block: WococoHeaderId,
proof: <Self as MessageLane>::MessagesReceivingProof,
) -> Bytes {
let (relayers_state, proof) = proof;
let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo(
relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_delivery_proof(
proof,
relayers_state,
),
);
let genesis_hash = *self.source_client.genesis_hash();
let transaction = Rococo::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call);
log::trace!(
target: "bridge",
"Prepared Wococo -> Rococo confirmation transaction. Weight: <unknown>/{}, size: {}/{}",
bp_rococo::max_extrinsic_weight(),
transaction.encode().len(),
bp_rococo::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
fn target_transactions_author(&self) -> bp_wococo::AccountId {
(*self.target_sign.public().as_array_ref()).into()
}
fn make_messages_delivery_transaction(
&self,
transaction_nonce: <Wococo as Chain>::Index,
_generated_at_header: RococoHeaderId,
_nonces: RangeInclusive<MessageNonce>,
proof: <Self as MessageLane>::MessagesProof,
) -> Bytes {
let (dispatch_weight, proof) = proof;
let FromBridgedChainMessagesProof {
ref nonces_start,
ref nonces_end,
..
} = proof;
let messages_count = nonces_end - nonces_start + 1;
let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo(
relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_proof(
self.relayer_id_at_source.clone(),
proof,
messages_count as _,
dispatch_weight,
),
);
let genesis_hash = *self.target_client.genesis_hash();
let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
log::trace!(
target: "bridge",
"Prepared Rococo -> Wococo delivery transaction. Weight: <unknown>/{}, size: {}/{}",
bp_wococo::max_extrinsic_weight(),
transaction.encode().len(),
bp_wococo::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
}
/// Rococo node as messages source.
type RococoSourceClient =
SubstrateMessagesSource<Rococo, RococoMessagesToWococo, relay_rococo_client::runtime::WithWococoMessagesInstance>;
/// Wococo node as messages target.
type WococoTargetClient =
SubstrateMessagesTarget<Wococo, RococoMessagesToWococo, relay_wococo_client::runtime::WithRococoMessagesInstance>;
/// Run Rococo-to-Wococo messages sync.
pub async fn run(
params: MessagesRelayParams<Rococo, RococoSigningParams, Wococo, WococoSigningParams>,
) -> Result<(), String> {
let stall_timeout = Duration::from_secs(5 * 60);
let relayer_id_at_rococo = (*params.source_sign.public().as_array_ref()).into();
let lane_id = params.lane_id;
let source_client = params.source_client;
let lane = RococoMessagesToWococo {
source_client: source_client.clone(),
source_sign: params.source_sign,
target_client: params.target_client.clone(),
target_sign: params.target_sign,
relayer_id_at_source: relayer_id_at_rococo,
};
// 2/3 is reserved for proofs and tx overhead
let max_messages_size_in_single_batch = bp_wococo::max_extrinsic_size() / 3;
// we don't know exact weights of the Wococo runtime. So to guess weights we'll be using
// weights from Rialto and then simply dividing it by x2.
let (max_messages_in_single_batch, max_messages_weight_in_single_batch) =
select_delivery_transaction_limits::<pallet_bridge_messages::weights::RialtoWeight<rialto_runtime::Runtime>>(
bp_wococo::max_extrinsic_weight(),
bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
);
let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = (
max_messages_in_single_batch / 2,
max_messages_weight_in_single_batch / 2,
);
log::info!(
target: "bridge",
"Starting Rococo -> Wococo messages relay.\n\t\
Rococo relayer account id: {:?}\n\t\
Max messages in single transaction: {}\n\t\
Max messages size in single transaction: {}\n\t\
Max messages weight in single transaction: {}",
lane.relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
);
messages_relay::message_lane_loop::run(
messages_relay::message_lane_loop::Params {
lane: lane_id,
source_tick: Rococo::AVERAGE_BLOCK_INTERVAL,
target_tick: Wococo::AVERAGE_BLOCK_INTERVAL,
reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY,
stall_timeout,
delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams {
max_unrewarded_relayer_entries_at_target: bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
max_unconfirmed_nonces_at_target: bp_wococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
max_messages_in_single_batch,
max_messages_weight_in_single_batch,
max_messages_size_in_single_batch,
relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic,
},
},
RococoSourceClient::new(
source_client.clone(),
lane.clone(),
lane_id,
WOCOCO_CHAIN_ID,
params.target_to_source_headers_relay,
),
WococoTargetClient::new(
params.target_client,
lane,
lane_id,
ROCOCO_CHAIN_ID,
params.source_to_target_headers_relay,
),
relay_utils::relay_metrics(
Some(messages_relay::message_lane_loop::metrics_prefix::<
RococoMessagesToWococo,
>(&lane_id)),
params.metrics_params,
)
.standalone_metric(|registry, prefix| {
StorageProofOverheadMetric::new(
registry,
prefix,
source_client.clone(),
"rococo_storage_proof_overhead".into(),
"Rococo storage proof overhead".into(),
)
})?
.into_params(),
futures::future::pending(),
)
.await
}
@@ -1,227 +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/>.
//! Wococo-to-Rococo messages sync entrypoint.
use crate::messages_lane::{
select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate,
};
use crate::messages_source::SubstrateMessagesSource;
use crate::messages_target::SubstrateMessagesTarget;
use bp_messages::MessageNonce;
use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID};
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use codec::Encode;
use messages_relay::message_lane::MessageLane;
use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams};
use relay_substrate_client::{metrics::StorageProofOverheadMetric, Chain, TransactionSignScheme};
use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo};
use sp_core::{Bytes, Pair};
use std::{ops::RangeInclusive, time::Duration};
/// Wococo-to-Rococo message lane.
pub type WococoMessagesToRococo =
SubstrateMessageLaneToSubstrate<Wococo, WococoSigningParams, Rococo, RococoSigningParams>;
impl SubstrateMessageLane for WococoMessagesToRococo {
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD;
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD;
const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_wococo::FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD;
const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD;
const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD;
type SourceChain = Wococo;
type TargetChain = Rococo;
fn source_transactions_author(&self) -> bp_wococo::AccountId {
(*self.source_sign.public().as_array_ref()).into()
}
fn make_messages_receiving_proof_transaction(
&self,
transaction_nonce: <Wococo as Chain>::Index,
_generated_at_block: RococoHeaderId,
proof: <Self as MessageLane>::MessagesReceivingProof,
) -> Bytes {
let (relayers_state, proof) = proof;
let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo(
relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_delivery_proof(
proof,
relayers_state,
),
);
let genesis_hash = *self.source_client.genesis_hash();
let transaction = Wococo::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call);
log::trace!(
target: "bridge",
"Prepared Rococo -> Wococo confirmation transaction. Weight: <unknown>/{}, size: {}/{}",
bp_wococo::max_extrinsic_weight(),
transaction.encode().len(),
bp_wococo::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
fn target_transactions_author(&self) -> bp_rococo::AccountId {
(*self.target_sign.public().as_array_ref()).into()
}
fn make_messages_delivery_transaction(
&self,
transaction_nonce: <Rococo as Chain>::Index,
_generated_at_header: WococoHeaderId,
_nonces: RangeInclusive<MessageNonce>,
proof: <Self as MessageLane>::MessagesProof,
) -> Bytes {
let (dispatch_weight, proof) = proof;
let FromBridgedChainMessagesProof {
ref nonces_start,
ref nonces_end,
..
} = proof;
let messages_count = nonces_end - nonces_start + 1;
let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo(
relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_proof(
self.relayer_id_at_source.clone(),
proof,
messages_count as _,
dispatch_weight,
),
);
let genesis_hash = *self.target_client.genesis_hash();
let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
log::trace!(
target: "bridge",
"Prepared Wococo -> Rococo delivery transaction. Weight: <unknown>/{}, size: {}/{}",
bp_rococo::max_extrinsic_weight(),
transaction.encode().len(),
bp_rococo::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
}
/// Wococo node as messages source.
type WococoSourceClient =
SubstrateMessagesSource<Wococo, WococoMessagesToRococo, relay_wococo_client::runtime::WithRococoMessagesInstance>;
/// Rococo node as messages target.
type RococoTargetClient =
SubstrateMessagesTarget<Rococo, WococoMessagesToRococo, relay_rococo_client::runtime::WithWococoMessagesInstance>;
/// Run Wococo-to-Rococo messages sync.
pub async fn run(
params: MessagesRelayParams<Wococo, WococoSigningParams, Rococo, RococoSigningParams>,
) -> Result<(), String> {
let stall_timeout = Duration::from_secs(5 * 60);
let relayer_id_at_wococo = (*params.source_sign.public().as_array_ref()).into();
let lane_id = params.lane_id;
let source_client = params.source_client;
let lane = WococoMessagesToRococo {
source_client: source_client.clone(),
source_sign: params.source_sign,
target_client: params.target_client.clone(),
target_sign: params.target_sign,
relayer_id_at_source: relayer_id_at_wococo,
};
// 2/3 is reserved for proofs and tx overhead
let max_messages_size_in_single_batch = bp_rococo::max_extrinsic_size() / 3;
// we don't know exact weights of the Rococo runtime. So to guess weights we'll be using
// weights from Rialto and then simply dividing it by x2.
let (max_messages_in_single_batch, max_messages_weight_in_single_batch) =
select_delivery_transaction_limits::<pallet_bridge_messages::weights::RialtoWeight<rialto_runtime::Runtime>>(
bp_rococo::max_extrinsic_weight(),
bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
);
let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = (
max_messages_in_single_batch / 2,
max_messages_weight_in_single_batch / 2,
);
log::info!(
target: "bridge",
"Starting Wococo -> Rococo messages relay.\n\t\
Wococo relayer account id: {:?}\n\t\
Max messages in single transaction: {}\n\t\
Max messages size in single transaction: {}\n\t\
Max messages weight in single transaction: {}",
lane.relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
);
messages_relay::message_lane_loop::run(
messages_relay::message_lane_loop::Params {
lane: lane_id,
source_tick: Wococo::AVERAGE_BLOCK_INTERVAL,
target_tick: Rococo::AVERAGE_BLOCK_INTERVAL,
reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY,
stall_timeout,
delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams {
max_unrewarded_relayer_entries_at_target: bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
max_unconfirmed_nonces_at_target: bp_rococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
max_messages_in_single_batch,
max_messages_weight_in_single_batch,
max_messages_size_in_single_batch,
relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic,
},
},
WococoSourceClient::new(
source_client.clone(),
lane.clone(),
lane_id,
ROCOCO_CHAIN_ID,
params.target_to_source_headers_relay,
),
RococoTargetClient::new(
params.target_client,
lane,
lane_id,
WOCOCO_CHAIN_ID,
params.source_to_target_headers_relay,
),
relay_utils::relay_metrics(
Some(messages_relay::message_lane_loop::metrics_prefix::<
WococoMessagesToRococo,
>(&lane_id)),
params.metrics_params,
)
.standalone_metric(|registry, prefix| {
StorageProofOverheadMetric::new(
registry,
prefix,
source_client.clone(),
"wococo_storage_proof_overhead".into(),
"Wococo storage proof overhead".into(),
)
})?
.into_params(),
futures::future::pending(),
)
.await
}
@@ -1,215 +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/>.
//! Complex headers+messages relays support.
//!
//! To add new complex relay between `ChainA` and `ChainB`, you must:
//!
//! 1) ensure that there's a `declare_chain_options!(...)` for both chains;
//! 2) add `declare_bridge_options!(...)` for the bridge;
//! 3) add bridge support to the `select_bridge! { ... }` macro.
use crate::cli::{CliChain, HexLaneId, PrometheusParams};
use crate::declare_chain_options;
use crate::messages_lane::MessagesRelayParams;
use crate::on_demand_headers::OnDemandHeadersRelay;
use futures::{FutureExt, TryFutureExt};
use relay_utils::metrics::MetricsParams;
use structopt::StructOpt;
/// Start headers+messages relayer process.
#[derive(StructOpt)]
pub enum RelayHeadersAndMessages {
MillauRialto(MillauRialtoHeadersAndMessages),
RococoWococo(RococoWococoHeadersAndMessages),
}
/// Parameters that have the same names across all bridges.
#[derive(StructOpt)]
pub struct HeadersAndMessagesSharedParams {
/// Hex-encoded lane identifiers that should be served by the complex relay.
#[structopt(long, default_value = "00000000")]
lane: Vec<HexLaneId>,
#[structopt(flatten)]
prometheus_params: PrometheusParams,
}
// The reason behind this macro is that 'normal' relays are using source and target chains terminology,
// which is unusable for both-way relays (if you're relaying headers from Rialto to Millau and from
// Millau to Rialto, then which chain is source?).
macro_rules! declare_bridge_options {
($chain1:ident, $chain2:ident) => {
paste::item! {
#[doc = $chain1 " and " $chain2 " headers+messages relay params."]
#[derive(StructOpt)]
pub struct [<$chain1 $chain2 HeadersAndMessages>] {
#[structopt(flatten)]
shared: HeadersAndMessagesSharedParams,
#[structopt(flatten)]
left: [<$chain1 ConnectionParams>],
#[structopt(flatten)]
left_sign: [<$chain1 SigningParams>],
#[structopt(flatten)]
right: [<$chain2 ConnectionParams>],
#[structopt(flatten)]
right_sign: [<$chain2 SigningParams>],
}
#[allow(unreachable_patterns)]
impl From<RelayHeadersAndMessages> for [<$chain1 $chain2 HeadersAndMessages>] {
fn from(relay_params: RelayHeadersAndMessages) -> [<$chain1 $chain2 HeadersAndMessages>] {
match relay_params {
RelayHeadersAndMessages::[<$chain1 $chain2>](params) => params,
_ => unreachable!(),
}
}
}
}
};
}
macro_rules! select_bridge {
($bridge: expr, $generic: tt) => {
match $bridge {
RelayHeadersAndMessages::MillauRialto(_) => {
type Params = MillauRialtoHeadersAndMessages;
type Left = relay_millau_client::Millau;
type Right = relay_rialto_client::Rialto;
type LeftToRightFinality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto;
type RightToLeftFinality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau;
type LeftToRightMessages = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto;
type RightToLeftMessages = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau;
const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_millau::BlockNumber = bp_millau::SESSION_LENGTH;
const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_rialto::BlockNumber = bp_rialto::SESSION_LENGTH;
use crate::chains::millau_messages_to_rialto::run as left_to_right_messages;
use crate::chains::rialto_messages_to_millau::run as right_to_left_messages;
$generic
}
RelayHeadersAndMessages::RococoWococo(_) => {
type Params = RococoWococoHeadersAndMessages;
type Left = relay_rococo_client::Rococo;
type Right = relay_wococo_client::Wococo;
type LeftToRightFinality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo;
type RightToLeftFinality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo;
type LeftToRightMessages = crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo;
type RightToLeftMessages = crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo;
const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_rococo::BlockNumber = bp_rococo::SESSION_LENGTH;
const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = bp_wococo::SESSION_LENGTH;
use crate::chains::rococo_messages_to_wococo::run as left_to_right_messages;
use crate::chains::wococo_messages_to_rococo::run as right_to_left_messages;
$generic
}
}
};
}
// All supported chains.
declare_chain_options!(Millau, millau);
declare_chain_options!(Rialto, rialto);
declare_chain_options!(Rococo, rococo);
declare_chain_options!(Wococo, wococo);
// All supported bridges.
declare_bridge_options!(Millau, Rialto);
declare_bridge_options!(Rococo, Wococo);
impl RelayHeadersAndMessages {
/// Run the command.
pub async fn run(self) -> anyhow::Result<()> {
select_bridge!(self, {
let params: Params = self.into();
let left_client = params.left.to_client::<Left>().await?;
let left_sign = params.left_sign.to_keypair::<Left>()?;
let right_client = params.right.to_client::<Right>().await?;
let right_sign = params.right_sign.to_keypair::<Right>()?;
let lanes = params.shared.lane;
let metrics_params: MetricsParams = params.shared.prometheus_params.into();
let metrics_params = relay_utils::relay_metrics(None, metrics_params).into_params();
let left_to_right_on_demand_headers = OnDemandHeadersRelay::new(
left_client.clone(),
right_client.clone(),
LeftToRightFinality::new(right_client.clone(), right_sign.clone()),
MAX_MISSING_LEFT_HEADERS_AT_RIGHT,
);
let right_to_left_on_demand_headers = OnDemandHeadersRelay::new(
right_client.clone(),
left_client.clone(),
RightToLeftFinality::new(left_client.clone(), left_sign.clone()),
MAX_MISSING_RIGHT_HEADERS_AT_LEFT,
);
// Need 2x capacity since we consider both directions for each lane
let mut message_relays = Vec::with_capacity(lanes.len() * 2);
for lane in lanes {
let lane = lane.into();
let left_to_right_messages = left_to_right_messages(MessagesRelayParams {
source_client: left_client.clone(),
source_sign: left_sign.clone(),
target_client: right_client.clone(),
target_sign: right_sign.clone(),
source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()),
target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()),
lane_id: lane,
metrics_params: metrics_params.clone().disable().metrics_prefix(
messages_relay::message_lane_loop::metrics_prefix::<LeftToRightMessages>(&lane),
),
})
.map_err(|e| anyhow::format_err!("{}", e))
.boxed();
let right_to_left_messages = right_to_left_messages(MessagesRelayParams {
source_client: right_client.clone(),
source_sign: right_sign.clone(),
target_client: left_client.clone(),
target_sign: left_sign.clone(),
source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()),
target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()),
lane_id: lane,
metrics_params: metrics_params.clone().disable().metrics_prefix(
messages_relay::message_lane_loop::metrics_prefix::<RightToLeftMessages>(&lane),
),
})
.map_err(|e| anyhow::format_err!("{}", e))
.boxed();
message_relays.push(left_to_right_messages);
message_relays.push(right_to_left_messages);
}
relay_utils::relay_metrics(None, metrics_params)
.expose()
.await
.map_err(|e| anyhow::format_err!("{}", e))?;
futures::future::select_all(message_relays).await.0
})
}
}
@@ -1,71 +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::cli::bridge::FullBridge;
use crate::cli::{
HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, TargetConnectionParams,
TargetSigningParams,
};
use crate::messages_lane::MessagesRelayParams;
use crate::select_full_bridge;
use structopt::StructOpt;
/// Start messages relayer process.
#[derive(StructOpt)]
pub struct RelayMessages {
/// A bridge instance to relay messages for.
#[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)]
bridge: FullBridge,
/// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`.
#[structopt(long, default_value = "00000000")]
lane: HexLaneId,
#[structopt(flatten)]
source: SourceConnectionParams,
#[structopt(flatten)]
source_sign: SourceSigningParams,
#[structopt(flatten)]
target: TargetConnectionParams,
#[structopt(flatten)]
target_sign: TargetSigningParams,
#[structopt(flatten)]
prometheus_params: PrometheusParams,
}
impl RelayMessages {
/// Run the command.
pub async fn run(self) -> anyhow::Result<()> {
select_full_bridge!(self.bridge, {
let source_client = self.source.to_client::<Source>().await?;
let source_sign = self.source_sign.to_keypair::<Source>()?;
let target_client = self.target.to_client::<Target>().await?;
let target_sign = self.target_sign.to_keypair::<Target>()?;
relay_messages(MessagesRelayParams {
source_client,
source_sign,
target_client,
target_sign,
source_to_target_headers_relay: None,
target_to_source_headers_relay: None,
lane_id: self.lane.into(),
metrics_params: self.prometheus_params.into(),
})
.await
.map_err(|e| anyhow::format_err!("{}", e))
})
}
}

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