Add canvas-kusama runtime (#980)

* Added kanvas runtime

* Fix up benchmarking

* Fixup markdown stucture

* replace :emoji_name: by utf8
* fix up header hierarchy

* Merge canvas README

* Only use "Canvas" as a name

* Remove reference to Rocanvas
This commit is contained in:
Alexander Theißen authored and GitHub committed 2022-02-17 16:18:48 -05:00
1 parent eeca2bb61a
commit 4d319d0fae
13 files changed
+3174 -295

No files matched your search

+505 -275
View File
File diff suppressed because it is too large. Load diff
+1
View File
@@ -32,6 +32,7 @@ members = [
"polkadot-parachains/statemint",
"polkadot-parachains/statemine",
"polkadot-parachains/westmint",
"polkadot-parachains/canvas-kusama",
"test/client",
"test/relay-sproof-builder",
"test/relay-validation-worker-provider",
+111 -14
View File
@@ -1,4 +1,9 @@
# Cumulus :cloud:
# Cumulus ☁️
This repository contains both the Cumulus SDK and also specific chains implemented
on top of this SDK.
## Cumulus SDK
A set of tools for writing [Substrate](https://substrate.io/)-based
[Polkadot](https://wiki.polkadot.network/en/)
@@ -14,7 +19,7 @@ make it easy to write parachains for Polkadot by leveraging the power of Substra
Cumulus clouds are shaped sort of like dots; together they form a system that is intricate,
beautiful and functional.
## Consensus
### Consensus
[`parachain-consensus`](https://github.com/paritytech/cumulus/blob/master/client/consensus/common/src/parachain_consensus.rs) is a
[consensus engine](https://docs.substrate.io/v3/advanced/consensus) for Substrate
@@ -25,18 +30,18 @@ to follow,
[finalize](https://wiki.polkadot.network/docs/en/learn-consensus#probabilistic-vs-provable-finality),
and treat as best.
## Collator
### Collator
A Polkadot [collator](https://wiki.polkadot.network/docs/en/learn-collator) for the parachain is
implemented by the `polkadot-collator` binary.
# Statemint 🪙
## Statemint 🪙
This repository also contains the Statemint runtime (as well as the canary runtime Statemine and the
test runtime Westmint).
Statemint is a common good parachain providing an asset store for the Polkadot ecosystem.
## Build & Launch a Node
### Build & Launch a Node
To run a Statemine or Westmint node (Statemint is not deployed, yet) you will need to compile the
`polkadot-collator` binary:
@@ -54,14 +59,104 @@ CHAIN=westmint # or statemine
Refer to the [setup instructions below](#local-setup) to run a local network for development.
# Rococo :crown:
## Canvas 🧑‍🎨
[![matrix][k1]][k2] [![discord][l1]][l2]
[k1]: https://img.shields.io/badge/matrix-chat-brightgreen.svg?style=flat
[k2]: https://riot.im/app/#/room/#ink:matrix.parity.io
[l1]: https://img.shields.io/discord/722223075629727774?style=flat-square&label=discord
[l2]: https://discord.com/invite/wGUDt2p
This is a node implementation of `Canvas`, a common good parachain for `pallet-contracts`
based wasm smart contracts. Right now this repository only contains the `canvas-kusama` runtime
which we plan to use for both Rococo and Kusama.
If you have any questions, feel free to talk to us on [Element][k2] or on [Discord][l2]
(in the [`ink_smart-contracts`](https://discord.com/channels/722223075629727774/765280480609828864) channel).
## Developing Smart Contracts for Canvas
![Canvas Overview](./docs/canvas-overview.svg)
This node contains Substrate's smart contracts module ‒ the
[`contracts`](https://github.com/paritytech/substrate/tree/master/frame/contracts) pallet.
This `contracts` pallet takes smart contracts as WebAssembly blobs and defines an API
for everything a smart contract needs (storage access, …).
As long as a programming language compiles to WebAssembly and there exists an implementation
of this API in it, you can write a smart contract for this pallet ‒ and thus for Canvas ‒ in
that language.
This is a list of languages you can currently choose from:
* [Parity's ink!](https://github.com/paritytech/ink) for Rust
* [ask!](https://github.com/patractlabs/ask) for Assembly Script
* The [Solang](https://github.com/hyperledger-labs/solang) compiler for Solidity
There are also different user interfaces and command-line tools you can use to deploy
or interact with contracts:
* [polkadot-js](https://polkadot.js.org/apps/)
* [Canvas UI](https://paritytech.github.io/canvas-ui/) (outdated)
If you are looking for a quickstart, we can recommend
[ink!'s Guided Tutorial for Beginners](https://docs.substrate.io/tutorials/v3/ink-workshop/pt1/).
### Build & Launch a Node
To run a Canvas node that connects to Rococo (Kusama and Polkadot parachains are not deployed, yet)
you will need to compile the `polkadot-collator` binary:
```bash
cargo build --release --locked -p polkadot-collator
```
Once the executable is built, launch the parachain node via:
```bash
./target/release/polkadot-collator --chain rocanvas
```
Refer to the [setup instructions below](#local-setup) to run a local network for development.
### Rococo Deployment
We have a live deployment of the Canvas parachain on [Rococo](https://wiki.polkadot.network/docs/build-pdk#rococo-testnet) ‒
a testnet for Polkadot and Kusama parachains.
You can interact with the network through Polkadot JS Apps,
[click here for a direct link to Canvas](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-canvas-rpc.polkadot.io#/explorer).
The Canvas parachain uses the Rococo relay chain's native token (ROC) instead of having its own token.
Due to this you'll need ROC in order to deploy contracts on Canvas.
As a first step, you should create an account. See [here](https://wiki.polkadot.network/docs/learn-account-generation)
for a detailed guide.
As a second step, you have to get ROC testnet tokens through the [Rococo Faucet](https://wiki.polkadot.network/docs/learn-DOT#getting-rococo-tokens).
This is a chat room in which you need to write:
```bash
!drip YOUR_SS_58_ADDRESS:1002
```
The number `1002` is the parachain id of Canvas on Rococo, by supplying it the faucet will teleport ROC
tokens directly to your account on the parachain.
If everything worked out, the teleported ROC tokens will show up under
[the "Accounts" tab for Canvas](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-canvas-rpc.polkadot.io#/accounts).
Once you have ROC on Canvas you can deploy a contract as you would normally.
If you're unsure about this, our [guided tutorial](https://docs.substrate.io/tutorials/v3/ink-workshop/pt1/)
will clarify that for you in no time.
## Rococo 👑
[Rococo](https://polkadot.js.org/apps/?rpc=wss://rococo-rpc.polkadot.io) is becoming a [Community Parachain Testbed](https://polkadot.network/blog/rococo-revamp-becoming-a-community-parachain-testbed/) for parachain teams in the Polkadot ecosystem. It supports multiple parachains with the differentiation of long-term connections and recurring short-term connections, to see which parachains are currently connected and how long they will be connected for [see here](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-rpc.polkadot.io#/parachains).
Rococo is an elaborate style of design and the name describes the painstaking effort that has gone
into this project.
## Build & Launch Rococo Collators
### Build & Launch Rococo Collators
Collators are similar to validators in the relay chain. These nodes build the blocks that will
eventually be included by the relay chain for a parachain.
@@ -92,19 +187,21 @@ Once the executable is built, launch collators for each parachain (repeat once e
./target/release/polkadot-collator --chain $CHAIN --validator
```
## Parachains
### Parachains
- [Canvas - WASM Smart Contract](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-canvas-rpc.polkadot.io#/explorer)
* [Statemint](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-statemint-rpc.polkadot.io#/explorer)
* [Canvas on Rococo](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo-canvas-rpc.polkadot.io#/explorer)
* [RILT](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frococo.kilt.io#/explorer)
The network uses horizontal message passing (HRMP) to enable communication between parachains and
the relay chain and, in turn, between parachains. This means that every message is sent to the relay
chain, and from the relay chain to its destination parachain.
## Local Setup
### Local Setup
Launch a local setup including a Relay Chain and a Parachain.
### Launch the Relay Chain
#### Launch the Relay Chain
```bash
# Compile Polkadot with the real overseer feature
@@ -121,7 +218,7 @@ cargo build --release
./target/release/polkadot --chain rococo-local-cfde.json --bob --tmp --port 30334
```
### Launch the Parachain
#### Launch the Parachain
```bash
# Compile
@@ -144,11 +241,11 @@ cargo build --release
./target/release/polkadot-collator --tmp --port 40337 --ws-port 9948 -- --execution wasm --chain ../polkadot/rococo-local-cfde.json --port 30337
```
### Register the parachain
#### Register the parachain
![image](https://user-images.githubusercontent.com/2915325/99548884-1be13580-2987-11eb-9a8b-20be658d34f9.png)
## Containerize
### Containerize
After building `polkadot-collator` with cargo or with Parity CI image as documented in [this chapter](#build--launch-rococo-collators),
the following will allow producing a new docker image where the compiled binary is injected:
+764
View File
@@ -0,0 +1,764 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="829mm"
height="715mm"
viewBox="0 0 829 715"
version="1.1"
id="svg8"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)"
sodipodi:docname="how-it-works.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<defs
id="defs2">
<marker
style="overflow:visible"
id="marker7726"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Lstart"
inkscape:isstock="true">
<path
transform="scale(0.8) translate(12.5,0)"
style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path7465" />
</marker>
<marker
style="overflow:visible"
id="marker32724"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path32466" />
</marker>
<marker
style="overflow:visible"
id="marker2343"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lstart"
inkscape:isstock="true">
<path
transform="matrix(0.8,0,0,0.8,10,0)"
style="fill:#d8b6ff;fill-opacity:1;fill-rule:evenodd;stroke:#d8b6ff;stroke-width:1pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path2341" />
</marker>
<marker
style="overflow:visible"
id="marker2279"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:#d8b6ff;fill-opacity:1;fill-rule:evenodd;stroke:#d8b6ff;stroke-width:1pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path2277" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Lend"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:#e50000;fill-opacity:1;fill-rule:evenodd;stroke:#e50000;stroke-width:1pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path1510" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Lstart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lstart"
inkscape:isstock="true">
<path
transform="matrix(0.8,0,0,0.8,10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path1507" />
</marker>
<marker
style="overflow:visible"
id="marker1813-6"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:#d8b6ff;fill-opacity:1;fill-rule:evenodd;stroke:#d8b6ff;stroke-width:1pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path1811-1" />
</marker>
<marker
style="overflow:visible"
id="marker1813-6-6"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:#d8b6ff;fill-opacity:1;fill-rule:evenodd;stroke:#d8b6ff;stroke-width:1pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path1811-1-1" />
</marker>
<clipPath
id="ga18cbd6cb1_1_0.4">
<path
d="M 0,0 H 512 V 512 H 0 Z"
clip-rule="evenodd"
id="path3358" />
</clipPath>
<clipPath
id="ga18cbd6cb1_1_0.4-6">
<path
d="M 0,0 H 512 V 512 H 0 Z"
clip-rule="evenodd"
id="path3358-7" />
</clipPath>
<clipPath
id="ga18cbd6cb1_1_0.4-6-3">
<path
d="M 0,0 H 512 V 512 H 0 Z"
clip-rule="evenodd"
id="path3358-7-6" />
</clipPath>
<marker
style="overflow:visible"
id="marker32724-2"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path32466-9" />
</marker>
<marker
style="overflow:visible"
id="marker32724-27"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path32466-0" />
</marker>
<marker
style="overflow:visible"
id="marker32724-27-3"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path32466-0-6" />
</marker>
<marker
style="overflow:visible"
id="marker32724-27-3-6"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path32466-0-6-2" />
</marker>
<marker
style="overflow:visible"
id="marker32724-1"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path32466-8" />
</marker>
<marker
style="overflow:visible"
id="marker32724-9"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path32466-2" />
</marker>
<marker
style="overflow:visible"
id="marker32724-3"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path32466-7" />
</marker>
<marker
style="overflow:visible"
id="marker32724-3-2"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path32466-7-2" />
</marker>
<marker
style="overflow:visible"
id="marker32724-97"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path32466-3" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.12114248"
inkscape:cx="429.24663"
inkscape:cy="1943.9919"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
showguides="true"
inkscape:window-width="1471"
inkscape:window-height="1080"
inkscape:window-x="0"
inkscape:window-y="23"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="0"
inkscape:guide-bbox="true"
width="829mm">
<sodipodi:guide
position="289.8806,728.03695"
orientation="0,-1"
id="guide44197" />
<sodipodi:guide
position="40.94359,185.59939"
orientation="1,0"
id="guide81698" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:14.5058;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:113.386;stroke-opacity:1"
id="rect1440"
width="829.57776"
height="715.97333"
x="0"
y="0"
ry="0" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="542.16547"
y="419.47101"
id="text1127"><tspan
sodipodi:role="line"
id="tspan1125"
x="542.16547"
y="419.47101"
style="stroke-width:0.264583" /></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:14.1111px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;white-space:pre;inline-size:372.233;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="455.81284"
y="231.4695"
id="text835-3"
transform="translate(14.142967,413.67741)" />
<g
id="g52787"
transform="translate(-76.682965,-41.563407)">
<path
id="rect2466"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 103.20932,424.05872 H 883.96988 V 724.38367 H 103.20932 Z" />
<g
id="g32738"
transform="translate(39.470311,-37.284235)">
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15.875px;line-height:1.25;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="449.05841"
y="378.08499"
id="text835-3-2"><tspan
sodipodi:role="line"
x="449.05841"
y="378.08499"
style="font-size:15.875px;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
id="tspan1083">The .contract file contains the WebAssembly</tspan><tspan
sodipodi:role="line"
x="449.05841"
y="397.92874"
style="font-size:15.875px;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
id="tspan2077">blob and metadata for the contract.</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:25.4px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="340.15393"
y="338.19156"
id="text1975-2"><tspan
sodipodi:role="line"
id="tspan1973-2"
x="340.15393"
y="338.19156"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.4px;font-family:monospace;-inkscape-font-specification:monospace;fill:#000000;stroke-width:0.264583">.contract File</tspan></text>
</g>
<path
style="mix-blend-mode:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker32724)"
d="m 162.44329,210.7796 65.19725,40.25153"
id="path1809-0" />
<path
style="mix-blend-mode:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker32724-97)"
d="m 356.93917,210.7796 65.19725,40.25153"
id="path1809-0-6" />
<path
style="mix-blend-mode:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker32724-3)"
d="m 619.41079,210.7796 -65.19725,40.25153"
id="path1809-0-59" />
<path
style="mix-blend-mode:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker32724-3-2)"
d="m 813.90671,210.7796 -65.19725,40.25153"
id="path1809-0-59-8" />
<g
id="g18870"
transform="translate(-155.99885,-105.40214)">
<g
id="g28235"
style="stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none">
<g
id="g3104"
transform="translate(57.106751,132.51159)"
style="stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none">
<rect
style="fill:#18ffb2;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect2468"
width="376.05222"
height="185.83325"
x="404.45572"
y="489.5585"
ry="0" />
<g
id="g84315"
transform="translate(-0.51935474,6.1523713)"
style="stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none">
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15.875px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
x="592.87457"
y="620.01123"
id="text835-3-7"><tspan
sodipodi:role="line"
x="592.87457"
y="620.01123"
style="font-size:15.875px;text-align:center;text-anchor:middle;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
id="tspan1097">Substrate's module for smart contracts</tspan></text>
<g
id="g4054"
style="stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
transform="translate(19.524257,10.054167)">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.4px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
x="474.41205"
y="566.8855"
id="text1975-0-1"><tspan
sodipodi:role="line"
id="tspan1973-9-7"
x="474.41205"
y="566.8855"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.4px;font-family:monospace;-inkscape-font-specification:monospace;fill:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none">pallet-contracts</tspan></text>
<image
clip-path="url(#ga18cbd6cb1_1_0.4-6-3)"
fill="#000000"
width="512"
height="512"
x="0"
y="0"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,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 truncated
id="image3361"
transform="matrix(0.08465155,0,0,0.08465645,429.03528,538.77455)"
style="stroke-width:11.8127909;stroke-miterlimit:4;stroke-dasharray:none" />
</g>
</g>
</g>
</g>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#00000f;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:10;stroke-opacity:1"
id="rect859"
width="326.8931"
height="92.220352"
x="486.14203"
y="575.13098"
ry="27.279261" />
<path
style="fill:#000000;stroke:#000000;stroke-width:1.715;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.715, 1.715;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker7726);marker-end:url(#marker32724)"
d="M 642.70694,491.17751 V 567.7991"
id="path1809-0-5" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:14.1111px;line-height:0;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="649.55072"
y="591.22406"
id="text835-0-9"><tspan
sodipodi:role="line"
x="649.55072"
y="591.22406"
style="font-size:14.1111px;line-height:1.25;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
id="tspan1075-9" /><tspan
sodipodi:role="line"
x="649.55072"
y="617.64673"
style="font-size:15.875px;line-height:0.72;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
id="tspan2428">The WebAssembly blob targets</tspan><tspan
sodipodi:role="line"
x="649.55072"
y="640.50671"
style="font-size:15.875px;line-height:0.72;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
id="tspan2430">an API exposed by Substrate's</tspan><tspan
sodipodi:role="line"
x="649.55072"
y="651.93671"
style="font-size:15.875px;line-height:0.72;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
id="tspan2432">contracts module.</tspan></text>
<g
id="g1342">
<g
id="g37555"
transform="translate(177.66064,94.365491)">
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15.875px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="177.42126"
y="689.06769"
id="text1087"><tspan
sodipodi:role="line"
id="tspan1085"
x="177.42126"
y="689.06769"
style="font-size:15.875px;text-align:center;text-anchor:middle;fill:#000000;stroke-width:0.264583" /><tspan
sodipodi:role="line"
x="177.42126"
y="708.91144"
style="font-size:15.875px;text-align:center;text-anchor:middle;fill:#000000;stroke-width:0.264583"
id="tspan2399">Blockchain-Framework</tspan></text>
</g>
<g
id="g30494"
transform="matrix(1.3732612,0,0,1.3732612,276.72012,1009.2471)">
<path
d="m 8.2218148,-178.09322 a 4.3841458,4.3841458 0 0 1 1.5160625,2.667 h -3.048 a 1.7039166,1.7039166 0 0 0 -0.6006041,-1.02129 1.8335625,1.8335625 0 0 0 -1.1721042,-0.37042 1.2832292,1.2832292 0 0 0 -0.8387291,0.23812 0.83079166,0.83079166 0 0 0 -0.28575,0.67734 0.79374999,0.79374999 0 0 0 0.5291666,0.74083 8.3476041,8.3476041 0 0 0 1.6483542,0.49742 16.644937,16.644937 0 0 1 2.00025,0.57944 3.3125833,3.3125833 0 0 1 1.3520208,0.96308 2.6458333,2.6458333 0 0 1 0.5662083,1.79652 2.746375,2.746375 0 0 1 -0.4947708,1.61925 3.2808333,3.2808333 0 0 1 -1.42875,1.10331 5.5747708,5.5747708 0 0 1 -2.2119166,0.39423 q -2.1563542,0 -3.4395833,-0.9525 a 4.0137291,4.0137291 0 0 1 -1.58750002,-2.72256 H 3.869419 a 1.4049375,1.4049375 0 0 0 0.5820834,1.05833 2.1854583,2.1854583 0 0 0 1.30175,0.3519 1.2144375,1.2144375 0 0 0 0.8387291,-0.26459 0.86254166,0.86254166 0 0 0 0.28575,-0.67468 0.81491666,0.81491666 0 0 0 -0.5291667,-0.79375 9.5752707,9.5752707 0 0 0 -1.7065624,-0.50536 13.554604,13.554604 0 0 1 -1.9420417,-0.52916 3.20675,3.20675 0 0 1 -1.3229166,-0.92605 2.5691041,2.5691041 0 0 1 -0.53710419,-1.73566 2.8442708,2.8442708 0 0 1 1.08743749,-2.30188 q 1.0821458,-0.88371 3.0665208,-0.88635 1.984375,-0.003 3.2279166,0.99748 z"
id="path28110"
style="stroke-width:0.264583" />
<path
d="m 22.519898,-178.97164 v 10.63096 h -3.272896 v -1.92617 a 3.52425,3.52425 0 0 1 -1.362604,1.48432 3.937,3.937 0 0 1 -2.103437,0.55297 q -1.828271,0 -2.910417,-1.21972 -1.082146,-1.21973 -1.076854,-3.34963 v -6.17273 h 3.2385 v 5.77321 a 2.3627291,2.3627291 0 0 0 0.563562,1.6854 1.9737916,1.9737916 0 0 0 1.513417,0.6006 1.9976041,1.9976041 0 0 0 1.561042,-0.62971 c 0.381,-0.41804 0.576791,-1.016 0.576791,-1.78858 v -5.64092 z"
id="path28112"
style="stroke-width:0.264583" />
<path
d="m 34.166856,-178.44776 a 4.5376041,4.5376041 0 0 1 1.640417,1.88648 6.5669583,6.5669583 0 0 1 0.597958,2.91041 6.5801874,6.5801874 0 0 1 -0.597958,2.91042 4.5111458,4.5111458 0 0 1 -1.640417,1.89442 4.2915416,4.2915416 0 0 1 -2.352146,0.65616 3.8549791,3.8549791 0 0 1 -2.0955,-0.55033 3.2173333,3.2173333 0 0 1 -1.275291,-1.52665 v 1.92352 h -3.257021 v -14.09435 h 3.257021 v 5.39221 a 3.2041041,3.2041041 0 0 1 1.275291,-1.50548 3.8549791,3.8549791 0 0 1 2.0955,-0.55298 4.3127083,4.3127083 0 0 1 2.352146,0.65617 z m -5.085291,2.88925 a 2.6458333,2.6458333 0 0 0 -0.656167,1.89441 2.6458333,2.6458333 0 0 0 0.656167,1.88648 2.38125,2.38125 0 0 0 3.370791,0.0185 2.6881666,2.6881666 0 0 0 0.640292,-1.905 2.6881666,2.6881666 0 0 0 -0.640292,-1.905 2.1881041,2.1881041 0 0 0 -1.685396,-0.68527 2.2198541,2.2198541 0 0 0 -1.685395,0.69586 z"
id="path28114"
style="stroke-width:0.264583" />
<path
d="m 45.311106,-178.09322 a 4.3841458,4.3841458 0 0 1 1.516062,2.667 h -3.047999 a 1.6906875,1.6906875 0 0 0 -0.600605,-1.02129 1.8335625,1.8335625 0 0 0 -1.172104,-0.37042 1.2832292,1.2832292 0 0 0 -0.838729,0.23812 0.83079166,0.83079166 0 0 0 -0.28575,0.67734 0.79374999,0.79374999 0 0 0 0.529167,0.74083 8.3476041,8.3476041 0 0 0 1.648354,0.49742 16.644937,16.644937 0 0 1 2.00025,0.57944 3.3125833,3.3125833 0 0 1 1.352021,0.96308 2.6458333,2.6458333 0 0 1 0.566208,1.79652 2.746375,2.746375 0 0 1 -0.494771,1.61925 3.2808333,3.2808333 0 0 1 -1.42875,1.10331 5.5562499,5.5562499 0 0 1 -2.209271,0.39952 q -2.151062,0 -3.439583,-0.9525 a 4.0137291,4.0137291 0 0 1 -1.5875,-2.72256 h 3.14325 a 1.412875,1.412875 0 0 0 0.582083,1.05833 2.1854583,2.1854583 0 0 0 1.304396,0.36248 1.2144375,1.2144375 0 0 0 0.838729,-0.26458 0.86254166,0.86254166 0 0 0 0.28575,-0.67469 0.81491666,0.81491666 0 0 0 -0.529166,-0.79375 9.5752707,9.5752707 0 0 0 -1.706563,-0.51329 13.554604,13.554604 0 0 1 -1.942041,-0.52917 3.20675,3.20675 0 0 1 -1.322917,-0.92604 2.5691041,2.5691041 0 0 1 -0.552979,-1.74096 2.8442708,2.8442708 0 0 1 1.098021,-2.30452 q 1.082145,-0.88371 3.06652,-0.88635 1.984375,-0.003 3.227917,0.99748 z"
id="path28116"
style="stroke-width:0.264583" />
<path
d="m 55.074231,-171.13997 v 2.79929 h -1.465792 c -1.243541,0 -2.214562,-0.30692 -2.910416,-0.9234 -0.695855,-0.61648 -1.023938,-1.63512 -1.023938,-3.05858 v -3.90525 h -1.426104 v -2.74373 h 1.426104 v -2.60879 h 3.259667 v 2.60879 h 2.132541 v 2.74373 h -2.132541 v 3.96875 a 1.190625,1.190625 0 0 0 0.264583,0.87577 1.2356042,1.2356042 0 0 0 0.867833,0.24871 z"
id="path28118"
style="stroke-width:0.264583" />
<path
d="m 62.342335,-178.51391 a 4.0057916,4.0057916 0 0 1 2.084917,-0.5715 v 3.48721 h -0.931334 c -0.865187,0 -1.534583,0.18256 -2.010833,0.55298 -0.47625,0.37041 -0.714375,0.98954 -0.714375,1.86531 v 4.83923 h -3.257021 v -10.63096 h 3.257021 v 2.00025 a 4.6593124,4.6593124 0 0 1 1.571625,-1.54252 z"
id="path28120"
style="stroke-width:0.264583" />
<path
d="m 71.973168,-178.55095 a 3.3205208,3.3205208 0 0 1 1.293813,1.50548 v -1.92617 h 3.2385 v 10.63096 h -3.2385 v -1.92617 a 3.33375,3.33375 0 0 1 -1.293813,1.50548 3.8549791,3.8549791 0 0 1 -2.0955,0.55034 4.2994791,4.2994791 0 0 1 -2.354791,-0.65617 4.4979166,4.4979166 0 0 1 -1.637771,-1.89442 6.5801874,6.5801874 0 0 1 -0.600604,-2.91041 6.5669583,6.5669583 0 0 1 0.600604,-2.91042 4.5323124,4.5323124 0 0 1 1.637771,-1.88648 4.3232916,4.3232916 0 0 1 2.354791,-0.65617 3.8549791,3.8549791 0 0 1 2.0955,0.57415 z m -2.735791,2.99244 a 2.69875,2.69875 0 0 0 -0.637646,1.905 2.69875,2.69875 0 0 0 0.637646,1.905 2.3944791,2.3944791 0 0 0 3.373437,-0.0185 2.6617083,2.6617083 0 0 0 0.656167,-1.88648 2.6458333,2.6458333 0 0 0 -0.656167,-1.905 2.2198541,2.2198541 0 0 0 -1.685396,-0.69586 2.1986875,2.1986875 0 0 0 -1.688041,0.69586 z"
id="path28122"
style="stroke-width:0.264583" />
<path
d="m 85.077981,-171.13997 v 2.79929 h -1.465792 q -1.867958,0 -2.910417,-0.9234 -1.042458,-0.92339 -1.039812,-3.05858 v -3.90525 h -1.412875 v -2.74373 h 1.42875 v -2.60879 h 3.259666 v 2.60879 h 2.132542 v 2.74373 h -2.132542 v 3.96875 a 1.190625,1.190625 0 0 0 0.264584,0.87577 1.2329583,1.2329583 0 0 0 0.865187,0.24871 z"
id="path28124"
style="stroke-width:0.264583" />
<path
d="M 97.098001,-173.06614 H 89.72671 q 0.05556,1.20386 0.608541,1.72508 a 1.9658541,1.9658541 0 0 0 1.410229,0.52917 1.93675,1.93675 0 0 0 1.201209,-0.36248 1.68275,1.68275 0 0 0 0.627062,-0.94456 h 3.439584 a 4.4979166,4.4979166 0 0 1 -0.912813,2.01083 4.9053749,4.9053749 0 0 1 -1.791229,1.39171 6.1303958,6.1303958 0 0 1 -5.191125,-0.15346 4.6804791,4.6804791 0 0 1 -1.87325,-1.88912 5.8790416,5.8790416 0 0 1 -0.687917,-2.91042 5.9531249,5.9531249 0 0 1 0.677334,-2.91042 4.6460833,4.6460833 0 0 1 1.894416,-1.88647 6.2600416,6.2600416 0 0 1 5.55625,0 4.5852291,4.5852291 0 0 1 1.852084,1.81768 5.4398333,5.4398333 0 0 1 0.656166,2.69611 4.4979166,4.4979166 0 0 1 -0.09525,0.88635 z m -3.767666,-2.94217 a 2.06375,2.06375 0 0 0 -1.436688,-0.52916 2.1166666,2.1166666 0 0 0 -1.486958,0.52916 2.2251458,2.2251458 0 0 0 -0.66675,1.56105 h 4.153958 c 0.01588,-0.68792 -0.169333,-1.2118 -0.563562,-1.56105 z"
id="path28126"
style="stroke-width:0.264583" />
<path
class="cls-1"
d="m 111.78502,-170.24303 v 3.175 H 99.995189 v -3.175 z"
id="path28128"
style="fill:#18ffb2;stroke-width:0.264583" />
</g>
</g>
</g>
<g
id="g38048"
transform="translate(-58.664253)">
<g
style="clip-rule:evenodd;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421"
id="g1956"
transform="matrix(0.04069094,0,0,0.04069094,170.72405,85.326523)">
<g
id="g1942"
style="fill:#000000;fill-opacity:1">
<path
id="inc"
d="m 1811.78,748.385 c -50.595,18.311 -78.758,71.865 -62.852,119.517 15.906,47.653 69.897,71.474 120.492,53.164 50.595,-18.311 78.758,-71.865 62.852,-119.518 -15.906,-47.652 -69.897,-71.474 -120.492,-53.163 z M 160.58,264.179 c 13.209,0.001 19.813,6.605 19.813,19.814 v 620.821 c 0,13.209 -6.604,19.813 -19.813,19.814 H 29.811 c -13.209,0 -19.814,-6.605 -19.814,-19.814 V 283.993 c 0,-13.209 6.605,-19.813 19.814,-19.814 z m 537.605,-5.283 c 143.978,0 194.171,97.746 194.171,232.478 v 413.44 c 0,13.209 -6.604,19.813 -19.813,19.814 H 741.774 c -13.209,0 -19.813,-6.605 -19.813,-19.814 V 471.56 c 0,-44.91 -33.022,-60.761 -71.329,-60.761 h -15.85 c -56.799,0 -97.747,23.776 -112.277,47.552 v 446.463 c 0,13.209 -6.604,19.813 -19.813,19.814 H 371.923 c -13.209,0 -19.813,-6.605 -19.813,-19.814 V 283.993 c 0,-13.209 6.604,-19.813 19.813,-19.814 h 130.769 c 13.209,0.001 19.813,6.605 19.813,19.814 v 58.119 c 19.814,-33.022 70.008,-83.216 167.754,-83.216 z M 1201.446,0 c 13.21,0 19.814,6.605 19.814,19.813 V 478.165 L 1408.827,280.03 c 7.925,-9.246 19.813,-15.85 30.381,-15.851 h 136.052 c 17.173,0.001 33.022,19.814 9.246,44.911 l -196.813,211.343 229.836,368.53 c 7.925,14.53 6.604,35.664 -15.851,35.665 h -124.164 c -17.172,0 -33.023,-5.284 -43.59,-23.776 L 1272.775,634.03 1221.26,685.545 v 219.269 c 0,13.209 -6.604,19.813 -19.814,19.814 h -130.768 c -13.209,0 -19.814,-6.605 -19.814,-19.814 V 19.813 C 1050.864,6.605 1057.468,0 1070.678,0 Z M 69.566,31.383 C 19.982,46.375 -9.857,96.406 2.975,143.038 15.808,189.669 66.482,215.357 116.067,200.364 165.652,185.372 195.49,135.341 182.658,88.71 169.826,42.078 119.151,16.391 69.566,31.383 Z"
style="fill:#000000;fill-opacity:1" />
<path
d="m 1795.61,594.617 -28.783,-0.213 c -13.209,0 -19.813,-6.605 -19.813,-19.814 V 19.813 C 1747.014,6.605 1753.618,0 1766.827,0 h 134.732 c 13.209,0 19.813,6.605 19.813,19.813 l -0.081,18.721 c -51.238,12.482 -91.137,64.695 -94.329,129.8 -2.564,52.29 19.2,99.658 53.607,126.46 -25.633,17.438 -44.472,46.887 -49.193,82.159 -5.141,38.403 7.648,74.783 31.364,98.837 -23.939,10.508 -45.741,31.983 -58.147,60.301 -8.77,20.019 -11.509,40.408 -8.983,58.526 z"
style="fill:#000000;fill-opacity:1"
id="path1938" />
<path
d="m 1837.23,549.753 c -9.822,22.417 -2.309,46.088 16.766,52.827 19.074,6.738 42.534,-5.992 52.356,-28.41 9.821,-22.418 2.308,-46.089 -16.766,-52.827 -19.075,-6.739 -42.535,5.992 -52.356,28.41 z m 35.572,-164.125 c -6.558,34.707 11.744,67.29 40.844,72.716 29.1,5.426 58.05,-18.347 64.607,-53.054 6.558,-34.707 -11.744,-67.29 -40.844,-72.716 -29.1,-5.425 -58.05,18.347 -64.607,53.054 z m -7.312,-204.559 c -2.328,47.49 28.18,88.336 68.085,91.158 39.905,2.821 74.194,-33.443 76.522,-80.933 2.329,-47.49 -28.179,-88.336 -68.084,-91.158 -39.906,-2.821 -74.194,33.444 -76.523,80.933 z"
style="fill:#000000;fill-opacity:1"
id="path1940" />
</g>
</g>
<image
preserveAspectRatio="none"
inkscape:svg-dpi="96"
width="75.484314"
height="75.484314"
xlink:href="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iOTBweCIg aGVpZ2h0PSI5MHB4IiB2aWV3Qm94PSIwIDAgMTEyIDExMiIgdmVyc2lvbj0iMS4xIiB4bWxucz0i aHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9y Zy8xOTk5L3hsaW5rIj4KICAgIDx0aXRsZT5Bc2shPC90aXRsZT4KICAgIDxnIGlkPSLpobXpnaIt MSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0i ZXZlbm9kZCI+CiAgICAgICAgPGcgaWQ9IlByb2R1Y3RzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgt NDc4LjAwMDAwMCwgLTE5NDUuMDAwMDAwKSI+CiAgICAgICAgICAgIDxnIGlkPSJBc2shIiB0cmFu c2Zvcm09InRyYW5zbGF0ZSg0NzguMDAwMDAwLCAxOTQ1LjAwMDAwMCkiPgogICAgICAgICAgICAg ICAgPHJlY3QgaWQ9IuefqeW9oiIgeD0iMCIgeT0iMCIgd2lkdGg9IjExMiIgaGVpZ2h0PSIxMTIi PjwvcmVjdD4KICAgICAgICAgICAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDcuMDAwMDAw LCAxMS4wMDAwMDApIiBmaWxsLXJ1bGU9Im5vbnplcm8iIGlkPSLotYTmupAtNyI+CiAgICAgICAg ICAgICAgICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDAuMDAwMDAwKSI+ CiAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMC4yNjIxNjMsMTEuNjAzMDE1NyBM NTYuMDIyMzU5NSwxMS42MDMwMTU3IEM1OS41NTY5ODE5LDExLjYwMzAxNTcgNjIuNDIyMzU5NSwx NC40NjgzOTMzIDYyLjQyMjM1OTUsMTguMDAzMDE1NyBMNjIuNDIyMzU5NSw3MS4zMTIxMDY2IEM2 Mi40MjIzNTk1LDc0Ljg0NjcyOSA1OS41NTY5ODE5LDc3LjcxMjEwNjYgNTYuMDIyMzU5NSw3Ny43 MTIxMDY2IEwyMC4yNjIxNjMsNzcuNzEyMTA2NiBDMTYuNzI3NTQwNiw3Ny43MTIxMDY2IDEzLjg2 MjE2Myw3NC44NDY3MjkgMTMuODYyMTYzLDcxLjMxMjEwNjYgTDEzLjg2MjE2MywxOC4wMDMwMTU3 IEMxMy44NjIxNjMsMTQuNDY4MzkzMyAxNi43Mjc1NDA2LDExLjYwMzAxNTcgMjAuMjYyMTYzLDEx LjYwMzAxNTcgWiIgaWQ9IuefqeW9oiIgc3Ryb2tlPSIjMDAwMDcyIiBzdHJva2Utd2lkdGg9IjIi IGZpbGw9IiNGRkZGRkYiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDM4LjE0MjI2MSwgNDQuNjU3NTYx KSByb3RhdGUoLTMwLjAwMDAwMCkgdHJhbnNsYXRlKC0zOC4xNDIyNjEsIC00NC42NTc1NjEpICI+ PC9wYXRoPgogICAgICAgICAgICAgICAgICAgICAgICA8bGluZSB4MT0iMTcuMzM2NjA5MyIgeTE9 IjQyLjk4NzcxNSIgeDI9IjQ0LjkzMzY2MDkiIHkyPSIyNy4wNjYzMzkxIiBpZD0i6Lev5b6EIiBz dHJva2U9IiMwMDAwNzIiIHN0cm9rZS13aWR0aD0iMiIgZmlsbD0iIzAwRkZGRiIgc3Ryb2tlLWxp bmVjYXA9InJvdW5kIj48L2xpbmU+CiAgICAgICAgICAgICAgICAgICAgICAgIDxsaW5lIHgxPSIy My4wODU5OTUxIiB5MT0iNTIuOTgyODAxIiB4Mj0iNTAuNjgzMDQ2NyIgeTI9IjM3LjA2MTQyNTEi IGlkPSLot6/lvoQiIHN0cm9rZT0iIzAwMDA3MiIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSIjMDBG RkZGIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjwvbGluZT4KICAgICAgICAgICAgICAgICAgICAg ICAgPGxpbmUgeDE9IjI4LjgzNTM4MDgiIHkxPSI2Mi44ODk0MzQ5IiB4Mj0iNTYuNDMyNDMyNCIg eTI9IjQ2Ljk2ODA1OSIgaWQ9Iui3r+W+hCIgc3Ryb2tlPSIjMDAwMDcyIiBzdHJva2Utd2lkdGg9 IjIiIGZpbGw9IiMwMEZGRkYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PC9saW5lPgogICAgICAg ICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMzQuNjAxNDg5Nyw5LjUyOTcyNDI3IEw3Ni45MDcx NDA4LDkuNTI5NzI0MjcgQzgwLjQ0MTc2MzIsOS41Mjk3MjQyNyA4My4zMDcxNDA4LDEyLjM5NTEw MTkgODMuMzA3MTQwOCwxNS45Mjk3MjQzIEw4My4zMDcxNDA4LDczLjIyODAwNDQgQzgzLjMwNzE0 MDgsNzYuNzYyNjI2OCA4MC40NDE3NjMyLDc5LjYyODAwNDQgNzYuOTA3MTQwOCw3OS42MjgwMDQ0 IEwzNC42MDE0ODk3LDc5LjYyODAwNDQgQzMxLjA2Njg2NzMsNzkuNjI4MDA0NCAyOC4yMDE0ODk3 LDc2Ljc2MjYyNjggMjguMjAxNDg5Nyw3My4yMjgwMDQ0IEwyOC4yMDE0ODk3LDE1LjkyOTcyNDMg QzI4LjIwMTQ4OTcsMTIuMzk1MTAxOSAzMS4wNjY4NjczLDkuNTI5NzI0MjcgMzQuNjAxNDg5Nyw5 LjUyOTcyNDI3IFoiIGlkPSLnn6nlvaIiIHN0cm9rZT0iIzAwMDA3MiIgc3Ryb2tlLXdpZHRoPSIy IiBmaWxsPSIjRkZGRkZGIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg1NS43NTQzMTUsIDQ0LjU3ODg2 NCkgcm90YXRlKC0zMC4wMDAwMDApIHRyYW5zbGF0ZSgtNTUuNzU0MzE1LCAtNDQuNTc4ODY0KSAi PjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICAgICAgPGNpcmNsZSBpZD0i5qSt5ZyG5b2iIiBm aWxsPSIjRkYxRTk3IiBjeD0iODMuMTQ0OTYzMSIgY3k9IjU4LjM3ODM3ODQiIHI9IjMuNTM4MDgz NTQiPjwvY2lyY2xlPgogICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNjEuMDE0NDU4 NCwzLjUwMDgwODY5IEM2Mi40MTkzNTQsMy44NzcyNDkzNiA2My42MTcxNjg0LDQuNzk2MzY0NjQg NjQuMzQ0Mzk1OSw2LjA1NTk1OTY2IEw5My41Nzc4MTEyLDU2LjY4OTcyMDEgQzk0LjIxMTIwMjks NTcuNzg2Nzg2OCA5NC4zODI4NDQ1LDU5LjA5MDUzNDMgOTQuMDU0OTc2OCw2MC4zMTQxNTMxIEM5 My43MjcxMDkxLDYxLjUzNzc3MTkgOTIuOTI2NTg5NCw2Mi41ODEwMjk2IDkxLjgyOTUyMjcsNjMu MjE0NDIxMyBMNTMuNzU4NDUwMiw4NS4xOTQ3NjUzIEM1Mi42NjEzODM2LDg1LjgyODE1NyA1MS4z NTc2MzYxLDg1Ljk5OTc5ODYgNTAuMTM0MDE3Miw4NS42NzE5MzEgQzQ4LjkxMDM5ODQsODUuMzQ0 MDYzMyA0Ny44NjcxNDA3LDg0LjU0MzU0MzUgNDcuMjMzNzQ5LDgzLjQ0NjQ3NjkgTDE4LjAwMDMz MzgsMzIuODEyNzE2NCBDMTYuNDg1OTYwOSwzMC4xODk3NDU2IDE3LjM4NDY1NywyNi44MzU3NjU4 IDIwLjAwNzYyNzksMjUuMzIxMzkyOCBMMjkuNjU2MDQxLDE5Ljc1MTAxIEMzMS4xOTU3NDk4LDIw LjY4ODQ5ODUgMzMuMDA0MTAwMiwyMS4yMjg1MDEyIDM0LjkzODU3NDksMjEuMjI4NTAxMiBDNDAu NTU2NDEsMjEuMjI4NTAxMiA0NS4xMTA1NjUxLDE2LjY3NDM0NjEgNDUuMTEwNTY1MSwxMS4wNTY1 MTExIEw0NS4xMDc2OTc0LDEwLjgyODkzMSBMNTYuODUzMDcyMyw0LjA0ODY2NTU2IEM1OC4xMTI2 Njc0LDMuMzIxNDM4MDMgNTkuNjA5NTYyNywzLjEyNDM2ODAzIDYxLjAxNDQ1ODQsMy41MDA4MDg2 OSBaIiBpZD0i5b2i54q257uT5ZCIIiBmaWxsPSIjMDA3QkQyIj48L3BhdGg+CiAgICAgICAgICAg ICAgICAgICAgICAgIDxnIGlkPSLnvJbnu4QiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI0Ljc2NjU4 NSwgMC44ODQ1MjEpIiBmaWxsPSIjRkZGRkZGIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAg IDxnIGlkPSJvN29JMW4iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDExLjQ5ODc3MSwgMjIuOTk3NTQz KSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0LjIxMjk4Njcs Ny44NDIwODQ5IEwxNC42MjAwMTAxLDcuODQyMDg0OSBMMjUuMTczNjczOCwzMS4xMjE0MDk2IEwy MC4xODUyNzU4LDMxLjEyMTLine truncated
id="image3074"
x="637.16882"
y="66.449432" />
<g
id="Page-1"
sketch:type="MSPage"
transform="matrix(0.0688834,0,0,0.0688834,365.32312,60.801204)">
<g
id="solidity"
transform="translate(402,118)"
sketch:type="MSLayerGroup">
<g
id="Group"
sketch:type="MSShapeGroup">
<path
id="Shape"
opacity="0.45"
enable-background="new "
d="M 371.772,135.308 241.068,367.61 H -20.158 L 110.456,135.308 h 261.316" />
<path
id="Shape_1_"
opacity="0.6"
enable-background="new "
d="M 241.068,367.61 H 502.386 L 371.772,135.308 H 110.456 Z" />
<path
id="Shape_2_"
opacity="0.8"
enable-background="new "
d="M 110.456,599.822 241.068,367.61 110.456,135.308 -20.158,367.61 Z" />
<path
id="Shape_3_"
opacity="0.45"
enable-background="new "
d="M 111.721,948.275 242.425,715.972 H 503.743 L 373.038,948.275 H 111.721" />
<path
id="Shape_4_"
opacity="0.6"
enable-background="new "
d="M 242.424,715.973 H -18.893 L 111.72,948.276 h 261.317 z" />
<path
id="Shape_5_"
opacity="0.8"
enable-background="new "
d="M 373.038,483.761 242.424,715.973 373.038,948.276 503.742,715.973 Z" />
</g>
</g>
</g>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15.875px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="409.41479"
y="169.30264"
id="text835-5"><tspan
sodipodi:role="line"
x="409.41479"
y="169.30264"
style="font-size:15.875px;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
id="tspan1079-3">Solidity</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15.875px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="674.48651"
y="169.30264"
id="text835-5-5"><tspan
sodipodi:role="line"
x="674.48651"
y="169.30264"
style="font-size:15.875px;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
id="tspan1079-3-6">ask! Assembly Script eDSL</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15.875px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="215.62152"
y="169.30264"
id="text835"><tspan
sodipodi:role="line"
x="215.62152"
y="169.30264"
style="font-size:15.875px;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
id="tspan1079">Parity's Rust eDSL</tspan></text>
<g
id="g102807"
transform="translate(0,6.3500003)">
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path51541"
cx="864.93872"
cy="109.19419"
r="5.4990706" />
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path51541-1"
cx="880.50763"
cy="109.19419"
r="5.4990706" />
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path51541-2"
cx="896.0766"
cy="109.19419"
r="5.4990706" />
</g>
</g>
<g
id="g1493">
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:25.4px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="223.87091"
y="475.59076"
id="text1087-3"><tspan
sodipodi:role="line"
x="223.87091"
y="475.59076"
style="font-size:25.4px;text-align:center;text-anchor:middle;fill:#000000;stroke-width:0.264583"
id="tspan2399-7">Canvas</tspan></text>
<g
id="g9297"
transform="translate(187.58423,255.21786)">
<circle
cx="-43.440742"
cy="211.92067"
r="26.458332"
fill="#000000"
id="circle9169"
style="stroke-width:0.264583" />
<path
d="m -48.732408,217.21233 h 10.583334 v 10.58333 h -10.583334 z"
fill="#ffffff"
id="path9171"
style="stroke-width:0.264583" />
<path
d="m -48.732408,196.04566 h 10.583334 V 206.629 h -10.583334 z"
fill="#ffffff"
id="path9173"
style="stroke-width:0.264583" />
<path
d="m -59.315741,206.629 h 10.583333 v 10.58333 h -10.583333 z"
fill="#ffffff"
id="path9175"
style="stroke-width:0.264583" />
<path
d="m -27.565741,206.629 c 0,-1.38983 -0.273844,-2.76604 -0.805656,-4.05006 -0.531813,-1.28405 -1.311275,-2.45073 -2.294202,-3.4335 -0.982663,-0.98274 -2.149475,-1.76231 -3.433498,-2.29417 -1.284023,-0.53187 -2.660121,-0.80561 -4.049977,-0.80561 V 206.629 Z"
fill="#ffffff"
id="path9177"
style="stroke-width:0.264583" />
<path
d="m -38.149074,227.79566 c 1.389856,0 2.765954,-0.27384 4.049977,-0.80565 1.284023,-0.53182 2.450835,-1.31128 3.433498,-2.29421 0.982927,-0.98266 1.762389,-2.14947 2.294202,-3.43349 0.531812,-1.28403 0.805656,-2.66012 0.805656,-4.04998 h -10.583333 z"
fill="#ffffff"
id="path9179"
style="stroke-width:0.264583" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 88 KiB

+2
View File
@@ -25,6 +25,7 @@ seedling-runtime = { path = "seedling" }
statemint-runtime = { path = "statemint" }
statemine-runtime = { path = "statemine" }
westmint-runtime = { path = "westmint" }
canvas-kusama-runtime = { path = "canvas-kusama" }
parachains-common = { path = "parachains-common" }
# Substrate dependencies
@@ -66,6 +67,7 @@ jsonrpc-core = "18.0.0"
sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-rpc-system = { package = "substrate-frame-rpc-system", git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-contracts-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Cumulus dependencies
cumulus-client-cli = { path = "../client/cli" }
@@ -0,0 +1,174 @@
[package]
name = "canvas-kusama-runtime"
version = "0.2.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[build-dependencies]
substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
[dependencies]
hex-literal = { version = '0.3.1', optional = true }
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.0", default-features = false, features = ["derive"] }
serde = { version = '1.0.119', optional = true, features = ['derive'] }
smallvec = "1.6.1"
# Substrate Dependencies
## Substrate Primitive Dependencies
sp-api = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
sp-block-builder = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
sp-consensus-aura = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
sp-core = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
sp-inherents = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
sp-io = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
sp-offchain = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
sp-runtime = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
sp-session = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
sp-std = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
sp-transaction-pool = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
sp-version = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
node-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
## Substrate FRAME Dependencies
frame-benchmarking = { git = 'https://github.com/paritytech/substrate', default-features = false, optional = true , branch = "master" }
frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "master" }
frame-executive = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
frame-support = { git = 'https://github.com/paritytech/substrate', default-features = false, branch = "master" }
frame-system = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
frame-system-benchmarking = { git = 'https://github.com/paritytech/substrate', default-features = false, optional = true , branch = "master" }
frame-system-rpc-runtime-api = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
## Substrate Pallet Dependencies
pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-balances = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-timestamp = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
pallet-transaction-payment = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
pallet-transaction-payment-rpc-runtime-api = { git = 'https://github.com/paritytech/substrate', default-features = false , branch = "master" }
pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
# Cumulus Dependencies
cumulus-pallet-aura-ext = { path = "../../pallets/aura-ext", default-features = false }
cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
cumulus-primitives-timestamp = { path = "../../primitives/timestamp", default-features = false }
cumulus-primitives-utility = { path = "../../primitives/utility", default-features = false }
cumulus-pallet-dmp-queue = { path = "../../pallets/dmp-queue", default-features = false }
cumulus-pallet-xcmp-queue = { path = "../../pallets/xcmp-queue", default-features = false }
cumulus-pallet-xcm = { path = "../../pallets/xcm", default-features = false }
cumulus-pallet-session-benchmarking = { path = "../../pallets/session-benchmarking", default-features = false }
pallet-collator-selection = { path = "../../pallets/collator-selection", default-features = false }
parachains-common = { path = "../parachains-common", default-features = false }
parachain-info = { path = "../pallets/parachain-info", default-features = false }
# Polkadot Dependencies
polkadot-parachain = { git = 'https://github.com/paritytech/polkadot', default-features = false , branch = "master" }
polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
kusama-runtime-constants = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
xcm = { git = 'https://github.com/paritytech/polkadot', default-features = false , branch = "master" }
xcm-builder = { git = 'https://github.com/paritytech/polkadot', default-features = false , branch = "master" }
xcm-executor = { git = 'https://github.com/paritytech/polkadot', default-features = false , branch = "master" }
pallet-xcm = { git = 'https://github.com/paritytech/polkadot', default-features = false , branch = "master" }
# Contracts specific packages
pallet-contracts = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-contracts-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-contracts-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
[features]
default = [
"std",
]
std = [
"codec/std",
"serde",
"scale-info/std",
"log/std",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-aura/std",
"sp-core/std",
"sp-inherents/std",
"sp-io/std",
"sp-offchain/std",
"sp-runtime/std",
"sp-session/std",
"sp-std/std",
"sp-transaction-pool/std",
"sp-version/std",
"node-primitives/std",
"frame-executive/std",
"frame-support/std",
"frame-system/std",
"frame-system-rpc-runtime-api/std",
"pallet-authorship/std",
"pallet-aura/std",
"pallet-sudo/std",
"pallet-balances/std",
"pallet-multisig/std",
"pallet-collator-selection/std",
"pallet-randomness-collective-flip/std",
"pallet-contracts-primitives/std",
"pallet-contracts-rpc-runtime-api/std",
"pallet-contracts/std",
"pallet-session/std",
"pallet-timestamp/std",
"pallet-transaction-payment/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-utility/std",
"pallet-xcm/std",
"cumulus-pallet-aura-ext/std",
"cumulus-pallet-dmp-queue/std",
"cumulus-pallet-parachain-system/std",
"cumulus-pallet-xcm/std",
"cumulus-pallet-xcmp-queue/std",
"cumulus-primitives-core/std",
"cumulus-primitives-timestamp/std",
"cumulus-primitives-utility/std",
"parachains-common/std",
"parachain-info/std",
"polkadot-parachain/std",
"polkadot-runtime-common/std",
"kusama-runtime-constants/std",
"xcm/std",
"xcm-builder/std",
"xcm-executor/std",
]
# Make contract callable functions marked as __unstable__ available. Do not enable
# on live chains as those are subject to change.
contracts-unstable-interface = [
"pallet-contracts/unstable-interface"
]
runtime-benchmarks = [
"hex-literal",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"frame-benchmarking/runtime-benchmarks",
"frame-system-benchmarking",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-contracts/runtime-benchmarks",
"pallet-multisig/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-utility/runtime-benchmarks",
"pallet-xcm/runtime-benchmarks",
"pallet-collator-selection/runtime-benchmarks",
"cumulus-pallet-session-benchmarking/runtime-benchmarks",
]
try-runtime = [
"frame-try-runtime",
"frame-executive/try-runtime",
]
@@ -0,0 +1,9 @@
use substrate_wasm_builder::WasmBuilder;
fn main() {
WasmBuilder::new()
.with_current_project()
.export_heap_base()
.import_memory()
.build()
}
@@ -0,0 +1,73 @@
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub mod currency {
use kusama_runtime_constants as constants;
use node_primitives::Balance;
/// The existential deposit. Set to 1/10 of its parent Relay Chain.
pub const EXISTENTIAL_DEPOSIT: Balance = constants::currency::EXISTENTIAL_DEPOSIT / 10;
pub const UNITS: Balance = constants::currency::UNITS;
pub const CENTS: Balance = constants::currency::CENTS;
pub const GRAND: Balance = constants::currency::GRAND;
pub const MILLICENTS: Balance = constants::currency::MILLICENTS;
pub const fn deposit(items: u32, bytes: u32) -> Balance {
// map to 1/10 of what the kusama relay chain charges (v9020)
constants::currency::deposit(items, bytes) / 10
}
}
/// Fee-related.
pub mod fee {
use frame_support::weights::{
constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients,
WeightToFeePolynomial,
};
use node_primitives::Balance;
use smallvec::smallvec;
pub use sp_runtime::Perbill;
/// The block saturation level. Fees will be updates based on this value.
pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25);
/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the
/// node's balance type.
///
/// This should typically create a mapping between the following ranges:
/// - [0, MAXIMUM_BLOCK_WEIGHT]
/// - [Balance::min, Balance::max]
///
/// Yet, it can be used for any other sort of change to weight-fee. Some examples being:
/// - Setting it to `0` will essentially disable the weight fee.
/// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged.
pub struct WeightToFee;
impl WeightToFeePolynomial for WeightToFee {
type Balance = Balance;
fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
// in Kusama, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT:
// in Statemine, we map to 1/10 of that, or 1/100 CENT
let p = super::currency::CENTS;
let q = 100 * Balance::from(ExtrinsicBaseWeight::get());
smallvec![WeightToFeeCoefficient {
degree: 1,
negative: false,
coeff_frac: Perbill::from_rational(p % q, q),
coeff_integer: p / q,
}]
}
}
}
@@ -0,0 +1,866 @@
// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#![cfg_attr(not(feature = "std"), no_std)]
#![recursion_limit = "256"]
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
pub mod constants;
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{AccountIdLookup, BlakeTwo256, Block as BlockT},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use constants::{currency::*, fee::WeightToFee};
use frame_support::{
construct_runtime, match_type, parameter_types,
traits::{EnsureOneOf, Everything, Nothing},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight},
DispatchClass, IdentityFee, Weight,
},
PalletId,
};
use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureRoot,
};
pub use parachains_common as common;
use parachains_common::{
impls::DealWithFees, opaque, AccountId, BlockNumber, Hash, Header, Index, Signature,
AVERAGE_ON_INITIALIZE_RATIO, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION,
};
pub use parachains_common::{AuraId, Balance};
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
// Polkadot imports
use pallet_contracts::weights::WeightInfo;
use pallet_xcm::{EnsureXcm, IsMajorityOfBody, XcmPassthrough};
use polkadot_parachain::primitives::Sibling;
use polkadot_runtime_common::{BlockHashCount, RocksDbWeight, SlowAdjustingFeeUpdate};
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin,
FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, ParentIsPreset,
RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
UsingComponents,
};
use xcm_executor::{Config as XcmExecutorConfig, XcmExecutor};
/// The address format for describing accounts.
pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
/// Block type as expected by this runtime.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// A Block signed with a Justification
pub type SignedBlock = generic::SignedBlock<Block>;
/// BlockId type as expected by this runtime.
pub type BlockId = generic::BlockId<Block>;
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (
frame_system::CheckNonZeroSender<Runtime>,
frame_system::CheckSpecVersion<Runtime>,
frame_system::CheckTxVersion<Runtime>,
frame_system::CheckGenesis<Runtime>,
frame_system::CheckEra<Runtime>,
frame_system::CheckNonce<Runtime>,
frame_system::CheckWeight<Runtime>,
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
/// Extrinsic type that has already been checked.
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
/// Executive: handles dispatch to the various modules.
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
>;
// Prints debug output of the `contracts` pallet to stdout if the node is
// started with `-lruntime::contracts=debug`.
pub const CONTRACTS_DEBUG_OUTPUT: bool = true;
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: Aura,
}
}
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("canvas-kusama"),
impl_name: create_runtime_str!("canvas-kusama"),
authoring_version: 1,
spec_version: 15,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
// Since Canvas is a "live" chain (on Rococo anyways), we need to set this to `0` until a
// migration path to `state_version = 1` is ready.
//
// See the following PRs for more details:
// - https://github.com/paritytech/substrate/pull/9732
// - https://github.com/paritytech/substrate/pull/10073
state_version: 0,
};
/// The version information used to identify this runtime when compiled natively.
#[cfg(feature = "std")]
pub fn native_version() -> NativeVersion {
NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
}
parameter_types! {
pub const Version: RuntimeVersion = VERSION;
pub RuntimeBlockLength: BlockLength =
BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
.base_block(BlockExecutionWeight::get())
.for_class(DispatchClass::all(), |weights| {
weights.base_extrinsic = ExtrinsicBaseWeight::get();
})
.for_class(DispatchClass::Normal, |weights| {
weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
})
.for_class(DispatchClass::Operational, |weights| {
weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
// Operational transactions have some extra reserved space, so that they
// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
weights.reserved = Some(
MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
);
})
.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
.build_or_panic();
pub const SS58Prefix: u8 = 42;
}
// Configure FRAME pallets to include in runtime.
impl frame_system::Config for Runtime {
type BaseCallFilter = frame_support::traits::Everything;
type BlockWeights = RuntimeBlockWeights;
type BlockLength = RuntimeBlockLength;
type AccountId = AccountId;
type Call = Call;
type Lookup = AccountIdLookup<AccountId, ()>;
type Index = Index;
type BlockNumber = BlockNumber;
type Hash = Hash;
type Hashing = BlakeTwo256;
type Header = Header;
type Event = Event;
type Origin = Origin;
type BlockHashCount = BlockHashCount;
type DbWeight = RocksDbWeight;
type Version = Version;
type PalletInfo = PalletInfo;
type OnNewAccount = ();
type OnKilledAccount = ();
type AccountData = pallet_balances::AccountData<Balance>;
type SystemWeightInfo = frame_system::weights::SubstrateWeight<Runtime>;
type SS58Prefix = SS58Prefix;
type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
type MaxConsumers = frame_support::traits::ConstU32<16>;
}
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 = pallet_timestamp::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
pub const UncleGenerations: u32 = 0;
}
impl pallet_authorship::Config for Runtime {
type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Aura>;
type UncleGenerations = UncleGenerations;
type FilterUncle = ();
type EventHandler = (CollatorSelection,);
}
parameter_types! {
pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT;
pub const MaxLocks: u32 = 50;
pub const MaxReserves: u32 = 50;
}
impl pallet_balances::Config for Runtime {
type MaxLocks = MaxLocks;
/// 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 MaxReserves = MaxReserves;
type ReserveIdentifier = [u8; 8];
}
parameter_types! {
/// Relay Chain `TransactionByteFee` / 10
pub const TransactionByteFee: Balance = 1 * MILLICENTS;
pub const OperationalFeeMultiplier: u8 = 5;
}
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction =
pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees<Runtime>>;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = WeightToFee;
type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
type OperationalFeeMultiplier = OperationalFeeMultiplier;
}
parameter_types! {
// One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes.
pub const DepositBase: Balance = deposit(1, 88);
// Additional storage item size of 32 bytes.
pub const DepositFactor: Balance = deposit(0, 32);
pub const MaxSignatories: u16 = 100;
}
impl pallet_multisig::Config for Runtime {
type Event = Event;
type Call = Call;
type Currency = Balances;
type DepositBase = DepositBase;
type DepositFactor = DepositFactor;
type MaxSignatories = MaxSignatories;
type WeightInfo = pallet_multisig::weights::SubstrateWeight<Runtime>;
}
impl pallet_utility::Config for Runtime {
type Event = Event;
type Call = Call;
type PalletsOrigin = OriginCaller;
type WeightInfo = pallet_utility::weights::SubstrateWeight<Runtime>;
}
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 OnSystemEvent = ();
type SelfParaId = parachain_info::Pallet<Runtime>;
type DmpMessageHandler = DmpQueue;
type ReservedDmpWeight = ReservedDmpWeight;
type OutboundXcmpMessageSource = XcmpQueue;
type XcmpMessageHandler = XcmpQueue;
type ReservedXcmpWeight = ReservedXcmpWeight;
}
parameter_types! {
pub const DepositPerItem: Balance = deposit(1, 0);
pub const DepositPerByte: Balance = deposit(0, 1);
// The lazy deletion runs inside on_initialize.
pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *
RuntimeBlockWeights::get().max_block;
// The weight needed for decoding the queue should be less or equal than a fifth
// of the overall weight dedicated to the lazy deletion.
pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (
<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -
<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)
)) / 5) as u32;
pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();
}
impl pallet_contracts::Config for Runtime {
type Time = Timestamp;
type Randomness = RandomnessCollectiveFlip;
type Currency = Balances;
type Event = Event;
type Call = Call;
/// The safest default is to allow no calls at all.
///
/// Runtimes should whitelist dispatchables that are allowed to be called from contracts
/// and make sure they are stable. Dispatchables exposed to contracts are not allowed to
/// change because that would break already deployed contracts. The `Call` structure itself
/// is not allowed to change the indices of existing pallets, too.
type CallFilter = frame_support::traits::Nothing;
type DepositPerItem = DepositPerItem;
type DepositPerByte = DepositPerByte;
type WeightPrice = pallet_transaction_payment::Pallet<Self>;
type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
type ChainExtension = ();
type DeletionQueueDepth = DeletionQueueDepth;
type DeletionWeightLimit = DeletionWeightLimit;
type Schedule = Schedule;
type CallStack = [pallet_contracts::Frame<Self>; 31];
type AddressGenerator = pallet_contracts::DefaultAddressGenerator;
}
impl pallet_randomness_collective_flip::Config for Runtime {}
impl parachain_info::Config for Runtime {}
impl cumulus_pallet_aura_ext::Config for Runtime {}
parameter_types! {
pub const RelayLocation: MultiLocation = MultiLocation::parent();
pub const RelayNetwork: NetworkId = NetworkId::Any;
pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
}
/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
/// `Transact` in order to determine the dispatch Origin.
pub type LocationToAccountId = (
// The parent (Relay-chain) origin converts to the parent `AccountId`.
ParentIsPreset<AccountId>,
// Sibling parachain origins convert to AccountId via the `ParaId::into`.
SiblingParachainConvertsVia<Sibling, AccountId>,
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
AccountId32Aliases<RelayNetwork, AccountId>,
);
/// Means for transacting assets on this chain.
pub type LocalAssetTransactor = CurrencyAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
IsConcrete<RelayLocation>,
// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We don't track any teleports.
(),
>;
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
/// biases the kind of local `Origin` it will become.
pub type XcmOriginToTransactDispatchOrigin = (
// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
// foreign chains who want to have a local sovereign account on this chain which they control.
SovereignSignedViaLocation<LocationToAccountId, Origin>,
// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
// recognized.
RelayChainAsNative<RelayChainOrigin, Origin>,
// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
// recognized.
SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,
// Native signed account converter; this just converts an `AccountId32` origin into a normal
// `Origin::Signed` origin of the same 32-byte value.
SignedAccountId32AsNative<RelayNetwork, Origin>,
// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
XcmPassthrough<Origin>,
);
parameter_types! {
// One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate.
pub UnitWeightCost: Weight = 1_000_000_000;
pub const MaxInstructions: u32 = 100;
}
match_type! {
pub type ParentOrParentsExecutivePlurality: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) }
};
}
match_type! {
pub type ParentOrSiblings: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(_) }
};
}
pub type Barrier = (
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom<Everything>,
// Parent and its exec plurality get free execution
AllowUnpaidExecutionFrom<ParentOrParentsExecutivePlurality>,
// Expected responses are OK.
AllowKnownQueryResponses<PolkadotXcm>,
// Subscriptions for version tracking are OK.
AllowSubscriptionsFrom<ParentOrSiblings>,
);
pub struct XcmConfig;
impl XcmExecutorConfig 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 ROC
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;
}
parameter_types! {
pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;
}
/// Converts a local signed origin into an XCM multilocation.
/// Forms the basis for local origins sending/executing XCMs.
pub type LocalOriginToLocation = SignedToAccountId32<Origin, AccountId, RelayNetwork>;
/// The means for routing XCM messages which are not for local execution into the right message
/// queues.
pub type XcmRouter = (
// Two routers - use UMP to communicate with the relay chain:
cumulus_primitives_utility::ParentAsUmp<ParachainSystem, PolkadotXcm>,
// ..and XCMP to communicate with the sibling chains.
XcmpQueue,
);
impl pallet_xcm::Config for Runtime {
type Event = Event;
// We want to disallow users sending (arbitrary) XCMs from this chain.
type SendXcmOrigin = EnsureXcmOrigin<Origin, ()>;
type XcmRouter = XcmRouter;
// We support local origins dispatching XCM executions in principle...
type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
// ... but disallow generic XCM execution. As a result only teleports and reserve transfers are allowed.
type XcmExecuteFilter = Nothing;
type XcmExecutor = XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Everything;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
type LocationInverter = LocationInverter<Ancestry>;
type Origin = Origin;
type Call = Call;
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
}
impl cumulus_pallet_xcm::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
}
impl cumulus_pallet_xcmp_queue::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
type ChannelInfo = ParachainSystem;
type VersionWrapper = PolkadotXcm;
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
type ControllerOrigin = EnsureOneOf<
EnsureRoot<AccountId>,
EnsureXcm<IsMajorityOfBody<RelayLocation, ExecutiveBody>>,
>;
type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
}
impl cumulus_pallet_dmp_queue::Config for Runtime {
type Event = Event;
type XcmExecutor = XcmExecutor<XcmConfig>;
type ExecuteOverweightOrigin = EnsureRoot<AccountId>;
}
parameter_types! {
pub const Period: u32 = 6 * HOURS;
pub const Offset: u32 = 0;
pub const MaxAuthorities: u32 = 100_000;
}
impl pallet_session::Config for Runtime {
type Event = Event;
type ValidatorId = <Self as frame_system::Config>::AccountId;
// we don't have stash and controller, thus we don't need the convert as well.
type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
type ShouldEndSession = pallet_session::PeriodicSessions<Period, Offset>;
type NextSessionRotation = pallet_session::PeriodicSessions<Period, Offset>;
type SessionManager = CollatorSelection;
// Essentially just Aura, but lets be pedantic.
type SessionHandler = <SessionKeys as sp_runtime::traits::OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys;
type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
}
impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
type DisabledValidators = ();
type MaxAuthorities = MaxAuthorities;
}
parameter_types! {
pub const PotId: PalletId = PalletId(*b"PotStake");
pub const MaxCandidates: u32 = 1000;
pub const MinCandidates: u32 = 5;
pub const SessionLength: BlockNumber = 6 * HOURS;
pub const MaxInvulnerables: u32 = 100;
pub const ExecutiveBody: BodyId = BodyId::Executive;
}
/// We allow root and the Relay Chain council to execute privileged collator selection operations.
pub type CollatorSelectionUpdateOrigin =
EnsureOneOf<EnsureRoot<AccountId>, EnsureXcm<IsMajorityOfBody<RelayLocation, ExecutiveBody>>>;
impl pallet_collator_selection::Config for Runtime {
type Event = Event;
type Currency = Balances;
type UpdateOrigin = CollatorSelectionUpdateOrigin;
type PotId = PotId;
type MaxCandidates = MaxCandidates;
type MinCandidates = MinCandidates;
type MaxInvulnerables = MaxInvulnerables;
// should be a multiple of session or things will get inconsistent
type KickThreshold = Period;
type ValidatorId = <Self as frame_system::Config>::AccountId;
type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
type ValidatorRegistration = Session;
type WeightInfo = pallet_collator_selection::weights::SubstrateWeight<Runtime>;
}
// Create the runtime by composing the FRAME pallets that were previously configured.
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
// System support stuff.
System: frame_system::{Pallet, Call, Config, Storage, Event<T>} = 0,
ParachainSystem: cumulus_pallet_parachain_system::{
Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned,
} = 1,
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 2,
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 3,
ParachainInfo: parachain_info::{Pallet, Storage, Config} = 4,
// Monetary stuff.
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 10,
TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 11,
// Collator support. The order of these 5 are important and shall not change.
Authorship: pallet_authorship::{Pallet, Call, Storage} = 20,
CollatorSelection: pallet_collator_selection::{Pallet, Call, Storage, Event<T>, Config<T>} = 21,
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>} = 22,
Aura: pallet_aura::{Pallet, Storage, Config<T>} = 23,
AuraExt: cumulus_pallet_aura_ext::{Pallet, Storage, Config} = 24,
// XCM helpers.
XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 30,
PolkadotXcm: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin, Config} = 31,
CumulusXcm: cumulus_pallet_xcm::{Pallet, Event<T>, Origin} = 32,
DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 33,
// Smart Contracts.
Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 40,
// Handy utilities.
Utility: pallet_utility::{Pallet, Call, Event} = 50,
Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 51,
}
);
#[cfg(feature = "runtime-benchmarks")]
#[macro_use]
extern crate frame_benchmarking;
#[cfg(feature = "runtime-benchmarks")]
mod benches {
define_benchmarks!(
[frame_system, SystemBench::<Runtime>]
[pallet_balances, Balances]
[pallet_multisig, Multisig]
[pallet_session, SessionBench::<Runtime>]
[pallet_utility, Utility]
[pallet_timestamp, Timestamp]
[pallet_collator_selection, CollatorSelection]
[pallet_contracts, Contracts]
);
}
impl_runtime_apis! {
impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
fn slot_duration() -> sp_consensus_aura::SlotDuration {
sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
}
fn authorities() -> Vec<AuraId> {
Aura::authorities().into_inner()
}
}
impl sp_api::Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn execute_block(block: Block) {
Executive::execute_block(block)
}
fn initialize_block(header: &<Block as BlockT>::Header) {
Executive::initialize_block(header)
}
}
impl sp_api::Metadata<Block> for Runtime {
fn metadata() -> OpaqueMetadata {
OpaqueMetadata::new(Runtime::metadata().into())
}
}
impl sp_block_builder::BlockBuilder<Block> for Runtime {
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
Executive::apply_extrinsic(extrinsic)
}
fn finalize_block() -> <Block as BlockT>::Header {
Executive::finalize_block()
}
fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
data.create_extrinsics()
}
fn check_inherents(
block: Block,
data: sp_inherents::InherentData,
) -> sp_inherents::CheckInherentsResult {
data.check_extrinsics(&block)
}
}
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(
source: TransactionSource,
tx: <Block as BlockT>::Extrinsic,
block_hash: <Block as BlockT>::Hash,
) -> TransactionValidity {
Executive::validate_transaction(source, tx, block_hash)
}
}
impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
fn offchain_worker(header: &<Block as BlockT>::Header) {
Executive::offchain_worker(header)
}
}
impl sp_session::SessionKeys<Block> for Runtime {
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
SessionKeys::generate(seed)
}
fn decode_session_keys(
encoded: Vec<u8>,
) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
SessionKeys::decode_into_raw_public_keys(&encoded)
}
}
impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
fn account_nonce(account: AccountId) -> Index {
System::account_nonce(account)
}
}
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
fn query_info(
uxt: <Block as BlockT>::Extrinsic,
len: u32,
) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
TransactionPayment::query_info(uxt, len)
}
fn query_fee_details(
uxt: <Block as BlockT>::Extrinsic,
len: u32,
) -> pallet_transaction_payment::FeeDetails<Balance> {
TransactionPayment::query_fee_details(uxt, len)
}
}
impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
ParachainSystem::collect_collation_info(header)
}
}
impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>
for Runtime
{
fn call(
origin: AccountId,
dest: AccountId,
value: Balance,
gas_limit: u64,
storage_deposit_limit: Option<Balance>,
input_data: Vec<u8>,
) -> pallet_contracts_primitives::ContractExecResult<Balance> {
Contracts::bare_call(origin, dest, value, gas_limit, storage_deposit_limit, input_data, CONTRACTS_DEBUG_OUTPUT)
}
fn instantiate(
origin: AccountId,
value: Balance,
gas_limit: u64,
storage_deposit_limit: Option<Balance>,
code: pallet_contracts_primitives::Code<Hash>,
data: Vec<u8>,
salt: Vec<u8>,
) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, Balance>
{
Contracts::bare_instantiate(origin, value, gas_limit, storage_deposit_limit, code, data, salt, CONTRACTS_DEBUG_OUTPUT)
}
fn upload_code(
origin: AccountId,
code: Vec<u8>,
storage_deposit_limit: Option<Balance>,
) -> pallet_contracts_primitives::CodeUploadResult<Hash, Balance>
{
Contracts::bare_upload_code(origin, code, storage_deposit_limit)
}
fn get_storage(
address: AccountId,
key: [u8; 32],
) -> pallet_contracts_primitives::GetStorageResult {
Contracts::get_storage(address, key)
}
}
#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime<Block> for Runtime {
fn on_runtime_upgrade() -> (Weight, Weight) {
log::info!("try-runtime::on_runtime_upgrade canvas");
let weight = Executive::try_runtime_upgrade().unwrap();
(weight, RuntimeBlockWeights::get().max_block)
}
fn execute_block_no_check(block: Block) -> Weight {
Executive::execute_block_no_check(block)
}
}
#[cfg(feature = "runtime-benchmarks")]
impl frame_benchmarking::Benchmark<Block> for Runtime {
fn benchmark_metadata(extra: bool) -> (
Vec<frame_benchmarking::BenchmarkList>,
Vec<frame_support::traits::StorageInfo>,
) {
use frame_benchmarking::{Benchmarking, BenchmarkList};
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
let mut list = Vec::<BenchmarkList>::new();
list_benchmarks!(list, extra);
let storage_info = AllPalletsWithSystem::storage_info();
return (list, storage_info)
}
fn dispatch_benchmark(
config: frame_benchmarking::BenchmarkConfig
) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {
use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey};
use frame_system_benchmarking::Pallet as SystemBench;
impl frame_system_benchmarking::Config for Runtime {}
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
let whitelist: Vec<TrackedStorageKey> = vec![
// Block Number
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),
// Total Issuance
hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),
// Execution Phase
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),
// Event Count
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),
// System Events
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),
];
let mut batches = Vec::<BenchmarkBatch>::new();
let params = (&config, &whitelist);
add_benchmarks!(params, batches);
if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
Ok(batches)
}
}
}
struct CheckInherents;
impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
fn check_inherents(
block: &Block,
relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
) -> sp_inherents::CheckInherentsResult {
let relay_chain_slot = relay_state_proof
.read_slot()
.expect("Could not read the relay chain slot from the proof");
let inherent_data =
cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
relay_chain_slot,
sp_std::time::Duration::from_secs(6),
)
.create_inherent_data()
.expect("Could not create the timestamp inherent data");
inherent_data.check_extrinsics(&block)
}
}
cumulus_pallet_parachain_system::register_validate_block! {
Runtime = Runtime,
BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
CheckInherents = CheckInherents,
}
@@ -834,3 +834,254 @@ fn westmint_genesis(
},
}
}
/// We use the same runtime on kusama and rococo.
pub type CanvasKusamaChainSpec =
sc_service::GenericChainSpec<canvas_kusama_runtime::GenesisConfig, Extensions>;
/// No relay chain suffix because the id is the same over all relay chains.
const CANVAS_PARACHAIN_ID: u32 = 1002;
/// The existential deposit is determined by the runtime "canvas-kusama".
const CANVAS_KUSAMA_ED: canvas_kusama_runtime::Balance =
canvas_kusama_runtime::constants::currency::EXISTENTIAL_DEPOSIT;
pub fn canvas_rococo_development_config() -> CanvasKusamaChainSpec {
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "ROC".into());
properties.insert("tokenDecimals".into(), 12.into());
CanvasKusamaChainSpec::from_genesis(
// Name
"Canvas on Rococo Development",
// ID
"canvas-rococo-dev",
ChainType::Development,
move || {
canvas_kusama_genesis(
// initial collators.
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed::<canvas_kusama_runtime::AuraId>("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed::<canvas_kusama_runtime::AuraId>("Bob"),
),
],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
CANVAS_PARACHAIN_ID.into(),
)
},
Vec::new(),
None,
None,
None,
None,
Extensions {
relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
para_id: CANVAS_PARACHAIN_ID,
},
)
}
pub fn canvas_rococo_local_config() -> CanvasKusamaChainSpec {
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "ROC".into());
properties.insert("tokenDecimals".into(), 12.into());
CanvasKusamaChainSpec::from_genesis(
// Name
"Canvas on Rococo",
// ID
"canvas-rococo-local",
ChainType::Local,
move || {
canvas_kusama_genesis(
// initial collators.
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed::<canvas_kusama_runtime::AuraId>("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed::<canvas_kusama_runtime::AuraId>("Bob"),
),
],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
CANVAS_PARACHAIN_ID.into(),
)
},
// Bootnodes
Vec::new(),
// Telemetry
None,
// Protocol ID
None,
// Fork ID
None,
// Properties
Some(properties),
// Extensions
Extensions {
relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
para_id: CANVAS_PARACHAIN_ID,
},
)
}
pub fn canvas_rococo_config() -> CanvasKusamaChainSpec {
// Give your base currency a unit name and decimal places
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "ROC".into());
properties.insert("tokenDecimals".into(), 12.into());
CanvasKusamaChainSpec::from_genesis(
// Name
"Canvas on Rococo",
// ID
"canvas-rococo",
ChainType::Live,
move || {
canvas_kusama_genesis(
vec![
// 5GKFbTTgrVS4Vz1UWWHPqMZQNFWZtqo7H2KpCDyYhEL3aS26
(
hex!["bc09354c12c054c8f6b3da208485eacec4ac648bad348895273b37bab5a0937c"]
.into(),
hex!["bc09354c12c054c8f6b3da208485eacec4ac648bad348895273b37bab5a0937c"]
.unchecked_into(),
),
// 5EPRJHm2GpABVWcwnAujcrhnrjFZyDGd5TwKFzkBoGgdRyv2
(
hex!["66be63b7bcbfb91040e5248e2d1ceb822cf219c57848c5924ffa3a1f8e67ba72"]
.into(),
hex!["66be63b7bcbfb91040e5248e2d1ceb822cf219c57848c5924ffa3a1f8e67ba72"]
.unchecked_into(),
),
// 5GH62vrJrVZxLREcHzm2PR5uTLAT5RQMJitoztCGyaP4o3uM
(
hex!["ba62886472a0a9f66b5e39f1469ce1c5b3d8cad6be39078daf16f111e89d1e44"]
.into(),
hex!["ba62886472a0a9f66b5e39f1469ce1c5b3d8cad6be39078daf16f111e89d1e44"]
.unchecked_into(),
),
// 5FHfoJDLdjRYX5KXLRqMDYBbWrwHLMtti21uK4QByUoUAbJF
(
hex!["8e97f65cda001976311df9bed39e8d0c956089093e94a75ef76fe9347a0eda7b"]
.into(),
hex!["8e97f65cda001976311df9bed39e8d0c956089093e94a75ef76fe9347a0eda7b"]
.unchecked_into(),
),
],
// Warning: The configuration for a production chain should not contain
// any endowed accounts here, otherwise it'll be minting extra native tokens
// from the relay chain on the parachain.
vec![
// NOTE: Remove endowed accounts if deployed on other relay chains.
// Endowed accounts
hex!["baa78c7154c7f82d6d377177e20bcab65d327eca0086513f9964f5a0f6bdad56"].into(),
// AccountId of an account which `ink-waterfall` uses for automated testing
hex!["0e47e2344d523c3cc5c34394b0d58b9a4200e813a038e6c5a6163cc07d70b069"].into(),
],
CANVAS_PARACHAIN_ID.into(),
)
},
// Bootnodes
vec![
"/ip4/34.90.191.237/tcp/30333/p2p/12D3KooWKg3Rpxcr9oJ8n6khoxpGKWztCZydtUZk2cojHqnfLrpj"
.parse()
.expect("MultiaddrWithPeerId"),
"/ip4/35.204.68.28/tcp/30333/p2p/12D3KooWPEXYrz8tHU3nDtPoPw4V7ou5dzMEWSTuUj7vaWiYVAVh"
.parse()
.expect("MultiaddrWithPeerId"),
"/ip4/34.90.139.15/tcp/30333/p2p/12D3KooWEVU8AFNary4nP4qEnEcwJaRuy59Wefekzdu9pKbnVEhk"
.parse()
.expect("MultiaddrWithPeerId"),
"/ip4/35.204.99.97/tcp/30333/p2p/12D3KooWP6pV3ZmcXzGDjv8ZMgA6nZxfAKDxSz4VNiLx6vVCQgJX"
.parse()
.expect("MultiaddrWithPeerId"),
],
// Telemetry
None,
// Protocol ID
None,
// Fork ID
None,
// Properties
Some(properties),
// Extensions
Extensions { relay_chain: "rococo".into(), para_id: CANVAS_PARACHAIN_ID },
)
}
fn canvas_kusama_genesis(
invulnerables: Vec<(AccountId, AuraId)>,
endowed_accounts: Vec<AccountId>,
id: ParaId,
) -> canvas_kusama_runtime::GenesisConfig {
canvas_kusama_runtime::GenesisConfig {
system: canvas_kusama_runtime::SystemConfig {
code: canvas_kusama_runtime::WASM_BINARY
.expect("WASM binary was not build, please build it!")
.to_vec(),
},
balances: canvas_kusama_runtime::BalancesConfig {
balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(),
},
parachain_info: canvas_kusama_runtime::ParachainInfoConfig { parachain_id: id },
collator_selection: canvas_kusama_runtime::CollatorSelectionConfig {
invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(),
candidacy_bond: CANVAS_KUSAMA_ED * 16,
..Default::default()
},
session: canvas_kusama_runtime::SessionConfig {
keys: invulnerables
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
canvas_kusama_runtime::SessionKeys { aura }, // session keys
)
})
.collect(),
},
// no need to pass anything to aura, in fact it will panic if we do. Session will take care
// of this.
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: canvas_kusama_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
}
}
+33 -3
View File
@@ -18,9 +18,9 @@ use crate::{
chain_spec,
cli::{Cli, RelayChainCli, Subcommand},
service::{
new_partial, Block, RococoParachainRuntimeExecutor, SeedlingRuntimeExecutor,
ShellRuntimeExecutor, StatemineRuntimeExecutor, StatemintRuntimeExecutor,
WestmintRuntimeExecutor,
new_partial, Block, CanvasKusamaRuntimeExecutor, RococoParachainRuntimeExecutor,
SeedlingRuntimeExecutor, ShellRuntimeExecutor, StatemineRuntimeExecutor,
StatemintRuntimeExecutor, WestmintRuntimeExecutor,
},
};
use codec::Encode;
@@ -47,6 +47,7 @@ trait IdentifyChain {
fn is_statemint(&self) -> bool;
fn is_statemine(&self) -> bool;
fn is_westmint(&self) -> bool;
fn is_canvas_kusama(&self) -> bool;
}
impl IdentifyChain for dyn sc_service::ChainSpec {
@@ -65,6 +66,10 @@ impl IdentifyChain for dyn sc_service::ChainSpec {
fn is_westmint(&self) -> bool {
self.id().starts_with("westmint")
}
fn is_canvas_kusama(&self) -> bool {
// we use the same runtime on rococo and kusama
self.id().starts_with("canvas-kusama") || self.id().starts_with("canvas-rococo")
}
}
impl<T: sc_service::ChainSpec + 'static> IdentifyChain for T {
@@ -83,6 +88,9 @@ impl<T: sc_service::ChainSpec + 'static> IdentifyChain for T {
fn is_westmint(&self) -> bool {
<dyn sc_service::ChainSpec>::is_westmint(self)
}
fn is_canvas_kusama(&self) -> bool {
<dyn sc_service::ChainSpec>::is_canvas_kusama(self)
}
}
fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
@@ -126,6 +134,10 @@ fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, St
"westmint" => Box::new(chain_spec::ChainSpec::from_json_bytes(
&include_bytes!("../res/westmint.json")[..],
)?),
// -- Canvas on Rococo
"canvas-rococo-dev" => Box::new(chain_spec::canvas_rococo_development_config()),
"canvas-rococo-local" => Box::new(chain_spec::canvas_rococo_local_config()),
"canvas-rococo" => Box::new(chain_spec::canvas_rococo_config()),
"" => Box::new(chain_spec::get_chain_spec()),
path => {
let chain_spec = chain_spec::ChainSpec::from_json_file(path.into())?;
@@ -139,6 +151,8 @@ fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, St
Box::new(chain_spec::ShellChainSpec::from_json_file(path.into())?)
} else if chain_spec.is_seedling() {
Box::new(chain_spec::SeedlingChainSpec::from_json_file(path.into())?)
} else if chain_spec.is_canvas_kusama() {
Box::new(chain_spec::CanvasKusamaChainSpec::from_json_file(path.into())?)
} else {
Box::new(chain_spec)
}
@@ -192,6 +206,8 @@ impl SubstrateCli for Cli {
&shell_runtime::VERSION
} else if chain_spec.is_seedling() {
&seedling_runtime::VERSION
} else if chain_spec.is_canvas_kusama() {
&canvas_kusama_runtime::VERSION
} else {
&rococo_parachain_runtime::VERSION
}
@@ -296,6 +312,15 @@ macro_rules! construct_async_run {
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
} else if runner.config().chain_spec.is_canvas_kusama() {
runner.async_run(|$config| {
let $components = new_partial::<canvas_kusama_runtime::RuntimeApi, CanvasKusamaRuntimeExecutor, _>(
&$config,
crate::service::canvas_kusama_build_import_queue,
)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
} else {
runner.async_run(|$config| {
let $components = new_partial::<
@@ -542,6 +567,11 @@ pub fn run() -> Result<()> {
.await
.map(|r| r.0)
.map_err(Into::into)
} else if config.chain_spec.is_canvas_kusama() {
crate::service::start_canvas_kusama_node(config, polkadot_config, id)
.await
.map(|r| r.0)
.map_err(Into::into)
} else {
crate::service::start_rococo_parachain_node(config, polkadot_config, id)
.await
+31 -2
View File
@@ -20,6 +20,8 @@
use std::sync::Arc;
use pallet_contracts_rpc::{Contracts, ContractsApi};
use parachains_common::{AccountId, Balance, Block, BlockNumber, Hash, Index as Nonce};
use sc_client_api::AuxStore;
pub use sc_rpc::{DenyUnsafe, SubscriptionTaskExecutor};
use sc_transaction_pool_api::TransactionPool;
@@ -27,8 +29,6 @@ use sp_api::ProvideRuntimeApi;
use sp_block_builder::BlockBuilder;
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
use parachains_common::{AccountId, Balance, Block, Index as Nonce};
/// A type representing all RPC extensions.
pub type RpcExtension = jsonrpc_core::IoHandler<sc_rpc::Metadata>;
@@ -68,3 +68,32 @@ where
io
}
/// Instantiate all RPCs we want at the canvas-kusama chain.
pub fn create_canvas_kusama<C, P>(deps: FullDeps<C, P>) -> RpcExtension
where
C: ProvideRuntimeApi<Block>
+ HeaderBackend<Block>
+ AuxStore
+ HeaderMetadata<Block, Error = BlockChainError>
+ Send
+ Sync
+ 'static,
C::Api: frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
C::Api: pallet_contracts_rpc::ContractsRuntimeApi<Block, AccountId, Balance, BlockNumber, Hash>,
C::Api: BlockBuilder<Block>,
P: TransactionPool + Sync + Send + 'static,
{
use frame_rpc_system::{FullSystem, SystemApi};
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
let mut io = jsonrpc_core::IoHandler::default();
let FullDeps { client, pool, deny_unsafe } = deps;
io.extend_with(SystemApi::to_delegate(FullSystem::new(client.clone(), pool, deny_unsafe)));
io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone())));
io.extend_with(ContractsApi::to_delegate(Contracts::new(client)));
io
}
+354 -1
View File
@@ -32,7 +32,7 @@ use cumulus_relay_chain_local::build_relay_chain_interface;
use polkadot_service::NativeExecutionDispatch;
use crate::rpc;
pub use parachains_common::{AccountId, Balance, Block, Hash, Header, Index as Nonce};
pub use parachains_common::{AccountId, Balance, Block, BlockNumber, Hash, Header, Index as Nonce};
use cumulus_client_consensus_relay_chain::Verifier as RelayChainVerifier;
use futures::lock::Mutex;
@@ -148,6 +148,21 @@ impl sc_executor::NativeExecutionDispatch for WestmintRuntimeExecutor {
}
}
/// Native Canvas on Kusama executor instance.
pub struct CanvasKusamaRuntimeExecutor;
impl sc_executor::NativeExecutionDispatch for CanvasKusamaRuntimeExecutor {
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
canvas_kusama_runtime::api::dispatch(method, data)
}
fn native_version() -> sc_executor::NativeVersion {
canvas_kusama_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
@@ -1252,3 +1267,341 @@ where
)
.await
}
#[sc_tracing::logging::prefix_logs_with("Parachain")]
async fn start_canvas_kusama_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>
+ pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
+ frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
+ pallet_contracts_rpc::ContractsRuntimeApi<Block, AccountId, Balance, BlockNumber, Hash>,
sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,
Executor: sc_executor::NativeExecutionDispatch + 'static,
RB: Fn(
Arc<TFullClient<Block, RuntimeApi, Executor>>,
) -> Result<jsonrpc_core::IoHandler<sc_rpc::Metadata>, sc_service::Error>
+ 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,
> + 'static,
BIC: FnOnce(
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
Option<&Registry>,
Option<TelemetryHandle>,
&TaskManager,
Arc<dyn RelayChainInterface>,
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 client = params.client.clone();
let backend = params.backend.clone();
let mut task_manager = params.task_manager;
let (relay_chain_interface, collator_key) =
build_relay_chain_interface(polkadot_config, telemetry_worker_handle, &mut task_manager)
.map_err(|e| match e {
polkadot_service::Error::Sub(x) => x,
s => format!("{}", s).into(),
})?;
let block_announce_validator = BlockAnnounceValidator::new(relay_chain_interface.clone(), id);
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 import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue);
let (network, system_rpc_tx, start_network) =
sc_service::build_network(sc_service::BuildNetworkParams {
config: &parachain_config,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue: import_queue.clone(),
block_announce_validator_builder: Some(Box::new(|_| {
Box::new(block_announce_validator)
})),
warp_sync: None,
})?;
let rpc_extensions_builder = {
let client = client.clone();
let transaction_pool = transaction_pool.clone();
Box::new(move |deny_unsafe, _| {
let deps = crate::rpc::FullDeps {
client: client.clone(),
pool: transaction_pool.clone(),
deny_unsafe,
};
Ok(crate::rpc::create_canvas_kusama(deps))
})
};
sc_service::spawn_tasks(sc_service::SpawnTasksParams {
rpc_extensions_builder,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
task_manager: &mut task_manager,
config: parachain_config,
keystore: params.keystore_container.sync_keystore(),
backend: backend.clone(),
network: network.clone(),
system_rpc_tx,
telemetry: telemetry.as_mut(),
})?;
let announce_block = {
let network = network.clone();
Arc::new(move |hash, data| network.announce_block(hash, data))
};
let relay_chain_slot_duration = Duration::from_secs(6);
if validator {
let parachain_consensus = build_consensus(
client.clone(),
prometheus_registry.as_ref(),
telemetry.as_ref().map(|t| t.handle()),
&task_manager,
relay_chain_interface.clone(),
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_interface,
spawner,
parachain_consensus,
import_queue,
collator_key,
relay_chain_slot_duration,
};
start_collator(params).await?;
} else {
let params = StartFullNodeParams {
client: client.clone(),
announce_block,
task_manager: &mut task_manager,
para_id: id,
relay_chain_interface,
relay_chain_slot_duration,
import_queue,
};
start_full_node(params)?;
}
start_network.start_network();
Ok((task_manager, client))
}
#[allow(clippy::type_complexity)]
pub fn canvas_kusama_build_import_queue(
client: Arc<
TFullClient<
Block,
canvas_kusama_runtime::RuntimeApi,
NativeElseWasmExecutor<CanvasKusamaRuntimeExecutor>,
>,
>,
config: &Configuration,
telemetry: Option<TelemetryHandle>,
task_manager: &TaskManager,
) -> Result<
sc_consensus::DefaultImportQueue<
Block,
TFullClient<
Block,
canvas_kusama_runtime::RuntimeApi,
NativeElseWasmExecutor<CanvasKusamaRuntimeExecutor>,
>,
>,
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 parachain node.
pub async fn start_canvas_kusama_node(
parachain_config: Configuration,
polkadot_config: Configuration,
id: ParaId,
) -> sc_service::error::Result<(
TaskManager,
Arc<
TFullClient<
Block,
canvas_kusama_runtime::RuntimeApi,
NativeElseWasmExecutor<CanvasKusamaRuntimeExecutor>,
>,
>,
)> {
start_canvas_kusama_node_impl::<
canvas_kusama_runtime::RuntimeApi,
CanvasKusamaRuntimeExecutor,
_,
_,
_,
>(
parachain_config,
polkadot_config,
id,
|_| Ok(Default::default()),
canvas_kusama_build_import_queue,
|client,
prometheus_registry,
telemetry,
task_manager,
relay_chain_interface,
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(),
);
Ok(AuraConsensus::build::<sp_consensus_aura::sr25519::AuthorityPair, _, _, _, _, _, _>(
BuildAuraConsensusParams {
proposer_factory,
create_inherent_data_providers: move |_, (relay_parent, validation_data)| {
let relay_chain_interface = relay_chain_interface.clone();
async move {
let parachain_inherent =
cumulus_primitives_parachain_inherent::ParachainInherentData::create_at(
relay_parent,
&relay_chain_interface,
&validation_data,
id,
).await;
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(),
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),
// And a maximum of 750ms if slots are skipped
max_block_proposal_slot_portion: Some(SlotProportion::new(1f32 / 16f32)),
telemetry,
},
))
},
)
.await
}