Initial teyrchain template from Pezkuwi SDK

This commit is contained in:
2025-12-06 09:57:50 +03:00
commit 0b36245b1b
39 changed files with 4120 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
[package]
name = "teyrchain-template"
description = "A teyrchain-template helper crate to keep documentation in sync with the template's components."
version = "0.0.0"
license = "Unlicense"
authors.workspace = true
homepage.workspace = true
repository.workspace = true
edition.workspace = true
publish = false
[dependencies]
docify = { workspace = true }
[features]
generate-readme = []
+28
View File
@@ -0,0 +1,28 @@
FROM docker.io/paritytech/ci-unified:latest as builder
WORKDIR /polkadot
COPY . /polkadot
RUN cargo fetch
RUN cargo build --workspace --locked --profile production
FROM docker.io/parity/base-bin:latest
COPY --from=builder /polkadot/target/production/parachain-template-node /usr/local/bin
USER root
RUN useradd -m -u 1001 -U -s /bin/sh -d /polkadot polkadot && \
mkdir -p /data /polkadot/.local/share && \
chown -R polkadot:polkadot /data && \
ln -s /data /polkadot/.local/share/polkadot && \
# unclutter and minimize the attack surface
rm -rf /usr/bin /usr/sbin && \
# check if executable works in this container
/usr/local/bin/parachain-template-node --version
USER polkadot
EXPOSE 30333 9933 9944 9615
VOLUME ["/data"]
ENTRYPOINT ["/usr/local/bin/parachain-template-node"]
+24
View File
@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org>
+268
View File
@@ -0,0 +1,268 @@
<div align="center">
# Pezkuwi SDK's Teyrchain Template
<img height="70px" alt="Pezkuwi SDK Logo" src="https://github.com/pezkuwichain/pezkuwi-sdk/raw/master/docs/images/Polkadot_Logo_Horizontal_Pink_White.png#gh-dark-mode-only"/>
<img height="70px" alt="Pezkuwi SDK Logo" src="https://github.com/pezkuwichain/pezkuwi-sdk/raw/master/docs/images/Polkadot_Logo_Horizontal_Pink_Black.png#gh-light-mode-only"/>
> This is a template for creating a [teyrchain](https://wiki.network.pezkuwichain.io/docs/learn-parachains) based on Pezkuwi SDK.
>
> This template is automatically updated after releases in the main [Pezkuwi SDK monorepo](https://github.com/pezkuwichain/pezkuwi-sdk).
</div>
## Table of Contents
- [Intro](#intro)
- [Template Structure](#template-structure)
- [Getting Started](#getting-started)
- [Starting a Development Chain](#starting-a-development-chain)
- [Omni Node](#omni-node-prerequisites)
- [Zombienet setup with Omni Node](#zombienet-setup-with-omni-node)
- [Teyrchain Template Node](#teyrchain-template-node)
- [Connect with the Pezkuwi-JS Apps Front-End](#connect-with-the-pezkuwi-js-apps-front-end)
- [Takeaways](#takeaways)
- [Runtime development](#runtime-development)
- [Contributing](#contributing)
- [Getting Help](#getting-help)
## Intro
- ⏫ This template provides a starting point to build a [teyrchain](https://wiki.network.pezkuwichain.io/docs/learn-parachains).
- ☁️ It is based on the
[Cumulus](https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/polkadot_sdk/cumulus/index.html) framework.
- 🔧 Its runtime is configured with a single custom pallet as a starting point, and a handful of ready-made pallets
such as a [Balances pallet](https://docs.pezkuwichain.io/sdk/master/pallet_balances/index.html).
- 👉 Learn more about teyrchains [here](https://wiki.network.pezkuwichain.io/docs/learn-parachains)
## Template Structure
A Pezkuwi SDK based project such as this one consists of:
- 🧮 the [Runtime](./runtime/README.md) - the core logic of the teyrchain.
- 🎨 the [Pallets](./pallets/README.md) - from which the runtime is constructed.
- 💿 a [Node](./node/README.md) - the binary application, not part of the project default-members list and not compiled unless
building the project with `--workspace` flag, which builds all workspace members, and is an alternative to
[Omni Node](https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/reference_docs/omni_node/index.html).
## Getting Started
- 🦀 The template is using the Rust language.
- 👉 Check the
[Rust installation instructions](https://www.rust-lang.org/tools/install) for your system.
- 🛠️ Depending on your operating system and Rust version, there might be additional
packages required to compile this template - please take note of the Rust compiler output.
Fetch teyrchain template code:
```sh
git clone https://github.com/pezkuwichain/pezkuwi-sdk-parachain-template.git teyrchain-template
cd teyrchain-template
```
## Starting a Development Chain
The teyrchain template relies on a hardcoded teyrchain id which is defined in the runtime code
and referenced throughout the contents of this file as `{{TEYRCHAIN_ID}}`. Please replace
any command or file referencing this placeholder with the value of the `TEYRCHAIN_ID` constant:
<!-- docify::embed!("runtime/src/genesis_config_presets.rs", TEYRCHAIN_ID)-->
### Omni Node Prerequisites
[Omni Node](https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/reference_docs/omni_node/index.html) can
be used to run the teyrchain template's runtime. `pezkuwi-omni-node` binary crate usage is described at a high-level
[on crates.io](https://crates.io/crates/polkadot-omni-node).
#### Install `pezkuwi-omni-node`
```sh
cargo install pezkuwi-omni-node
```
> For more advanced options, please see the installation section at [`crates.io/omni-node`](https://crates.io/crates/polkadot-omni-node).
#### Build `teyrchain-template-runtime`
```sh
cargo build --profile production
```
#### Install `staging-chain-spec-builder`
```sh
cargo install staging-chain-spec-builder
```
> For more advanced options, please see the installation section at [`crates.io/staging-chain-spec-builder`](https://crates.io/crates/staging-chain-spec-builder).
#### Use `chain-spec-builder` to generate the `chain_spec.json` file
```sh
chain-spec-builder create --relay-chain "pezkuwichain-local" --runtime \
target/release/wbuild/teyrchain-template-runtime/teyrchain_template_runtime.wasm named-preset development
```
**Note**: the `relay-chain` flag is required by Omni Node. The `relay-chain` value is set in accordance
with the relay chain ID where this instantiation of teyrchain-template will connect to.
#### Run Omni Node
Start Omni Node with the generated chain spec. We'll start it in development mode (without a relay chain config), producing
and finalizing blocks based on manual seal, configured below to seal a block with each second.
```bash
pezkuwi-omni-node --chain <path/to/chain_spec.json> --dev --dev-block-time 1000
```
However, such a setup is not close to what would run in production, and for that we need to setup a local
relay chain network that will help with the block finalization. In this guide we'll setup a local relay chain
as well. We'll not do it manually, by starting one node at a time, but we'll use [zombienet](https://paritytech.github.io/zombienet/intro.html).
Follow through the next section for more details on how to do it.
### Zombienet setup with Omni Node
Assuming we continue from the last step of the previous section, we have a chain spec and we need to setup a relay chain.
We can install `zombienet` as described [here](https://paritytech.github.io/zombienet/install.html#installation), and
`zombienet-omni-node.toml` contains the network specification we want to start.
#### Relay chain prerequisites
Download the `pezkuwi` (and the accompanying `pezkuwi-prepare-worker` and `pezkuwi-execute-worker`) binaries from
[Pezkuwi SDK releases](https://github.com/pezkuwichain/pezkuwi-sdk/releases). Then expose them on `PATH` like so:
```sh
export PATH="$PATH:<path/to/binaries>"
```
#### Update `zombienet-omni-node.toml` with a valid chain spec path
To simplify the process of using the teyrchain-template with zombienet and Omni Node, we've added a pre-configured
development chain spec (dev_chain_spec.json) to the teyrchain template. The zombienet-omni-node.toml file of this
template points to it, but you can update it to an updated chain spec generated on your machine. To generate a
chain spec refer to [staging-chain-spec-builder](https://crates.io/crates/staging-chain-spec-builder)
Then make the changes in the network specification like so:
```toml
# ...
[[teyrchains]]
id = "<TEYRCHAIN_ID>"
chain_spec_path = "<TO BE UPDATED WITH A VALID PATH>"
# ...
```
#### Start the network
```sh
zombienet --provider native spawn zombienet-omni-node.toml
```
### Teyrchain Template Node
As mentioned in the `Template Structure` section, the `node` crate is optionally compiled and it is an alternative
to `Omni Node`. Similarly, it requires setting up a relay chain, and we'll use `zombienet` once more.
#### Install the `teyrchain-template-node`
```sh
cargo install --path node --locked
```
#### Setup and start the network
For setup, please consider the instructions for `zombienet` installation [here](https://paritytech.github.io/zombienet/install.html#installation)
and [relay chain prerequisites](#relay-chain-prerequisites).
We're left just with starting the network:
```sh
zombienet --provider native spawn zombienet.toml
```
### Connect with the Pezkuwi-JS Apps Front-End
- 🌐 You can interact with your local node using the
hosted version of the Pezkuwi/Substrate Portal:
[relay chain](https://pezkuwichain.io/#/explorer?rpc=ws://localhost:9944)
and [teyrchain](https://pezkuwichain.io/#/explorer?rpc=ws://localhost:9988).
- 🪐 A hosted version is also
available on [IPFS](https://dotapps.io/).
- 🧑‍🔧 You can also find the source code and instructions for hosting your own instance in the
[`pezkuwi-js/apps`](https://github.com/polkadot-js/apps) repository.
### Takeaways
Development teyrchains:
- 🔗 Connect to relay chains, and we showcased how to connect to a local one.
- 🧹 Do not persist the state.
- 💰 Are preconfigured with a genesis state that includes several prefunded development accounts.
- 🧑‍⚖️ Development accounts are used as validators, collators, and `sudo` accounts.
## Runtime development
We recommend using [`chopsticks`](https://github.com/AcalaNetwork/chopsticks) when the focus is more on the runtime
development and `OmniNode` is enough as is.
### Install chopsticks
To use `chopsticks`, please install the latest version according to the installation [guide](https://github.com/AcalaNetwork/chopsticks?tab=readme-ov-file#install).
### Build a raw chain spec
Build the `teyrchain-template-runtime` as mentioned before in this guide and use `chain-spec-builder`
again but this time by passing `--raw-storage` flag:
```sh
chain-spec-builder create --raw-storage --relay-chain "pezkuwichain-local" --runtime \
target/release/wbuild/teyrchain-template-runtime/teyrchain_template_runtime.wasm named-preset development
```
### Start `chopsticks` with the chain spec
```sh
npx @acala-network/chopsticks@latest --chain-spec <path/to/chain_spec.json>
```
### Alternatives
`OmniNode` can be still used for runtime development if using the `--dev` flag, while `teyrchain-template-node` doesn't
support it at this moment. It can still be used to test a runtime in a full setup where it is started alongside a
relay chain network (see [Teyrchain Template node](#teyrchain-template-node) setup).
## Contributing
- 🔄 This template is automatically updated after releases in the main [Pezkuwi SDK monorepo](https://github.com/pezkuwichain/pezkuwi-sdk).
- ➡️ Any pull requests should be directed to this [source](https://github.com/pezkuwichain/pezkuwi-sdk/tree/master/templates/teyrchain).
- 😇 Please refer to the monorepo's
[contribution guidelines](https://github.com/pezkuwichain/pezkuwi-sdk/blob/master/docs/contributor/CONTRIBUTING.md) and
[Code of Conduct](https://github.com/pezkuwichain/pezkuwi-sdk/blob/master/docs/contributor/CODE_OF_CONDUCT.md).
## Getting Help
- 🧑‍🏫 To learn about Pezkuwi in general, [docs.Pezkuwi.com](https://docs.pezkuwichain.io/) website is a good starting point.
- 🧑‍🔧 For technical introduction, [here](https://github.com/pezkuwichain/pezkuwi-sdk#-documentation) are
the Pezkuwi SDK documentation resources.
- 👥 Additionally, there are [GitHub issues](https://github.com/pezkuwichain/pezkuwi-sdk/issues) and
[Substrate StackExchange](https://exchange.pezkuwichain.app/).
- 👥You can also reach out on the [Official Pezkuwi discord server](https://polkadot-discord.w3f.tools/)
- 🧑Reach out on [Telegram](https://t.me/substratedevs) for more questions and discussions
+270
View File
@@ -0,0 +1,270 @@
<div align="center">
# Pezkuwi SDK's Teyrchain Template
<img height="70px" alt="Pezkuwi SDK Logo" src="https://github.com/pezkuwichain/pezkuwi-sdk/raw/master/docs/images/Polkadot_Logo_Horizontal_Pink_White.png#gh-dark-mode-only"/>
<img height="70px" alt="Pezkuwi SDK Logo" src="https://github.com/pezkuwichain/pezkuwi-sdk/raw/master/docs/images/Polkadot_Logo_Horizontal_Pink_Black.png#gh-light-mode-only"/>
> This is a template for creating a [teyrchain](https://wiki.network.pezkuwichain.io/docs/learn-parachains) based on Pezkuwi SDK.
>
> This template is automatically updated after releases in the main [Pezkuwi SDK monorepo](https://github.com/pezkuwichain/pezkuwi-sdk).
</div>
## Table of Contents
- [Intro](#intro)
- [Template Structure](#template-structure)
- [Getting Started](#getting-started)
- [Starting a Development Chain](#starting-a-development-chain)
- [Omni Node](#omni-node-prerequisites)
- [Zombienet setup with Omni Node](#zombienet-setup-with-omni-node)
- [Teyrchain Template Node](#teyrchain-template-node)
- [Connect with the Pezkuwi-JS Apps Front-End](#connect-with-the-pezkuwi-js-apps-front-end)
- [Takeaways](#takeaways)
- [Runtime development](#runtime-development)
- [Contributing](#contributing)
- [Getting Help](#getting-help)
## Intro
- ⏫ This template provides a starting point to build a [teyrchain](https://wiki.network.pezkuwichain.io/docs/learn-parachains).
- ☁️ It is based on the
[Cumulus](https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/polkadot_sdk/cumulus/index.html) framework.
- 🔧 Its runtime is configured with a single custom pallet as a starting point, and a handful of ready-made pallets
such as a [Balances pallet](https://docs.pezkuwichain.io/sdk/master/pallet_balances/index.html).
- 👉 Learn more about teyrchains [here](https://wiki.network.pezkuwichain.io/docs/learn-parachains)
## Template Structure
A Pezkuwi SDK based project such as this one consists of:
- 🧮 the [Runtime](./runtime/README.md) - the core logic of the teyrchain.
- 🎨 the [Pallets](./pallets/README.md) - from which the runtime is constructed.
- 💿 a [Node](./node/README.md) - the binary application, not part of the project default-members list and not compiled unless
building the project with `--workspace` flag, which builds all workspace members, and is an alternative to
[Omni Node](https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/reference_docs/omni_node/index.html).
## Getting Started
- 🦀 The template is using the Rust language.
- 👉 Check the
[Rust installation instructions](https://www.rust-lang.org/tools/install) for your system.
- 🛠️ Depending on your operating system and Rust version, there might be additional
packages required to compile this template - please take note of the Rust compiler output.
Fetch teyrchain template code:
```sh
git clone https://github.com/pezkuwichain/pezkuwi-sdk-parachain-template.git teyrchain-template
cd teyrchain-template
```
## Starting a Development Chain
The teyrchain template relies on a hardcoded teyrchain id which is defined in the runtime code
and referenced throughout the contents of this file as `{{TEYRCHAIN_ID}}`. Please replace
any command or file referencing this placeholder with the value of the `TEYRCHAIN_ID` constant:
```rust,ignore
pub const TEYRCHAIN_ID: u32 = 1000;
```
### Omni Node Prerequisites
[Omni Node](https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/reference_docs/omni_node/index.html) can
be used to run the teyrchain template's runtime. `pezkuwi-omni-node` binary crate usage is described at a high-level
[on crates.io](https://crates.io/crates/polkadot-omni-node).
#### Install `pezkuwi-omni-node`
```sh
cargo install pezkuwi-omni-node
```
> For more advanced options, please see the installation section at [`crates.io/omni-node`](https://crates.io/crates/polkadot-omni-node).
#### Build `teyrchain-template-runtime`
```sh
cargo build --profile production
```
#### Install `staging-chain-spec-builder`
```sh
cargo install staging-chain-spec-builder
```
> For more advanced options, please see the installation section at [`crates.io/staging-chain-spec-builder`](https://crates.io/crates/staging-chain-spec-builder).
#### Use `chain-spec-builder` to generate the `chain_spec.json` file
```sh
chain-spec-builder create --relay-chain "pezkuwichain-local" --runtime \
target/release/wbuild/teyrchain-template-runtime/teyrchain_template_runtime.wasm named-preset development
```
**Note**: the `relay-chain` flag is required by Omni Node. The `relay-chain` value is set in accordance
with the relay chain ID where this instantiation of teyrchain-template will connect to.
#### Run Omni Node
Start Omni Node with the generated chain spec. We'll start it in development mode (without a relay chain config), producing
and finalizing blocks based on manual seal, configured below to seal a block with each second.
```bash
pezkuwi-omni-node --chain <path/to/chain_spec.json> --dev --dev-block-time 1000
```
However, such a setup is not close to what would run in production, and for that we need to setup a local
relay chain network that will help with the block finalization. In this guide we'll setup a local relay chain
as well. We'll not do it manually, by starting one node at a time, but we'll use [zombienet](https://paritytech.github.io/zombienet/intro.html).
Follow through the next section for more details on how to do it.
### Zombienet setup with Omni Node
Assuming we continue from the last step of the previous section, we have a chain spec and we need to setup a relay chain.
We can install `zombienet` as described [here](https://paritytech.github.io/zombienet/install.html#installation), and
`zombienet-omni-node.toml` contains the network specification we want to start.
#### Relay chain prerequisites
Download the `pezkuwi` (and the accompanying `pezkuwi-prepare-worker` and `pezkuwi-execute-worker`) binaries from
[Pezkuwi SDK releases](https://github.com/pezkuwichain/pezkuwi-sdk/releases). Then expose them on `PATH` like so:
```sh
export PATH="$PATH:<path/to/binaries>"
```
#### Update `zombienet-omni-node.toml` with a valid chain spec path
To simplify the process of using the teyrchain-template with zombienet and Omni Node, we've added a pre-configured
development chain spec (dev_chain_spec.json) to the teyrchain template. The zombienet-omni-node.toml file of this
template points to it, but you can update it to an updated chain spec generated on your machine. To generate a
chain spec refer to [staging-chain-spec-builder](https://crates.io/crates/staging-chain-spec-builder)
Then make the changes in the network specification like so:
```toml
# ...
[[teyrchains]]
id = "<TEYRCHAIN_ID>"
chain_spec_path = "<TO BE UPDATED WITH A VALID PATH>"
# ...
```
#### Start the network
```sh
zombienet --provider native spawn zombienet-omni-node.toml
```
### Teyrchain Template Node
As mentioned in the `Template Structure` section, the `node` crate is optionally compiled and it is an alternative
to `Omni Node`. Similarly, it requires setting up a relay chain, and we'll use `zombienet` once more.
#### Install the `teyrchain-template-node`
```sh
cargo install --path node --locked
```
#### Setup and start the network
For setup, please consider the instructions for `zombienet` installation [here](https://paritytech.github.io/zombienet/install.html#installation)
and [relay chain prerequisites](#relay-chain-prerequisites).
We're left just with starting the network:
```sh
zombienet --provider native spawn zombienet.toml
```
### Connect with the Pezkuwi-JS Apps Front-End
- 🌐 You can interact with your local node using the
hosted version of the Pezkuwi/Substrate Portal:
[relay chain](https://pezkuwichain.io/#/explorer?rpc=ws://localhost:9944)
and [teyrchain](https://pezkuwichain.io/#/explorer?rpc=ws://localhost:9988).
- 🪐 A hosted version is also
available on [IPFS](https://dotapps.io/).
- 🧑‍🔧 You can also find the source code and instructions for hosting your own instance in the
[`pezkuwi-js/apps`](https://github.com/polkadot-js/apps) repository.
### Takeaways
Development teyrchains:
- 🔗 Connect to relay chains, and we showcased how to connect to a local one.
- 🧹 Do not persist the state.
- 💰 Are preconfigured with a genesis state that includes several prefunded development accounts.
- 🧑‍⚖️ Development accounts are used as validators, collators, and `sudo` accounts.
## Runtime development
We recommend using [`chopsticks`](https://github.com/AcalaNetwork/chopsticks) when the focus is more on the runtime
development and `OmniNode` is enough as is.
### Install chopsticks
To use `chopsticks`, please install the latest version according to the installation [guide](https://github.com/AcalaNetwork/chopsticks?tab=readme-ov-file#install).
### Build a raw chain spec
Build the `teyrchain-template-runtime` as mentioned before in this guide and use `chain-spec-builder`
again but this time by passing `--raw-storage` flag:
```sh
chain-spec-builder create --raw-storage --relay-chain "pezkuwichain-local" --runtime \
target/release/wbuild/teyrchain-template-runtime/teyrchain_template_runtime.wasm named-preset development
```
### Start `chopsticks` with the chain spec
```sh
npx @acala-network/chopsticks@latest --chain-spec <path/to/chain_spec.json>
```
### Alternatives
`OmniNode` can be still used for runtime development if using the `--dev` flag, while `teyrchain-template-node` doesn't
support it at this moment. It can still be used to test a runtime in a full setup where it is started alongside a
relay chain network (see [Teyrchain Template node](#teyrchain-template-node) setup).
## Contributing
- 🔄 This template is automatically updated after releases in the main [Pezkuwi SDK monorepo](https://github.com/pezkuwichain/pezkuwi-sdk).
- ➡️ Any pull requests should be directed to this [source](https://github.com/pezkuwichain/pezkuwi-sdk/tree/master/templates/teyrchain).
- 😇 Please refer to the monorepo's
[contribution guidelines](https://github.com/pezkuwichain/pezkuwi-sdk/blob/master/docs/contributor/CONTRIBUTING.md) and
[Code of Conduct](https://github.com/pezkuwichain/pezkuwi-sdk/blob/master/docs/contributor/CODE_OF_CONDUCT.md).
## Getting Help
- 🧑‍🏫 To learn about Pezkuwi in general, [docs.Pezkuwi.com](https://docs.pezkuwichain.io/) website is a good starting point.
- 🧑‍🔧 For technical introduction, [here](https://github.com/pezkuwichain/pezkuwi-sdk#-documentation) are
the Pezkuwi SDK documentation resources.
- 👥 Additionally, there are [GitHub issues](https://github.com/pezkuwichain/pezkuwi-sdk/issues) and
[Substrate StackExchange](https://exchange.pezkuwichain.app/).
- 👥You can also reach out on the [Official Pezkuwi discord server](https://polkadot-discord.w3f.tools/)
- 🧑Reach out on [Telegram](https://t.me/substratedevs) for more questions and discussions
+107
View File
File diff suppressed because one or more lines are too long
+46
View File
@@ -0,0 +1,46 @@
[package]
name = "teyrchain-template-node"
description = "A teyrchain node template built with Substrate and Cumulus, part of Pezkuwi Sdk."
version = "0.0.0"
license = "Unlicense"
authors.workspace = true
homepage.workspace = true
repository.workspace = true
edition.workspace = true
publish = false
build = "build.rs"
[lints]
workspace = true
[dependencies]
clap = { features = ["derive"], workspace = true }
codec = { workspace = true, default-features = true }
color-print = { workspace = true }
docify = { workspace = true }
futures = { workspace = true }
jsonrpsee = { features = ["server"], workspace = true }
log = { workspace = true, default-features = true }
serde = { features = ["derive"], workspace = true, default-features = true }
pezkuwi-sdk = { workspace = true, features = ["node", "pezkuwi-primitives"] }
teyrchain-template-runtime = { workspace = true }
# Substrate
prometheus-endpoint = { workspace = true, default-features = true }
[build-dependencies]
pezkuwi-sdk = { workspace = true, features = ["substrate-build-script-utils"] }
[features]
default = ["std"]
std = ["log/std", "pezkuwi-sdk/std", "teyrchain-template-runtime/std"]
runtime-benchmarks = [
"pezkuwi-sdk/runtime-benchmarks",
"teyrchain-template-runtime/runtime-benchmarks",
]
try-runtime = [
"pezkuwi-sdk/try-runtime",
"teyrchain-template-runtime/try-runtime",
]
+18
View File
@@ -0,0 +1,18 @@
# Node
️ A node - in PezkuwiChain - is a binary executable, whose primary purpose is to execute the [runtime](../runtime/README.md).
🔗 It communicates with other nodes in the network, and aims for
[consensus](https://wiki.network.pezkuwichain.io/docs/learn-consensus) among them.
⚙️ It acts as a remote procedure call (RPC) server, allowing interaction with the blockchain.
👉 Learn more about the architecture, and the difference between a node and a runtime
[here](https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/reference_docs/wasm_meta_protocol/index.html).
👇 Here are the most important files in this node template:
- [`chain_spec.rs`](./src/chain_spec.rs): A chain specification is a source code file that defines the chain's
initial (genesis) state.
- [`service.rs`](./src/service.rs): This file defines the node implementation.
It's a place to configure consensus-related topics.
+7
View File
@@ -0,0 +1,7 @@
use pezkuwi_sdk::substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed};
fn main() {
generate_cargo_keys();
rerun_if_git_head_changed();
}
+65
View File
@@ -0,0 +1,65 @@
use pezkuwi_sdk::*;
use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};
use sc_service::ChainType;
use serde::{Deserialize, Serialize};
use teyrchain_template_runtime as runtime;
/// Specialized `ChainSpec` for the normal teyrchain runtime.
pub type ChainSpec = sc_service::GenericChainSpec<Extensions>;
/// The relay chain that you want to configure this teyrchain to connect to.
pub const RELAY_CHAIN: &str = "pezkuwichain-local";
/// The extensions for the [`ChainSpec`].
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)]
pub struct Extensions {
/// The relay chain of the Teyrchain.
#[serde(alias = "relayChain", alias = "RelayChain")]
pub relay_chain: String,
}
impl Extensions {
/// Try to get the extension from the given `ChainSpec`.
pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> {
sc_chain_spec::get_extension(chain_spec.extensions())
}
}
pub fn development_chain_spec() -> ChainSpec {
// Give your base currency a unit name and decimal places
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "UNIT".into());
properties.insert("tokenDecimals".into(), 12.into());
properties.insert("ss58Format".into(), 42.into());
ChainSpec::builder(
runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"),
Extensions { relay_chain: RELAY_CHAIN.into() },
)
.with_name("Development")
.with_id("dev")
.with_chain_type(ChainType::Development)
.with_genesis_config_preset_name(sp_genesis_builder::DEV_RUNTIME_PRESET)
.with_properties(properties)
.build()
}
pub fn local_chain_spec() -> ChainSpec {
// Give your base currency a unit name and decimal places
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "UNIT".into());
properties.insert("tokenDecimals".into(), 12.into());
properties.insert("ss58Format".into(), 42.into());
ChainSpec::builder(
runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"),
Extensions { relay_chain: RELAY_CHAIN.into() },
)
.with_name("Local Testnet")
.with_id("local_testnet")
.with_chain_type(ChainType::Local)
.with_genesis_config_preset_name(sc_chain_spec::LOCAL_TESTNET_RUNTIME_PRESET)
.with_protocol_id("template-local")
.with_properties(properties)
.build()
}
+120
View File
@@ -0,0 +1,120 @@
use pezkuwi_sdk::*;
use std::path::PathBuf;
/// Sub-commands supported by the collator.
#[allow(clippy::large_enum_variant)]
#[derive(Debug, clap::Subcommand)]
pub enum Subcommand {
/// Build a chain specification.
/// DEPRECATED: `build-spec` command will be removed after 1/04/2026. Use `export-chain-spec`
/// command instead.
#[deprecated(
note = "build-spec command will be removed after 1/04/2026. Use export-chain-spec command instead"
)]
BuildSpec(sc_cli::BuildSpecCmd),
/// Export the chain specification.
ExportChainSpec(sc_cli::ExportChainSpecCmd),
/// Validate blocks.
CheckBlock(sc_cli::CheckBlockCmd),
/// Export blocks.
ExportBlocks(sc_cli::ExportBlocksCmd),
/// Export the state of a given block into a chain spec.
ExportState(sc_cli::ExportStateCmd),
/// Import blocks.
ImportBlocks(sc_cli::ImportBlocksCmd),
/// Revert the chain to a previous state.
Revert(sc_cli::RevertCmd),
/// Remove the whole chain.
PurgeChain(cumulus_client_cli::PurgeChainCmd),
/// Export the genesis head data of the teyrchain.
///
/// Head data is the encoded block header.
#[command(alias = "export-genesis-state")]
ExportGenesisHead(cumulus_client_cli::ExportGenesisHeadCommand),
/// Export the genesis wasm of the teyrchain.
ExportGenesisWasm(cumulus_client_cli::ExportGenesisWasmCommand),
/// Sub-commands concerned with benchmarking.
/// The pallet benchmarking moved to the `pallet` sub-command.
#[command(subcommand)]
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
}
const AFTER_HELP_EXAMPLE: &str = color_print::cstr!(
r#"<bold><underline>Examples:</></>
<bold>teyrchain-template-node build-spec --disable-default-bootnode > plain-teyrchain-chainspec.json</>
Export a chainspec for a local testnet in json format.
<bold>teyrchain-template-node --chain plain-teyrchain-chainspec.json --tmp -- --chain pezkuwichain-local</>
Launch a full node with chain specification loaded from plain-teyrchain-chainspec.json.
<bold>teyrchain-template-node</>
Launch a full node with default teyrchain <italic>local-testnet</> and relay chain <italic>pezkuwichain-local</>.
<bold>teyrchain-template-node --collator</>
Launch a collator with default teyrchain <italic>local-testnet</> and relay chain <italic>pezkuwichain-local</>.
"#
);
#[derive(Debug, clap::Parser)]
#[command(
propagate_version = true,
args_conflicts_with_subcommands = true,
subcommand_negates_reqs = true
)]
#[clap(after_help = AFTER_HELP_EXAMPLE)]
pub struct Cli {
#[command(subcommand)]
pub subcommand: Option<Subcommand>,
#[command(flatten)]
pub run: cumulus_client_cli::RunCmd,
/// Disable automatic hardware benchmarks.
///
/// By default these benchmarks are automatically ran at startup and measure
/// the CPU speed, the memory bandwidth and the disk speed.
///
/// The results are then printed out in the logs, and also sent as part of
/// telemetry, if telemetry is enabled.
#[arg(long)]
pub no_hardware_benchmarks: bool,
/// Relay chain arguments
#[arg(raw = true)]
pub relay_chain_args: Vec<String>,
}
#[derive(Debug)]
pub struct RelayChainCli {
/// The actual relay chain cli object.
pub base: pezkuwi_cli::RunCmd,
/// Optional chain id that should be passed to the relay chain.
pub chain_id: Option<String>,
/// The base path that should be used by the relay chain.
pub base_path: Option<PathBuf>,
}
impl RelayChainCli {
/// Parse the relay chain CLI parameters using the para chain `Configuration`.
pub fn new<'a>(
para_config: &sc_service::Configuration,
relay_chain_args: impl Iterator<Item = &'a String>,
) -> Self {
let extension = crate::chain_spec::Extensions::try_get(&*para_config.chain_spec);
let chain_id = extension.map(|e| e.relay_chain.clone());
let base_path = para_config.base_path.path().join("pezkuwi");
Self {
base_path: Some(base_path),
chain_id,
base: clap::Parser::parse_from(relay_chain_args),
}
}
}
+385
View File
@@ -0,0 +1,385 @@
use pezkuwi_sdk::*;
use cumulus_client_service::storage_proof_size::HostFunctions as ReclaimHostFunctions;
use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE};
use log::info;
use sc_cli::{
ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams,
NetworkParams, Result, RpcEndpoint, SharedParams, SubstrateCli,
};
use sc_service::config::{BasePath, PrometheusConfig};
use teyrchain_template_runtime::Block;
use crate::{
chain_spec,
cli::{Cli, RelayChainCli, Subcommand},
service::new_partial,
};
fn load_spec(id: &str) -> std::result::Result<Box<dyn ChainSpec>, String> {
Ok(match id {
"dev" => Box::new(chain_spec::development_chain_spec()),
"template-pezkuwichain" => Box::new(chain_spec::local_chain_spec()),
"" | "local" => Box::new(chain_spec::local_chain_spec()),
path => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?),
})
}
impl SubstrateCli for Cli {
fn impl_name() -> String {
"Teyrchain Collator Template".into()
}
fn impl_version() -> String {
env!("SUBSTRATE_CLI_IMPL_VERSION").into()
}
fn description() -> String {
format!(
"Teyrchain Collator Template\n\nThe command-line arguments provided first will be \
passed to the teyrchain node, while the arguments provided after -- will be passed \
to the relay chain node.\n\n\
{} <teyrchain-args> -- <relay-chain-args>",
Self::executable_name()
)
}
fn author() -> String {
env!("CARGO_PKG_AUTHORS").into()
}
fn support_url() -> String {
"https://github.com/pezkuwichain/pezkuwi-sdk/issues/new".into()
}
fn copyright_start_year() -> i32 {
2020
}
fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
load_spec(id)
}
}
impl SubstrateCli for RelayChainCli {
fn impl_name() -> String {
"Teyrchain Collator Template".into()
}
fn impl_version() -> String {
env!("SUBSTRATE_CLI_IMPL_VERSION").into()
}
fn description() -> String {
format!(
"Teyrchain Collator Template\n\nThe command-line arguments provided first will be \
passed to the teyrchain node, while the arguments provided after -- will be passed \
to the relay chain node.\n\n\
{} <teyrchain-args> -- <relay-chain-args>",
Self::executable_name()
)
}
fn author() -> String {
env!("CARGO_PKG_AUTHORS").into()
}
fn support_url() -> String {
"https://github.com/pezkuwichain/pezkuwi-sdk/issues/new".into()
}
fn copyright_start_year() -> i32 {
2020
}
fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
pezkuwi_cli::Cli::from_iter([RelayChainCli::executable_name()].iter()).load_spec(id)
}
}
macro_rules! construct_async_run {
(|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{
let runner = $cli.create_runner($cmd)?;
runner.async_run(|$config| {
let $components = new_partial(&$config)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
}}
}
/// Parse command line arguments into service configuration.
pub fn run() -> Result<()> {
let cli = Cli::from_args();
match &cli.subcommand {
#[allow(deprecated)]
Some(Subcommand::BuildSpec(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
},
Some(Subcommand::CheckBlock(cmd)) => {
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, components.import_queue))
})
},
Some(Subcommand::ExportChainSpec(cmd)) => {
let chain_spec = cli.load_spec(&cmd.chain)?;
cmd.run(chain_spec)
},
Some(Subcommand::ExportBlocks(cmd)) => {
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, config.database))
})
},
Some(Subcommand::ExportState(cmd)) => {
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, config.chain_spec))
})
},
Some(Subcommand::ImportBlocks(cmd)) => {
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, components.import_queue))
})
},
Some(Subcommand::Revert(cmd)) => {
construct_async_run!(|components, cli, cmd, config| {
Ok(cmd.run(components.client, components.backend, None))
})
},
Some(Subcommand::PurgeChain(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| {
let pezkuwi_cli = RelayChainCli::new(
&config,
[RelayChainCli::executable_name()].iter().chain(cli.relay_chain_args.iter()),
);
let pezkuwi_config = SubstrateCli::create_configuration(
&pezkuwi_cli,
&pezkuwi_cli,
config.tokio_handle.clone(),
)
.map_err(|err| format!("Relay chain argument error: {err}"))?;
cmd.run(config, pezkuwi_config)
})
},
Some(Subcommand::ExportGenesisHead(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| {
let partials = new_partial(&config)?;
cmd.run(partials.client)
})
},
Some(Subcommand::ExportGenesisWasm(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|_config| {
let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?;
cmd.run(&*spec)
})
},
Some(Subcommand::Benchmark(cmd)) => {
let runner = cli.create_runner(cmd)?;
// Switch on the concrete benchmark sub-command-
match cmd {
BenchmarkCmd::Pallet(cmd) => {
if cfg!(feature = "runtime-benchmarks") {
runner.sync_run(|config| cmd.run_with_spec::<sp_runtime::traits::HashingFor<Block>, ReclaimHostFunctions>(Some(config.chain_spec)))
} else {
Err("Benchmarking wasn't enabled when building the node. \
You can enable it with `--features runtime-benchmarks`."
.into())
}
},
BenchmarkCmd::Block(cmd) => runner.sync_run(|config| {
let partials = new_partial(&config)?;
cmd.run(partials.client)
}),
#[cfg(not(feature = "runtime-benchmarks"))]
BenchmarkCmd::Storage(_) => Err(sc_cli::Error::Input(
"Compile with --features=runtime-benchmarks \
to enable storage benchmarks."
.into(),
)),
#[cfg(feature = "runtime-benchmarks")]
BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| {
let partials = new_partial(&config)?;
let db = partials.backend.expose_db();
let storage = partials.backend.expose_storage();
let shared_cache = partials.backend.expose_shared_trie_cache();
cmd.run(config, partials.client.clone(), db, storage, shared_cache)
}),
BenchmarkCmd::Machine(cmd) => {
runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()))
},
// NOTE: this allows the Client to leniently implement
// new benchmark commands without requiring a companion MR.
#[allow(unreachable_patterns)]
_ => Err("Benchmarking sub-command unsupported".into()),
}
},
None => {
let runner = cli.create_runner(&cli.run.normalize())?;
let collator_options = cli.run.collator_options();
runner.run_node_until_exit(|config| async move {
let hwbench = (!cli.no_hardware_benchmarks)
.then(|| {
config.database.path().map(|database_path| {
let _ = std::fs::create_dir_all(database_path);
sc_sysinfo::gather_hwbench(
Some(database_path),
&SUBSTRATE_REFERENCE_HARDWARE,
)
})
})
.flatten();
let pezkuwi_cli = RelayChainCli::new(
&config,
[RelayChainCli::executable_name()].iter().chain(cli.relay_chain_args.iter()),
);
let tokio_handle = config.tokio_handle.clone();
let pezkuwi_config =
SubstrateCli::create_configuration(&pezkuwi_cli, &pezkuwi_cli, tokio_handle)
.map_err(|err| format!("Relay chain argument error: {err}"))?;
info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" });
crate::service::start_teyrchain_node(
config,
pezkuwi_config,
collator_options,
hwbench,
)
.await
.map(|r| r.0)
.map_err(Into::into)
})
},
}
}
impl DefaultConfigurationValues for RelayChainCli {
fn p2p_listen_port() -> u16 {
30334
}
fn rpc_listen_port() -> u16 {
9945
}
fn prometheus_listen_port() -> u16 {
9616
}
}
impl CliConfiguration<Self> for RelayChainCli {
fn shared_params(&self) -> &SharedParams {
self.base.base.shared_params()
}
fn import_params(&self) -> Option<&ImportParams> {
self.base.base.import_params()
}
fn network_params(&self) -> Option<&NetworkParams> {
self.base.base.network_params()
}
fn keystore_params(&self) -> Option<&KeystoreParams> {
self.base.base.keystore_params()
}
fn base_path(&self) -> Result<Option<BasePath>> {
Ok(self
.shared_params()
.base_path()?
.or_else(|| self.base_path.clone().map(Into::into)))
}
fn rpc_addr(&self, default_listen_port: u16) -> Result<Option<Vec<RpcEndpoint>>> {
self.base.base.rpc_addr(default_listen_port)
}
fn prometheus_config(
&self,
default_listen_port: u16,
chain_spec: &Box<dyn ChainSpec>,
) -> Result<Option<PrometheusConfig>> {
self.base.base.prometheus_config(default_listen_port, chain_spec)
}
fn init<F>(&self, _support_url: &String, _impl_version: &String, _logger_hook: F) -> Result<()>
where
F: FnOnce(&mut sc_cli::LoggerBuilder),
{
unreachable!("PezkuwiCli is never initialized; qed");
}
fn chain_id(&self, is_dev: bool) -> Result<String> {
let chain_id = self.base.base.chain_id(is_dev)?;
Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id })
}
fn role(&self, is_dev: bool) -> Result<sc_service::Role> {
self.base.base.role(is_dev)
}
fn transaction_pool(&self, is_dev: bool) -> Result<sc_service::config::TransactionPoolOptions> {
self.base.base.transaction_pool(is_dev)
}
fn trie_cache_maximum_size(&self) -> Result<Option<usize>> {
self.base.base.trie_cache_maximum_size()
}
fn rpc_methods(&self) -> Result<sc_service::config::RpcMethods> {
self.base.base.rpc_methods()
}
fn rpc_max_connections(&self) -> Result<u32> {
self.base.base.rpc_max_connections()
}
fn rpc_cors(&self, is_dev: bool) -> Result<Option<Vec<String>>> {
self.base.base.rpc_cors(is_dev)
}
fn default_heap_pages(&self) -> Result<Option<u64>> {
self.base.base.default_heap_pages()
}
fn force_authoring(&self) -> Result<bool> {
self.base.base.force_authoring()
}
fn disable_grandpa(&self) -> Result<bool> {
self.base.base.disable_grandpa()
}
fn max_runtime_instances(&self) -> Result<Option<usize>> {
self.base.base.max_runtime_instances()
}
fn announce_block(&self) -> Result<bool> {
self.base.base.announce_block()
}
fn telemetry_endpoints(
&self,
chain_spec: &Box<dyn ChainSpec>,
) -> Result<Option<sc_telemetry::TelemetryEndpoints>> {
self.base.base.telemetry_endpoints(chain_spec)
}
fn node_name(&self) -> Result<String> {
self.base.base.node_name()
}
}
+15
View File
@@ -0,0 +1,15 @@
//! Substrate Teyrchain Node Template CLI
#![warn(missing_docs)]
use pezkuwi_sdk::*;
mod chain_spec;
mod cli;
mod command;
mod rpc;
mod service;
fn main() -> sc_cli::Result<()> {
command::run()
}
+55
View File
@@ -0,0 +1,55 @@
//! A collection of node-specific RPC methods.
//! Substrate provides the `sc-rpc` crate, which defines the core RPC layer
//! used by Substrate nodes. This file extends those RPC definitions with
//! capabilities that are specific to this project's runtime configuration.
#![warn(missing_docs)]
use std::sync::Arc;
use teyrchain_template_runtime::{opaque::Block, AccountId, Balance, Nonce};
use pezkuwi_sdk::*;
use sc_transaction_pool_api::TransactionPool;
use sp_api::ProvideRuntimeApi;
use sp_block_builder::BlockBuilder;
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
/// A type representing all RPC extensions.
pub type RpcExtension = jsonrpsee::RpcModule<()>;
/// Full client dependencies
pub struct FullDeps<C, P> {
/// The client instance to use.
pub client: Arc<C>,
/// Transaction pool instance.
pub pool: Arc<P>,
}
/// Instantiate all RPC extensions.
pub fn create_full<C, P>(
deps: FullDeps<C, P>,
) -> Result<RpcExtension, Box<dyn std::error::Error + Send + Sync>>
where
C: ProvideRuntimeApi<Block>
+ HeaderBackend<Block>
+ HeaderMetadata<Block, Error = BlockChainError>
+ Send
+ Sync
+ 'static,
C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
C::Api: BlockBuilder<Block>,
P: TransactionPool + Sync + Send + 'static,
{
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer};
use substrate_frame_rpc_system::{System, SystemApiServer};
let mut module = RpcExtension::new(());
let FullDeps { client, pool } = deps;
module.merge(System::new(client.clone(), pool).into_rpc())?;
module.merge(TransactionPayment::new(client).into_rpc())?;
Ok(module)
}
+448
View File
@@ -0,0 +1,448 @@
//! Service and ServiceFactory implementation. Specialized wrapper over substrate service.
// std
use std::{sync::Arc, time::Duration};
// Local Runtime Types
use teyrchain_template_runtime::{
apis::RuntimeApi,
opaque::{Block, Hash},
};
use codec::Encode;
use pezkuwi_sdk::{cumulus_client_service::TeyrchainTracingExecuteBlock, *};
// Cumulus Imports
use cumulus_client_bootnodes::{start_bootnode_tasks, StartBootnodeTasksParams};
use cumulus_client_cli::CollatorOptions;
use cumulus_client_collator::service::CollatorService;
#[docify::export(lookahead_collator)]
use cumulus_client_consensus_aura::collators::lookahead::{self as aura, Params as AuraParams};
use cumulus_client_consensus_common::TeyrchainBlockImport as TTeyrchainBlockImport;
use cumulus_client_service::{
build_network, build_relay_chain_interface, prepare_node_config, start_relay_chain_tasks,
BuildNetworkParams, CollatorSybilResistance, DARecoveryProfile, StartRelayChainTasksParams,
TeyrchainHostFunctions,
};
#[docify::export(cumulus_primitives)]
use cumulus_primitives_core::{
relay_chain::{CollatorPair, ValidationCode},
GetTeyrchainInfo, ParaId,
};
use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface};
// Substrate Imports
use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE;
use pezkuwi_sdk::sc_network::PeerId;
use prometheus_endpoint::Registry;
use sc_client_api::Backend;
use sc_consensus::ImportQueue;
use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY};
use sc_network::{NetworkBackend, NetworkBlock};
use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager};
use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};
use sc_transaction_pool_api::OffchainTransactionPoolFactory;
use sp_api::ProvideRuntimeApi;
use sp_keystore::KeystorePtr;
#[docify::export(wasm_executor)]
type TeyrchainExecutor = WasmExecutor<TeyrchainHostFunctions>;
type TeyrchainClient = TFullClient<Block, RuntimeApi, TeyrchainExecutor>;
type TeyrchainBackend = TFullBackend<Block>;
type TeyrchainBlockImport = TTeyrchainBlockImport<Block, Arc<TeyrchainClient>, TeyrchainBackend>;
/// Assembly of PartialComponents (enough to run chain ops subcommands)
pub type Service = PartialComponents<
TeyrchainClient,
TeyrchainBackend,
(),
sc_consensus::DefaultImportQueue<Block>,
sc_transaction_pool::TransactionPoolHandle<Block, TeyrchainClient>,
(TeyrchainBlockImport, Option<Telemetry>, Option<TelemetryWorkerHandle>),
>;
/// Starts a `ServiceBuilder` for a full service.
///
/// Use this macro if you don't actually need the full service, but just the builder in order to
/// be able to perform chain operations.
#[docify::export(component_instantiation)]
pub fn new_partial(config: &Configuration) -> Result<Service, sc_service::Error> {
let telemetry = config
.telemetry_endpoints
.clone()
.filter(|x| !x.is_empty())
.map(|endpoints| -> Result<_, sc_telemetry::Error> {
let worker = TelemetryWorker::new(16)?;
let telemetry = worker.handle().new_telemetry(endpoints);
Ok((worker, telemetry))
})
.transpose()?;
let heap_pages = config
.executor
.default_heap_pages
.map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ });
let executor = TeyrchainExecutor::builder()
.with_execution_method(config.executor.wasm_method)
.with_onchain_heap_alloc_strategy(heap_pages)
.with_offchain_heap_alloc_strategy(heap_pages)
.with_max_runtime_instances(config.executor.max_runtime_instances)
.with_runtime_cache_size(config.executor.runtime_cache_size)
.build();
let (client, backend, keystore_container, task_manager) =
sc_service::new_full_parts_record_import::<Block, RuntimeApi, _>(
config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
executor,
true,
)?;
let client = Arc::new(client);
let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());
let telemetry = telemetry.map(|(worker, telemetry)| {
task_manager.spawn_handle().spawn("telemetry", None, worker.run());
telemetry
});
let transaction_pool = Arc::from(
sc_transaction_pool::Builder::new(
task_manager.spawn_essential_handle(),
client.clone(),
config.role.is_authority().into(),
)
.with_options(config.transaction_pool.clone())
.with_prometheus(config.prometheus_registry())
.build(),
);
let block_import = TeyrchainBlockImport::new(client.clone(), backend.clone());
let import_queue = build_import_queue(
client.clone(),
block_import.clone(),
config,
telemetry.as_ref().map(|telemetry| telemetry.handle()),
&task_manager,
);
Ok(PartialComponents {
backend,
client,
import_queue,
keystore_container,
task_manager,
transaction_pool,
select_chain: (),
other: (block_import, telemetry, telemetry_worker_handle),
})
}
/// Build the import queue for the teyrchain runtime.
fn build_import_queue(
client: Arc<TeyrchainClient>,
block_import: TeyrchainBlockImport,
config: &Configuration,
telemetry: Option<TelemetryHandle>,
task_manager: &TaskManager,
) -> sc_consensus::DefaultImportQueue<Block> {
cumulus_client_consensus_aura::equivocation_import_queue::fully_verifying_import_queue::<
sp_consensus_aura::sr25519::AuthorityPair,
_,
_,
_,
_,
>(
client,
block_import,
move |_, _| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
Ok(timestamp)
},
&task_manager.spawn_essential_handle(),
config.prometheus_registry(),
telemetry,
)
}
#[allow(clippy::too_many_arguments)]
fn start_consensus(
client: Arc<TeyrchainClient>,
backend: Arc<TeyrchainBackend>,
block_import: TeyrchainBlockImport,
prometheus_registry: Option<&Registry>,
telemetry: Option<TelemetryHandle>,
task_manager: &TaskManager,
relay_chain_interface: Arc<dyn RelayChainInterface>,
transaction_pool: Arc<sc_transaction_pool::TransactionPoolHandle<Block, TeyrchainClient>>,
keystore: KeystorePtr,
relay_chain_slot_duration: Duration,
para_id: ParaId,
collator_key: CollatorPair,
collator_peer_id: PeerId,
overseer_handle: OverseerHandle,
announce_block: Arc<dyn Fn(Hash, Option<Vec<u8>>) + Send + Sync>,
) -> Result<(), sc_service::Error> {
let proposer = sc_basic_authorship::ProposerFactory::with_proof_recording(
task_manager.spawn_handle(),
client.clone(),
transaction_pool,
prometheus_registry,
telemetry.clone(),
);
let collator_service = CollatorService::new(
client.clone(),
Arc::new(task_manager.spawn_handle()),
announce_block,
client.clone(),
);
let params = AuraParams {
create_inherent_data_providers: move |_, ()| async move { Ok(()) },
block_import,
para_client: client.clone(),
para_backend: backend,
relay_client: relay_chain_interface,
code_hash_provider: move |block_hash| {
client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash())
},
keystore,
collator_key,
collator_peer_id,
para_id,
overseer_handle,
relay_chain_slot_duration,
proposer,
collator_service,
authoring_duration: Duration::from_millis(2000),
reinitialize: false,
max_pov_percentage: None,
};
let fut = aura::run::<Block, sp_consensus_aura::sr25519::AuthorityPair, _, _, _, _, _, _, _, _>(
params,
);
task_manager.spawn_essential_handle().spawn("aura", None, fut);
Ok(())
}
/// Start a node with the given teyrchain `Configuration` and relay chain `Configuration`.
#[sc_tracing::logging::prefix_logs_with("Teyrchain")]
pub async fn start_teyrchain_node(
teyrchain_config: Configuration,
pezkuwi_config: Configuration,
collator_options: CollatorOptions,
hwbench: Option<sc_sysinfo::HwBench>,
) -> sc_service::error::Result<(TaskManager, Arc<TeyrchainClient>)> {
let teyrchain_config = prepare_node_config(teyrchain_config);
let params = new_partial(&teyrchain_config)?;
let (block_import, mut telemetry, telemetry_worker_handle) = params.other;
let prometheus_registry = teyrchain_config.prometheus_registry().cloned();
let net_config = sc_network::config::FullNetworkConfiguration::<
_,
_,
sc_network::NetworkWorker<Block, Hash>,
>::new(&teyrchain_config.network, prometheus_registry.clone());
let client = params.client.clone();
let backend = params.backend.clone();
let mut task_manager = params.task_manager;
let relay_chain_fork_id = pezkuwi_config.chain_spec.fork_id().map(ToString::to_string);
let teyrchain_fork_id = teyrchain_config.chain_spec.fork_id().map(ToString::to_string);
let advertise_non_global_ips = teyrchain_config.network.allow_non_globals_in_dht;
let teyrchain_public_addresses = teyrchain_config.network.public_addresses.clone();
let (relay_chain_interface, collator_key, relay_chain_network, paranode_rx) =
build_relay_chain_interface(
pezkuwi_config,
&teyrchain_config,
telemetry_worker_handle,
&mut task_manager,
collator_options.clone(),
hwbench.clone(),
)
.await
.map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?;
let validator = teyrchain_config.role.is_authority();
let transaction_pool = params.transaction_pool.clone();
let import_queue_service = params.import_queue.service();
// Take teyrchain id from runtime.
let best_hash = client.chain_info().best_hash;
let para_id = client
.runtime_api()
.teyrchain_id(best_hash)
.map_err(|_| "Failed to retrieve teyrchain id from runtime. Make sure you implement `cumulus_primitives_core::GetParachaiNidentity` runtime API.")?;
// NOTE: because we use Aura here explicitly, we can use `CollatorSybilResistance::Resistant`
// when starting the network.
let (network, system_rpc_tx, tx_handler_controller, sync_service) =
build_network(BuildNetworkParams {
teyrchain_config: &teyrchain_config,
net_config,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
para_id,
spawn_handle: task_manager.spawn_handle(),
relay_chain_interface: relay_chain_interface.clone(),
import_queue: params.import_queue,
sybil_resistance_level: CollatorSybilResistance::Resistant, // because of Aura
metrics: sc_network::NetworkWorker::<Block, Hash>::register_notification_metrics(
teyrchain_config.prometheus_config.as_ref().map(|config| &config.registry),
),
})
.await?;
let collator_peer_id = network.local_peer_id();
if teyrchain_config.offchain_worker.enabled {
use futures::FutureExt;
let offchain_workers =
sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions {
runtime_api_provider: client.clone(),
keystore: Some(params.keystore_container.keystore()),
offchain_db: backend.offchain_storage(),
transaction_pool: Some(OffchainTransactionPoolFactory::new(
transaction_pool.clone(),
)),
network_provider: Arc::new(network.clone()),
is_validator: teyrchain_config.role.is_authority(),
enable_http_requests: false,
custom_extensions: move |_| vec![],
})?;
task_manager.spawn_handle().spawn(
"offchain-workers-runner",
"offchain-work",
offchain_workers.run(client.clone(), task_manager.spawn_handle()).boxed(),
);
}
let rpc_builder = {
let client = client.clone();
let transaction_pool = transaction_pool.clone();
Box::new(move |_| {
let deps =
crate::rpc::FullDeps { client: client.clone(), pool: transaction_pool.clone() };
crate::rpc::create_full(deps).map_err(Into::into)
})
};
sc_service::spawn_tasks(sc_service::SpawnTasksParams {
rpc_builder,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
task_manager: &mut task_manager,
config: teyrchain_config,
keystore: params.keystore_container.keystore(),
backend: backend.clone(),
network: network.clone(),
sync_service: sync_service.clone(),
system_rpc_tx,
tx_handler_controller,
telemetry: telemetry.as_mut(),
tracing_execute_block: Some(Arc::new(TeyrchainTracingExecuteBlock::new(client.clone()))),
})?;
if let Some(hwbench) = hwbench {
sc_sysinfo::print_hwbench(&hwbench);
// Here you can check whether the hardware meets your chains' requirements. Putting a link
// in there and swapping out the requirements for your own are probably a good idea. The
// requirements for a para-chain are dictated by its relay-chain.
match SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench, false) {
Err(err) if validator => {
log::warn!(
"⚠️ The hardware does not meet the minimal requirements {} for role 'Authority'.",
err
);
},
_ => {},
}
if let Some(ref mut telemetry) = telemetry {
let telemetry_handle = telemetry.handle();
task_manager.spawn_handle().spawn(
"telemetry_hwbench",
None,
sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench),
);
}
}
let announce_block = {
let sync_service = sync_service.clone();
Arc::new(move |hash, data| sync_service.announce_block(hash, data))
};
let relay_chain_slot_duration = Duration::from_secs(6);
let overseer_handle = relay_chain_interface
.overseer_handle()
.map_err(|e| sc_service::Error::Application(Box::new(e)))?;
start_relay_chain_tasks(StartRelayChainTasksParams {
client: client.clone(),
announce_block: announce_block.clone(),
para_id,
relay_chain_interface: relay_chain_interface.clone(),
task_manager: &mut task_manager,
da_recovery_profile: if validator {
DARecoveryProfile::Collator
} else {
DARecoveryProfile::FullNode
},
import_queue: import_queue_service,
relay_chain_slot_duration,
recovery_handle: Box::new(overseer_handle.clone()),
sync_service: sync_service.clone(),
prometheus_registry: prometheus_registry.as_ref(),
})?;
start_bootnode_tasks(StartBootnodeTasksParams {
embedded_dht_bootnode: collator_options.embedded_dht_bootnode,
dht_bootnode_discovery: collator_options.dht_bootnode_discovery,
para_id,
task_manager: &mut task_manager,
relay_chain_interface: relay_chain_interface.clone(),
relay_chain_fork_id,
relay_chain_network,
request_receiver: paranode_rx,
teyrchain_network: network,
advertise_non_global_ips,
teyrchain_genesis_hash: client.chain_info().genesis_hash.encode(),
teyrchain_fork_id,
teyrchain_public_addresses,
});
if validator {
start_consensus(
client.clone(),
backend,
block_import,
prometheus_registry.as_ref(),
telemetry.as_ref().map(|t| t.handle()),
&task_manager,
relay_chain_interface,
transaction_pool,
params.keystore_container.keystore(),
relay_chain_slot_duration,
para_id,
collator_key.expect("Command line arguments do not allow this. qed"),
collator_peer_id,
overseer_handle,
announce_block,
)?;
}
Ok((task_manager, client))
}
+13
View File
@@ -0,0 +1,13 @@
# Pallets
️ A pallet is a unit of encapsulated logic, with a clearly defined responsibility. A pallet is analogous to a
module in the runtime.
💁 In this template, there is a simple custom pallet based on the FRAME framework.
👉 Learn more about FRAME
[here](https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html).
🧑‍🏫 Please refer to
[this guide](https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/guides/your_first_pallet/index.html)
to learn how to write a basic pallet.
+31
View File
@@ -0,0 +1,31 @@
[package]
name = "pallet-teyrchain-template"
description = "FRAME pallet template for defining custom runtime logic."
version = "0.0.0"
license = "Unlicense"
authors.workspace = true
homepage.workspace = true
repository.workspace = true
edition.workspace = true
publish = false
[lints]
workspace = true
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { features = ["derive"], workspace = true }
scale-info = { features = ["derive"], workspace = true }
frame = { workspace = true, default-features = false, features = [
"experimental",
"runtime",
] }
[features]
default = ["std"]
runtime-benchmarks = ["frame/runtime-benchmarks"]
std = ["codec/std", "frame/std", "scale-info/std"]
try-runtime = ["frame/try-runtime"]
+33
View File
@@ -0,0 +1,33 @@
//! Benchmarking setup for pallet-template
use super::*;
use frame::{deps::frame_benchmarking::v2::*, prelude::*};
#[benchmarks]
mod benchmarks {
use super::*;
#[cfg(test)]
use crate::pallet::Pallet as Template;
use frame_system::RawOrigin;
#[benchmark]
fn do_something() {
let caller: T::AccountId = whitelisted_caller();
#[extrinsic_call]
do_something(RawOrigin::Signed(caller), 100);
assert_eq!(Something::<T>::get().map(|v| v.block_number), Some(100u32.into()));
}
#[benchmark]
fn cause_error() {
Something::<T>::put(CompositeStruct { block_number: 100u32.into() });
let caller: T::AccountId = whitelisted_caller();
#[extrinsic_call]
cause_error(RawOrigin::Signed(caller));
assert_eq!(Something::<T>::get().map(|v| v.block_number), Some(101u32.into()));
}
impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test);
}
+183
View File
@@ -0,0 +1,183 @@
//! # Template Pallet
//!
//! A pallet with minimal functionality to help developers understand the essential components of
//! writing a FRAME pallet. It is typically used in beginner tutorials or in Pezkuwi SDK template
//! as a starting point for creating a new pallet and **not meant to be used in production**.
//!
//! ## Overview
//!
//! This template pallet contains basic examples of:
//! - declaring a storage item that stores a single block-number
//! - declaring and using events
//! - declaring and using errors
//! - a dispatchable function that allows a user to set a new value to storage and emits an event
//! upon success
//! - another dispatchable function that causes a custom error to be thrown
//!
//! Each pallet section is annotated with an attribute using the `#[pallet::...]` procedural macro.
//! This macro generates the necessary code for a pallet to be aggregated into a FRAME runtime.
//!
//! To get started with pallet development, consider using this tutorial:
//!
//! <https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/guides/your_first_pallet/index.html>
//!
//! And reading the main documentation of the `frame` crate:
//!
//! <https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html>
//!
//! And looking at the frame [`kitchen-sink`](https://docs.pezkuwichain.io/sdk/master/pallet_example_kitchensink/index.html)
//! pallet, a showcase of all pallet macros.
//!
//! ### Pallet Sections
//!
//! The pallet sections in this template are:
//!
//! - A **configuration trait** that defines the types and parameters which the pallet depends on
//! (denoted by the `#[pallet::config]` attribute). See: [`Config`].
//! - A **means to store pallet-specific data** (denoted by the `#[pallet::storage]` attribute).
//! See: [`storage_types`].
//! - A **declaration of the events** this pallet emits (denoted by the `#[pallet::event]`
//! attribute). See: [`Event`].
//! - A **declaration of the errors** that this pallet can throw (denoted by the `#[pallet::error]`
//! attribute). See: [`Error`].
//! - A **set of dispatchable functions** that define the pallet's functionality (denoted by the
//! `#[pallet::call]` attribute). See: [`dispatchables`].
//!
//! Run `cargo doc --package pallet-template --open` to view this pallet's documentation.
#![cfg_attr(not(feature = "std"), no_std)]
pub use pallet::*;
#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;
pub mod weights;
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
// <https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html>
// <https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/guides/your_first_pallet/index.html>
//
// To see a full list of `pallet` macros and their use cases, see:
// <https://docs.pezkuwichain.io/sdk/master/pallet_example_kitchensink/index.html>
// <https://docs.pezkuwichain.io/sdk/master/frame_support/pallet_macros/index.html>
#[frame::pallet]
pub mod pallet {
use frame::prelude::*;
/// Configure the pallet by specifying the parameters and types on which it depends.
#[pallet::config]
pub trait Config: frame_system::Config {
#[allow(deprecated)]
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// A type representing the weights required by the dispatchables of this pallet.
type WeightInfo: crate::weights::WeightInfo;
}
#[pallet::pallet]
pub struct Pallet<T>(_);
/// A struct to store a single block-number. Has all the right derives to store it in storage.
/// <https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/reference_docs/frame_storage_derives/index.html>
#[derive(
Encode, Decode, MaxEncodedLen, TypeInfo, CloneNoBound, PartialEqNoBound, DefaultNoBound,
)]
#[scale_info(skip_type_params(T))]
pub struct CompositeStruct<T: Config> {
/// A block number.
pub(crate) block_number: BlockNumberFor<T>,
}
/// The pallet's storage items.
/// <https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/guides/your_first_pallet/index.html#storage>
/// <https://docs.pezkuwichain.io/sdk/master/frame_support/pallet_macros/attr.storage.html>
#[pallet::storage]
pub type Something<T: Config> = StorageValue<_, CompositeStruct<T>>;
/// Pallets use events to inform users when important changes are made.
/// <https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/guides/your_first_pallet/index.html#event-and-error>
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// We usually use passive tense for events.
SomethingStored { block_number: BlockNumberFor<T>, who: T::AccountId },
}
/// Errors inform users that something went wrong.
/// <https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/guides/your_first_pallet/index.html#event-and-error>
#[pallet::error]
pub enum Error<T> {
/// Error names should be descriptive.
NoneValue,
/// Errors should have helpful documentation associated with them.
StorageOverflow,
}
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
/// Dispatchable functions allows users to interact with the pallet and invoke state changes.
/// These functions materialize as "extrinsics", which are often compared to transactions.
/// Dispatchable functions must be annotated with a weight and must return a DispatchResult.
/// <https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/guides/your_first_pallet/index.html#dispatchables>
#[pallet::call]
impl<T: Config> Pallet<T> {
/// An example dispatchable that takes a singles value as a parameter, writes the value to
/// storage and emits an event. This function must be dispatched by a signed extrinsic.
#[pallet::call_index(0)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
pub fn do_something(origin: OriginFor<T>, bn: u32) -> DispatchResultWithPostInfo {
// Check that the extrinsic was signed and get the signer.
// This function will return an error if the extrinsic is not signed.
// <https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/reference_docs/frame_origin/index.html>
let who = ensure_signed(origin)?;
// Convert the u32 into a block number. This is possible because the set of trait bounds
// defined in [`frame_system::Config::BlockNumber`].
let block_number: BlockNumberFor<T> = bn.into();
// Update storage.
<Something<T>>::put(CompositeStruct { block_number });
// Emit an event.
Self::deposit_event(Event::SomethingStored { block_number, who });
// Return a successful [`DispatchResultWithPostInfo`] or [`DispatchResult`].
Ok(().into())
}
/// An example dispatchable that may throw a custom error.
#[pallet::call_index(1)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().reads_writes(1,1))]
pub fn cause_error(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let _who = ensure_signed(origin)?;
// Read a value from storage.
match <Something<T>>::get() {
// Return an error if the value has not been set.
None => Err(Error::<T>::NoneValue)?,
Some(mut old) => {
// Increment the value read from storage; will error in the event of overflow.
old.block_number = old
.block_number
.checked_add(&One::one())
// ^^ equivalent is to:
// .checked_add(&1u32.into())
// both of which build a `One` instance for the type `BlockNumber`.
.ok_or(Error::<T>::StorageOverflow)?;
// Update the value in storage with the incremented result.
<Something<T>>::put(old);
// Explore how you can rewrite this using
// [`frame_support::storage::StorageValue::mutate`].
Ok(().into())
},
}
}
}
}
+48
View File
@@ -0,0 +1,48 @@
use frame::{
deps::{frame_support::weights::constants::RocksDbWeight, frame_system::GenesisConfig},
prelude::*,
runtime::prelude::*,
testing_prelude::*,
};
// Configure a mock runtime to test the pallet.
#[frame_construct_runtime]
mod test_runtime {
#[runtime::runtime]
#[runtime::derive(
RuntimeCall,
RuntimeEvent,
RuntimeError,
RuntimeOrigin,
RuntimeFreezeReason,
RuntimeHoldReason,
RuntimeSlashReason,
RuntimeLockId,
RuntimeTask,
RuntimeViewFunction
)]
pub struct Test;
#[runtime::pallet_index(0)]
pub type System = frame_system;
#[runtime::pallet_index(1)]
pub type Template = crate;
}
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for Test {
type Nonce = u64;
type Block = MockBlock<Test>;
type BlockHashCount = ConstU64<250>;
type DbWeight = RocksDbWeight;
}
impl crate::Config for Test {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
}
// Build genesis storage according to the mock runtime.
pub fn new_test_ext() -> TestState {
GenesisConfig::<Test>::default().build_storage().unwrap().into()
}
+20
View File
@@ -0,0 +1,20 @@
use crate::{mock::*, Error, Something};
use frame::testing_prelude::*;
#[test]
fn it_works_for_default_value() {
new_test_ext().execute_with(|| {
// Dispatch a signed extrinsic.
assert_ok!(Template::do_something(RuntimeOrigin::signed(1), 42));
// Read pallet storage and assert an expected result.
assert_eq!(Something::<Test>::get().map(|v| v.block_number), Some(42));
});
}
#[test]
fn correct_error_for_none_value() {
new_test_ext().execute_with(|| {
// Ensure the expected error is thrown when no value is present.
assert_noop!(Template::cause_error(RuntimeOrigin::signed(1)), Error::<Test>::NoneValue);
});
}
+96
View File
@@ -0,0 +1,96 @@
//! Autogenerated weights for pallet_template
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-04-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `_`, CPU: `<UNKNOWN>`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
// Executed Command:
// ../../target/release/node-template
// benchmark
// pallet
// --chain
// dev
// --pallet
// pallet_template
// --extrinsic
// *
// --steps=50
// --repeat=20
// --wasm-execution=compiled
// --output
// pallets/template/src/weights.rs
// --template
// ../../.maintain/frame-weight-template.hbs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
use frame::{deps::frame_support::weights::constants::RocksDbWeight, prelude::*};
use core::marker::PhantomData;
/// Weight functions needed for pallet_template.
pub trait WeightInfo {
fn do_something() -> Weight;
fn cause_error() -> Weight;
}
/// Weights for pallet_template using the Substrate node and recommended hardware.
#[cfg_attr(
not(feature = "std"),
deprecated(
note = "SubstrateWeight is auto-generated and should not be used in production. Replace it with runtime benchmarked weights."
)
)]
pub struct SubstrateWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
/// Storage: Template Something (r:0 w:1)
/// Proof: Template Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
fn do_something() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 8_000_000 picoseconds.
Weight::from_parts(9_000_000, 0)
.saturating_add(T::DbWeight::get().writes(1_u64))
}
/// Storage: Template Something (r:1 w:1)
/// Proof: Template Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
fn cause_error() -> Weight {
// Proof Size summary in bytes:
// Measured: `32`
// Estimated: `1489`
// Minimum execution time: 6_000_000 picoseconds.
Weight::from_parts(6_000_000, 1489)
.saturating_add(T::DbWeight::get().reads(1_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
}
// For backwards compatibility and tests
impl WeightInfo for () {
/// Storage: Template Something (r:0 w:1)
/// Proof: Template Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
fn do_something() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 8_000_000 picoseconds.
Weight::from_parts(9_000_000, 0)
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
/// Storage: Template Something (r:1 w:1)
/// Proof: Template Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
fn cause_error() -> Weight {
// Proof Size summary in bytes:
// Measured: `32`
// Estimated: `1489`
// Minimum execution time: 6_000_000 picoseconds.
Weight::from_parts(6_000_000, 1489)
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
}
+108
View File
@@ -0,0 +1,108 @@
[package]
name = "teyrchain-template-runtime"
description = "A teyrchain runtime template built with Substrate and Cumulus, part of Pezkuwi Sdk."
version = "0.0.0"
license = "Unlicense"
authors.workspace = true
homepage.workspace = true
repository.workspace = true
edition.workspace = true
publish = false
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[lints]
workspace = true
[dependencies]
codec = { features = ["derive"], workspace = true }
docify = { workspace = true }
hex-literal = { optional = true, workspace = true, default-features = true }
log = { workspace = true }
scale-info = { features = ["derive"], workspace = true }
serde_json = { workspace = true, default-features = false, features = [
"alloc",
] }
smallvec = { workspace = true, default-features = true }
# Local
pallet-teyrchain-template = { workspace = true }
pezkuwi-sdk = { workspace = true, default-features = false, features = [
"pallet-aura",
"pallet-authorship",
"pallet-balances",
"pallet-message-queue",
"pallet-session",
"pallet-sudo",
"pallet-timestamp",
"pallet-transaction-payment",
"pallet-transaction-payment-rpc-runtime-api",
"pallet-xcm",
"pezkuwi-runtime-common",
"pezkuwi-teyrchain-primitives",
"staging-xcm",
"staging-xcm-builder",
"staging-xcm-executor",
"cumulus-pallet-aura-ext",
"cumulus-pallet-session-benchmarking",
"cumulus-pallet-weight-reclaim",
"cumulus-pallet-xcm",
"cumulus-pallet-xcmp-queue",
"cumulus-primitives-aura",
"cumulus-primitives-core",
"cumulus-primitives-utility",
"pallet-collator-selection",
"staging-teyrchain-info",
"teyrchains-common",
"runtime",
] }
# Cumulus
cumulus-pallet-teyrchain-system = { workspace = true }
[build-dependencies]
docify = { workspace = true }
substrate-wasm-builder = { optional = true, workspace = true, default-features = true }
[features]
default = ["std"]
std = [
"codec/std",
"cumulus-pallet-teyrchain-system/std",
"log/std",
"pallet-teyrchain-template/std",
"pezkuwi-sdk/std",
"scale-info/std",
"serde_json/std",
"substrate-wasm-builder",
]
runtime-benchmarks = [
"cumulus-pallet-teyrchain-system/runtime-benchmarks",
"hex-literal",
"pallet-teyrchain-template/runtime-benchmarks",
"pezkuwi-sdk/runtime-benchmarks",
"substrate-wasm-builder?/runtime-benchmarks",
]
try-runtime = [
"cumulus-pallet-teyrchain-system/try-runtime",
"pallet-teyrchain-template/try-runtime",
"pezkuwi-sdk/try-runtime",
]
# Enable the metadata hash generation.
#
# This is hidden behind a feature because it increases the compile time.
# The wasm binary needs to be compiled twice, once to fetch the metadata,
# generate the metadata hash and then a second time with the
# `RUNTIME_METADATA_HASH` environment variable set for the `CheckMetadataHash`
# extension.
metadata-hash = ["substrate-wasm-builder/metadata-hash"]
# A convenience feature for enabling things when doing a build
# for an on-chain release.
on-chain-release-build = ["metadata-hash"]
+10
View File
@@ -0,0 +1,10 @@
# Runtime
️ The runtime (in other words, a state transition function), refers to the core logic of the teyrchain that is
responsible for validating blocks and executing the state changes they define.
💁 The runtime in this template is constructed using ready-made FRAME pallets that ship with
[Pezkuwi SDK](https://github.com/pezkuwichain/pezkuwi-sdk), and a [template for a custom pallet](../pallets/README.md).
👉 Learn more about FRAME
[here](https://docs.pezkuwichain.io/sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html).
+17
View File
@@ -0,0 +1,17 @@
#[cfg(all(feature = "std", feature = "metadata-hash"))]
#[docify::export(template_enable_metadata_hash)]
fn main() {
substrate_wasm_builder::WasmBuilder::init_with_defaults()
.enable_metadata_hash("UNIT", 12)
.build();
}
#[cfg(all(feature = "std", not(feature = "metadata-hash")))]
fn main() {
substrate_wasm_builder::WasmBuilder::build_using_defaults();
}
/// The wasm builder is deactivated when compiling
/// this crate for wasm to speed up the compilation.
#[cfg(not(feature = "std"))]
fn main() {}
+328
View File
@@ -0,0 +1,328 @@
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org>
// External crates imports
use alloc::vec::Vec;
use pezkuwi_sdk::{staging_teyrchain_info as teyrchain_info, *};
use cumulus_primitives_core::ParaId;
use frame_support::{
genesis_builder_helper::{build_state, get_preset},
weights::Weight,
};
use pallet_aura::Authorities;
use sp_api::impl_runtime_apis;
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
traits::Block as BlockT,
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult,
};
use sp_version::RuntimeVersion;
// Local module imports
use super::{
AccountId, Balance, Block, ConsensusHook, Executive, InherentDataExt, Nonce, Runtime,
RuntimeCall, RuntimeGenesisConfig, SessionKeys, System, TeyrchainSystem, TransactionPayment,
SLOT_DURATION, VERSION,
};
// we move some impls outside so we can easily use them with `docify`.
impl Runtime {
#[docify::export]
fn impl_slot_duration() -> sp_consensus_aura::SlotDuration {
sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION)
}
#[docify::export]
fn impl_can_build_upon(
included_hash: <Block as BlockT>::Hash,
slot: cumulus_primitives_aura::Slot,
) -> bool {
ConsensusHook::can_build_upon(included_hash, slot)
}
}
impl_runtime_apis! {
impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
fn slot_duration() -> sp_consensus_aura::SlotDuration {
Runtime::impl_slot_duration()
}
fn authorities() -> Vec<AuraId> {
Authorities::<Runtime>::get().into_inner()
}
}
impl cumulus_primitives_core::RelayParentOffsetApi<Block> for Runtime {
fn relay_parent_offset() -> u32 {
0
}
}
impl cumulus_primitives_aura::AuraUnincludedSegmentApi<Block> for Runtime {
fn can_build_upon(
included_hash: <Block as BlockT>::Hash,
slot: cumulus_primitives_aura::Slot,
) -> bool {
Runtime::impl_can_build_upon(included_hash, slot)
}
}
impl sp_api::Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn execute_block(block: <Block as BlockT>::LazyBlock) {
Executive::execute_block(block)
}
fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
Executive::initialize_block(header)
}
}
impl sp_api::Metadata<Block> for Runtime {
fn metadata() -> OpaqueMetadata {
OpaqueMetadata::new(Runtime::metadata().into())
}
fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
Runtime::metadata_at_version(version)
}
fn metadata_versions() -> Vec<u32> {
Runtime::metadata_versions()
}
}
impl frame_support::view_functions::runtime_api::RuntimeViewFunction<Block> for Runtime {
fn execute_view_function(id: frame_support::view_functions::ViewFunctionId, input: Vec<u8>) -> Result<Vec<u8>, frame_support::view_functions::ViewFunctionDispatchError> {
Runtime::execute_view_function(id, input)
}
}
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 as BlockT>::LazyBlock,
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, Nonce> for Runtime {
fn account_nonce(account: AccountId) -> Nonce {
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)
}
fn query_weight_to_fee(weight: Weight) -> Balance {
TransactionPayment::weight_to_fee(weight)
}
fn query_length_to_fee(length: u32) -> Balance {
TransactionPayment::length_to_fee(length)
}
}
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall>
for Runtime
{
fn query_call_info(
call: RuntimeCall,
len: u32,
) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> {
TransactionPayment::query_call_info(call, len)
}
fn query_call_fee_details(
call: RuntimeCall,
len: u32,
) -> pallet_transaction_payment::FeeDetails<Balance> {
TransactionPayment::query_call_fee_details(call, len)
}
fn query_weight_to_fee(weight: Weight) -> Balance {
TransactionPayment::weight_to_fee(weight)
}
fn query_length_to_fee(length: u32) -> Balance {
TransactionPayment::length_to_fee(length)
}
}
impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
TeyrchainSystem::collect_collation_info(header)
}
}
#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime<Block> for Runtime {
fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
use super::configs::RuntimeBlockWeights;
let weight = Executive::try_runtime_upgrade(checks).unwrap();
(weight, RuntimeBlockWeights::get().max_block)
}
fn execute_block(
block: <Block as BlockT>::LazyBlock,
state_root_check: bool,
signature_check: bool,
select: frame_try_runtime::TryStateSelect,
) -> Weight {
// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
// have a backtrace here.
Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap()
}
}
#[cfg(feature = "runtime-benchmarks")]
impl frame_benchmarking::Benchmark<Block> for Runtime {
fn benchmark_metadata(extra: bool) -> (
Vec<frame_benchmarking::BenchmarkList>,
Vec<pezkuwi_sdk::frame_support::traits::StorageInfo>,
) {
use frame_benchmarking::BenchmarkList;
use pezkuwi_sdk::frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
use super::*;
let mut list = Vec::<BenchmarkList>::new();
list_benchmarks!(list, extra);
let storage_info = AllPalletsWithSystem::storage_info();
(list, storage_info)
}
#[allow(non_local_definitions)]
fn dispatch_benchmark(
config: frame_benchmarking::BenchmarkConfig
) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
use frame_benchmarking::{BenchmarkError, BenchmarkBatch};
use super::*;
use frame_system_benchmarking::Pallet as SystemBench;
impl frame_system_benchmarking::Config for Runtime {
fn setup_set_code_requirements(code: &Vec<u8>) -> Result<(), BenchmarkError> {
TeyrchainSystem::initialize_for_set_code_benchmark(code.len() as u32);
Ok(())
}
fn verify_set_code() {
System::assert_last_event(cumulus_pallet_teyrchain_system::Event::<Runtime>::ValidationFunctionStored.into());
}
}
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
use pezkuwi_sdk::frame_support::traits::WhitelistedStorageKeys;
let whitelist = AllPalletsWithSystem::whitelisted_storage_keys();
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)
}
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, crate::genesis_config_presets::get_preset)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
crate::genesis_config_presets::preset_names()
}
}
impl cumulus_primitives_core::GetTeyrchainInfo<Block> for Runtime {
fn teyrchain_id() -> ParaId {
teyrchain_info::Pallet::<Runtime>::teyrchain_id()
}
}
}
+37
View File
@@ -0,0 +1,37 @@
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org>
pezkuwi_sdk::frame_benchmarking::define_benchmarks!(
[frame_system, SystemBench::<Runtime>]
[pallet_balances, Balances]
[pallet_session, SessionBench::<Runtime>]
[pallet_timestamp, Timestamp]
[pallet_message_queue, MessageQueue]
[pallet_sudo, Sudo]
[pallet_collator_selection, CollatorSelection]
[cumulus_pallet_teyrchain_system, TeyrchainSystem]
[cumulus_pallet_xcmp_queue, XcmpQueue]
[cumulus_pallet_weight_reclaim, WeightReclaim]
);
+348
View File
@@ -0,0 +1,348 @@
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org>
mod xcm_config;
use pezkuwi_sdk::{staging_teyrchain_info as teyrchain_info, staging_xcm as xcm, *};
#[cfg(not(feature = "runtime-benchmarks"))]
use pezkuwi_sdk::{staging_xcm_builder as xcm_builder, staging_xcm_executor as xcm_executor};
// Substrate and Pezkuwi dependencies
use cumulus_pallet_teyrchain_system::RelayNumberMonotonicallyIncreases;
use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use frame_support::{
derive_impl,
dispatch::DispatchClass,
parameter_types,
traits::{
ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, TransformOrigin, VariantCountOf,
},
weights::{ConstantMultiplier, Weight},
PalletId,
};
use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureRoot,
};
use pallet_xcm::{EnsureXcm, IsVoiceOfBody};
use pezkuwi_runtime_common::{
xcm_sender::ExponentialPrice, BlockHashCount, SlowAdjustingFeeUpdate,
};
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_runtime::Perbill;
use sp_version::RuntimeVersion;
use teyrchains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling};
use xcm::latest::prelude::{AssetId, BodyId};
// Local module imports
use super::{
weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight},
AccountId, Aura, Balance, Balances, Block, BlockNumber, CollatorSelection, ConsensusHook, Hash,
MessageQueue, Nonce, PalletInfo, Runtime, RuntimeCall, RuntimeEvent, RuntimeFreezeReason,
RuntimeHoldReason, RuntimeOrigin, RuntimeTask, Session, SessionKeys, System, TeyrchainSystem,
WeightToFee, XcmpQueue, AVERAGE_ON_INITIALIZE_RATIO, CENTS, EXISTENTIAL_DEPOSIT, HOURS,
MAXIMUM_BLOCK_WEIGHT, MICRO_UNIT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, VERSION,
};
use xcm_config::{RelayLocation, XcmOriginToTransactDispatchOrigin};
parameter_types! {
pub const Version: RuntimeVersion = VERSION;
// This part is copied from Substrate's `bin/node/runtime/src/lib.rs`.
// The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the
// `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize
// the lazy contract deletion.
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: u16 = 42;
}
/// All migrations of the runtime, aside from the ones declared in the pallets.
///
/// This can be a tuple of types, each implementing `OnRuntimeUpgrade`.
#[allow(unused_parens)]
type SingleBlockMigrations = ();
/// The default types are being injected by [`derive_impl`](`frame_support::derive_impl`) from
/// [`TeyrchainDefaultConfig`](`struct@frame_system::config_preludes::TeyrchainDefaultConfig`),
/// but overridden as needed.
#[derive_impl(frame_system::config_preludes::TeyrchainDefaultConfig)]
impl frame_system::Config for Runtime {
/// The identifier used to distinguish between accounts.
type AccountId = AccountId;
/// The index type for storing how many extrinsics an account has signed.
type Nonce = Nonce;
/// The type for hashing blocks and tries.
type Hash = Hash;
/// The block type.
type Block = Block;
/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
type BlockHashCount = BlockHashCount;
/// Runtime version.
type Version = Version;
/// The data to be stored in an account.
type AccountData = pallet_balances::AccountData<Balance>;
/// The weight of database operations that the runtime can invoke.
type DbWeight = RocksDbWeight;
/// Block & extrinsics weights: base values and limits.
type BlockWeights = RuntimeBlockWeights;
/// The maximum length of a block (in bytes).
type BlockLength = RuntimeBlockLength;
/// This is used as an identifier of the chain. 42 is the generic substrate prefix.
type SS58Prefix = SS58Prefix;
/// The action to take on a Runtime Upgrade
type OnSetCode = cumulus_pallet_teyrchain_system::TeyrchainSetCode<Self>;
type MaxConsumers = frame_support::traits::ConstU32<16>;
type SingleBlockMigrations = SingleBlockMigrations;
}
/// Configure the palelt weight reclaim tx.
impl cumulus_pallet_weight_reclaim::Config for Runtime {
type WeightInfo = ();
}
impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the unix epoch.
type Moment = u64;
type OnTimestampSet = Aura;
type MinimumPeriod = ConstU64<0>;
type WeightInfo = ();
}
impl pallet_authorship::Config for Runtime {
type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Aura>;
type EventHandler = (CollatorSelection,);
}
parameter_types! {
pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT;
}
impl pallet_balances::Config for Runtime {
type MaxLocks = ConstU32<50>;
/// The type for recording an account's balance.
type Balance = Balance;
/// The ubiquitous event type.
type RuntimeEvent = RuntimeEvent;
type DustRemoval = ();
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
type MaxReserves = ConstU32<50>;
type ReserveIdentifier = [u8; 8];
type RuntimeHoldReason = RuntimeHoldReason;
type RuntimeFreezeReason = RuntimeFreezeReason;
type FreezeIdentifier = RuntimeFreezeReason;
type MaxFreezes = VariantCountOf<RuntimeFreezeReason>;
type DoneSlashHandler = ();
}
parameter_types! {
/// Relay Chain `TransactionByteFee` / 10
pub const TransactionByteFee: Balance = 10 * MICRO_UNIT;
}
impl pallet_transaction_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaction = pallet_transaction_payment::FungibleAdapter<Balances, ()>;
type WeightToFee = WeightToFee;
type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightInfo = ();
}
impl pallet_sudo::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type WeightInfo = ();
}
parameter_types! {
pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent;
}
impl cumulus_pallet_teyrchain_system::Config for Runtime {
type WeightInfo = ();
type RuntimeEvent = RuntimeEvent;
type OnSystemEvent = ();
type SelfParaId = teyrchain_info::Pallet<Runtime>;
type OutboundXcmpMessageSource = XcmpQueue;
type DmpQueue = frame_support::traits::EnqueueWithOrigin<MessageQueue, RelayOrigin>;
type ReservedDmpWeight = ReservedDmpWeight;
type XcmpMessageHandler = XcmpQueue;
type ReservedXcmpWeight = ReservedXcmpWeight;
type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases;
type ConsensusHook = ConsensusHook;
type RelayParentOffset = ConstU32<0>;
}
impl teyrchain_info::Config for Runtime {}
parameter_types! {
pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block;
}
impl pallet_message_queue::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
#[cfg(feature = "runtime-benchmarks")]
type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor<
cumulus_primitives_core::AggregateMessageOrigin,
>;
#[cfg(not(feature = "runtime-benchmarks"))]
type MessageProcessor = xcm_builder::ProcessXcmMessage<
AggregateMessageOrigin,
xcm_executor::XcmExecutor<xcm_config::XcmConfig>,
RuntimeCall,
>;
type Size = u32;
// The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin:
type QueueChangeHandler = NarrowOriginToSibling<XcmpQueue>;
type QueuePausedQuery = NarrowOriginToSibling<XcmpQueue>;
type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>;
type MaxStale = sp_core::ConstU32<8>;
type ServiceWeight = MessageQueueServiceWeight;
type IdleMaxServiceWeight = ();
}
impl cumulus_pallet_aura_ext::Config for Runtime {}
parameter_types! {
/// The asset ID for the asset that we use to pay for message delivery fees.
pub FeeAssetId: AssetId = AssetId(xcm_config::RelayLocation::get());
/// The base fee for the message delivery fees.
pub const ToSiblingBaseDeliveryFee: u128 = CENTS.saturating_mul(3);
pub const ToParentBaseDeliveryFee: u128 = CENTS.saturating_mul(3);
}
/// The price for delivering XCM messages to sibling teyrchains.
pub type PriceForSiblingTeyrchainDelivery =
ExponentialPrice<FeeAssetId, ToSiblingBaseDeliveryFee, TransactionByteFee, XcmpQueue>;
/// The price for delivering XCM messages to relay chain.
pub type PriceForParentDelivery =
ExponentialPrice<FeeAssetId, ToParentBaseDeliveryFee, TransactionByteFee, TeyrchainSystem>;
impl cumulus_pallet_xcmp_queue::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ChannelInfo = TeyrchainSystem;
type VersionWrapper = ();
// Enqueue XCMP messages from siblings for later processing.
type XcmpQueue = TransformOrigin<MessageQueue, AggregateMessageOrigin, ParaId, ParaIdToSibling>;
type MaxInboundSuspended = sp_core::ConstU32<1_000>;
type MaxActiveOutboundChannels = ConstU32<128>;
type MaxPageSize = ConstU32<{ 1 << 16 }>;
type ControllerOrigin = EnsureRoot<AccountId>;
type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
type WeightInfo = ();
type PriceForSiblingDelivery = PriceForSiblingTeyrchainDelivery;
}
parameter_types! {
pub const Period: u32 = 6 * HOURS;
pub const Offset: u32 = 0;
}
impl pallet_session::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
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 let's be pedantic.
type SessionHandler = <SessionKeys as sp_runtime::traits::OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys;
type DisablingStrategy = ();
type WeightInfo = ();
type Currency = Balances;
type KeyDeposit = ();
}
#[docify::export(aura_config)]
impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
type DisabledValidators = ();
type MaxAuthorities = ConstU32<100_000>;
type AllowMultipleBlocksPerSlot = ConstBool<true>;
type SlotDuration = ConstU64<SLOT_DURATION>;
}
parameter_types! {
pub const PotId: PalletId = PalletId(*b"PotStake");
pub const SessionLength: BlockNumber = 6 * HOURS;
// StakingAdmin pluralistic body.
pub const StakingAdminBodyId: BodyId = BodyId::Defense;
}
/// We allow root and the StakingAdmin to execute privileged collator selection operations.
pub type CollatorSelectionUpdateOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
EnsureXcm<IsVoiceOfBody<RelayLocation, StakingAdminBodyId>>,
>;
impl pallet_collator_selection::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type UpdateOrigin = CollatorSelectionUpdateOrigin;
type PotId = PotId;
type MaxCandidates = ConstU32<100>;
type MinEligibleCollators = ConstU32<4>;
type MaxInvulnerables = ConstU32<20>;
// 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 = ();
}
/// Configure the pallet template in pallets/template.
impl pallet_teyrchain_template::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = pallet_teyrchain_template::weights::SubstrateWeight<Runtime>;
}
+207
View File
@@ -0,0 +1,207 @@
use super::PriceForParentDelivery;
use crate::{
AccountId, AllPalletsWithSystem, Balances, PezkuwiXcm, Runtime, RuntimeCall, RuntimeEvent,
RuntimeOrigin, TeyrchainInfo, TeyrchainSystem, WeightToFee, XcmpQueue,
};
use pezkuwi_sdk::{
staging_xcm as xcm, staging_xcm_builder as xcm_builder, staging_xcm_executor as xcm_executor, *,
};
use frame_support::{
parameter_types,
traits::{ConstU32, Contains, Everything, Nothing},
weights::Weight,
};
use frame_system::EnsureRoot;
use pallet_xcm::XcmPassthrough;
use pezkuwi_runtime_common::impls::ToAuthor;
use pezkuwi_sdk::{
pezkuwi_sdk_frame::traits::Disabled,
staging_xcm_builder::{DenyRecursively, DenyThenTry},
};
use pezkuwi_teyrchain_primitives::primitives::Sibling;
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom,
DenyReserveTransferToRelayChain, EnsureXcmOrigin, FixedWeightBounds,
FrameTransactionalProcessor, FungibleAdapter, IsConcrete, NativeAsset, ParentIsPreset,
RelayChainAsNative, SiblingTeyrchainAsNative, SiblingTeyrchainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic,
};
use xcm_executor::XcmExecutor;
parameter_types! {
pub const RelayLocation: Location = Location::parent();
pub const RelayNetwork: Option<NetworkId> = None;
pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
// For the real deployment, it is recommended to set `RelayNetwork` according to the relay chain
// and prepend `UniversalLocation` with `GlobalConsensus(RelayNetwork::get())`.
pub UniversalLocation: InteriorLocation = Teyrchain(TeyrchainInfo::teyrchain_id().into()).into();
}
/// Type for specifying how a `Location` 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 teyrchain origins convert to AccountId via the `ParaId::into`.
SiblingTeyrchainConvertsVia<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 = FungibleAdapter<
// 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 Location 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, RuntimeOrigin>,
// Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when
// recognized.
RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
// Native converter for sibling Teyrchains; will convert to a `SiblingPara` origin when
// recognized.
SiblingTeyrchainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
// Native signed account converter; this just converts an `AccountId32` origin into a normal
// `RuntimeOrigin::Signed` origin of the same 32-byte value.
SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
XcmPassthrough<RuntimeOrigin>,
);
parameter_types! {
// One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate.
pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024);
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64;
}
pub struct ParentOrParentsExecutivePlurality;
impl Contains<Location> for ParentOrParentsExecutivePlurality {
fn contains(location: &Location) -> bool {
matches!(location.unpack(), (1, []) | (1, [Plurality { id: BodyId::Executive, .. }]))
}
}
pub type Barrier = TrailingSetTopicAsId<
DenyThenTry<
DenyRecursively<DenyReserveTransferToRelayChain>,
(
TakeWeightCredit,
WithComputedOrigin<
(
AllowTopLevelPaidExecutionFrom<Everything>,
AllowExplicitUnpaidExecutionFrom<ParentOrParentsExecutivePlurality>,
// ^^^ Parent and its exec plurality get free execution
),
UniversalLocation,
ConstU32<8>,
>,
),
>,
>;
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type RuntimeCall = RuntimeCall;
type XcmSender = XcmRouter;
type XcmEventEmitter = PezkuwiXcm;
// How to withdraw and deposit an asset.
type AssetTransactor = LocalAssetTransactor;
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = NativeAsset;
type IsTeleporter = (); // Teleporting is disabled.
type UniversalLocation = UniversalLocation;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
type Trader =
UsingComponents<WeightToFee, RelayLocation, AccountId, Balances, ToAuthor<Runtime>>;
type ResponseHandler = PezkuwiXcm;
type AssetTrap = PezkuwiXcm;
type AssetClaims = PezkuwiXcm;
type SubscriptionService = PezkuwiXcm;
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type AssetLocker = ();
type AssetExchanger = ();
type FeeManager = ();
type MessageExporter = ();
type UniversalAliases = Nothing;
type CallDispatcher = RuntimeCall;
type SafeCallFilter = Everything;
type Aliasers = Nothing;
type TransactionalProcessor = FrameTransactionalProcessor;
type HrmpNewChannelOpenRequestHandler = ();
type HrmpChannelAcceptedHandler = ();
type HrmpChannelClosingHandler = ();
type XcmRecorder = PezkuwiXcm;
}
/// Converts a local signed origin into an XCM location. Forms the basis for local origins
/// sending/executing XCMs.
pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
/// The means for routing XCM messages which are not for local execution into the right message
/// queues.
pub type XcmRouter = WithUniqueTopic<(
// Two routers - use UMP to communicate with the relay chain:
cumulus_primitives_utility::ParentAsUmp<TeyrchainSystem, PezkuwiXcm, PriceForParentDelivery>,
// ..and XCMP to communicate with the sibling chains.
XcmpQueue,
)>;
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
type XcmRouter = XcmRouter;
type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
type XcmExecuteFilter = Nothing;
// ^ Disable dispatchable execute on the XCM pallet.
// Needs to be `Everything` for local testing.
type XcmExecutor = XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Nothing;
type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
type UniversalLocation = UniversalLocation;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
// ^ Override for AdvertisedXcmVersion default
type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
type Currency = Balances;
type CurrencyMatcher = ();
type TrustedLockers = ();
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = pallet_xcm::TestWeightInfo;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
// Aliasing is disabled: xcm_executor::Config::Aliasers is set to `Nothing`.
type AuthorizedAliasConsideration = Disabled;
}
impl cumulus_pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type XcmExecutor = XcmExecutor<XcmConfig>;
}
+112
View File
@@ -0,0 +1,112 @@
use crate::{
AccountId, BalancesConfig, CollatorSelectionConfig, PezkuwiXcmConfig, RuntimeGenesisConfig,
SessionConfig, SessionKeys, SudoConfig, TeyrchainInfoConfig, EXISTENTIAL_DEPOSIT,
};
use alloc::{vec, vec::Vec};
use pezkuwi_sdk::{staging_xcm as xcm, *};
use cumulus_primitives_core::ParaId;
use frame_support::build_struct_json_patch;
use serde_json::Value;
use sp_genesis_builder::PresetId;
use sp_keyring::Sr25519Keyring;
use teyrchains_common::AuraId;
/// The default XCM version to set in genesis config.
const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION;
/// Teyrchain id used for genesis config presets of teyrchain template.
#[docify::export_content]
pub const TEYRCHAIN_ID: u32 = 1000;
/// Generate the session keys from individual elements.
///
/// The input must be a tuple of individual keys (a single arg for now since we have just one key).
pub fn template_session_keys(keys: AuraId) -> SessionKeys {
SessionKeys { aura: keys }
}
fn testnet_genesis(
invulnerables: Vec<(AccountId, AuraId)>,
endowed_accounts: Vec<AccountId>,
root: AccountId,
id: ParaId,
) -> Value {
build_struct_json_patch!(RuntimeGenesisConfig {
balances: BalancesConfig {
balances: endowed_accounts
.iter()
.cloned()
.map(|k| (k, 1u128 << 60))
.collect::<Vec<_>>(),
},
teyrchain_info: TeyrchainInfoConfig { teyrchain_id: id },
collator_selection: CollatorSelectionConfig {
invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect::<Vec<_>>(),
candidacy_bond: EXISTENTIAL_DEPOSIT * 16,
},
session: SessionConfig {
keys: invulnerables
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
template_session_keys(aura), // session keys
)
})
.collect::<Vec<_>>(),
},
pezkuwi_xcm: PezkuwiXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION) },
sudo: SudoConfig { key: Some(root) },
})
}
fn local_testnet_genesis() -> Value {
testnet_genesis(
// initial collators.
vec![
(Sr25519Keyring::Alice.to_account_id(), Sr25519Keyring::Alice.public().into()),
(Sr25519Keyring::Bob.to_account_id(), Sr25519Keyring::Bob.public().into()),
],
Sr25519Keyring::well_known().map(|k| k.to_account_id()).collect(),
Sr25519Keyring::Alice.to_account_id(),
TEYRCHAIN_ID.into(),
)
}
fn development_config_genesis() -> Value {
testnet_genesis(
// initial collators.
vec![
(Sr25519Keyring::Alice.to_account_id(), Sr25519Keyring::Alice.public().into()),
(Sr25519Keyring::Bob.to_account_id(), Sr25519Keyring::Bob.public().into()),
],
Sr25519Keyring::well_known().map(|k| k.to_account_id()).collect(),
Sr25519Keyring::Alice.to_account_id(),
TEYRCHAIN_ID.into(),
)
}
/// Provides the JSON representation of predefined genesis config for given `id`.
pub fn get_preset(id: &PresetId) -> Option<vec::Vec<u8>> {
let patch = match id.as_ref() {
sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET => local_testnet_genesis(),
sp_genesis_builder::DEV_RUNTIME_PRESET => development_config_genesis(),
_ => return None,
};
Some(
serde_json::to_string(&patch)
.expect("serialization to json is expected to work. qed.")
.into_bytes(),
)
}
/// List of supported presets.
pub fn preset_names() -> Vec<PresetId> {
vec![
PresetId::from(sp_genesis_builder::DEV_RUNTIME_PRESET),
PresetId::from(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET),
]
}
+317
View File
@@ -0,0 +1,317 @@
#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit = "256"]
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
pub mod apis;
#[cfg(feature = "runtime-benchmarks")]
mod benchmarks;
pub mod configs;
mod genesis_config_presets;
mod weights;
extern crate alloc;
use alloc::vec::Vec;
use smallvec::smallvec;
use pezkuwi_sdk::{staging_teyrchain_info as teyrchain_info, *};
use sp_runtime::{
generic, impl_opaque_keys,
traits::{BlakeTwo256, IdentifyAccount, Verify},
MultiSignature,
};
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use frame_support::weights::{
constants::WEIGHT_REF_TIME_PER_SECOND, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients,
WeightToFeePolynomial,
};
pub use genesis_config_presets::TEYRCHAIN_ID;
pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
pub use sp_runtime::{MultiAddress, Perbill, Permill};
use weights::ExtrinsicBaseWeight;
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
pub type Signature = MultiSignature;
/// Some way of identifying an account on the chain. We intentionally make it equivalent
/// to the public key of our transaction signing scheme.
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
/// Balance of an account.
pub type Balance = u128;
/// Index of a transaction in the chain.
pub type Nonce = u32;
/// A hash of some data used by the chain.
pub type Hash = sp_core::H256;
/// An index to a block.
pub type BlockNumber = u32;
/// The address format for describing accounts.
pub type Address = MultiAddress<AccountId, ()>;
/// Block header type as expected by this runtime.
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
/// 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 extension to the basic transaction logic.
#[docify::export(template_signed_extra)]
pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
Runtime,
(
frame_system::AuthorizeCall<Runtime>,
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>,
frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
),
>;
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic =
generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
/// Executive: handles dispatch to the various modules.
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
>;
/// 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 Pezkuwichain, extrinsic base weight (smallest non-zero weight) is mapped to 1
// MILLI_UNIT: in our template, we map to 1/10 of that, or 1/10 MILLI_UNIT
let p = MILLI_UNIT / 10;
let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time());
smallvec![WeightToFeeCoefficient {
degree: 1,
negative: false,
coeff_frac: Perbill::from_rational(p % q, q),
coeff_integer: p / q,
}]
}
}
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
/// to even the core data structures.
pub mod opaque {
use super::*;
pub use pezkuwi_sdk::sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
use pezkuwi_sdk::sp_runtime::{
generic,
traits::{BlakeTwo256, Hash as HashT},
};
/// Opaque block header type.
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
/// Opaque block type.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// Opaque block identifier type.
pub type BlockId = generic::BlockId<Block>;
/// Opaque block hash type.
pub type Hash = <BlakeTwo256 as HashT>::Output;
}
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: Aura,
}
}
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: alloc::borrow::Cow::Borrowed("teyrchain-template-runtime"),
impl_name: alloc::borrow::Cow::Borrowed("teyrchain-template-runtime"),
authoring_version: 1,
spec_version: 1,
impl_version: 0,
apis: apis::RUNTIME_API_VERSIONS,
transaction_version: 1,
system_version: 1,
};
#[docify::export]
mod block_times {
/// This determines the average expected block time that we are targeting. Blocks will be
/// produced at a minimum duration defined by `SLOT_DURATION`. `SLOT_DURATION` is picked up by
/// `pallet_timestamp` which is in turn picked up by `pallet_aura` to implement `fn
/// slot_duration()`.
///
/// Change this to adjust the block time.
pub const MILLI_SECS_PER_BLOCK: u64 = 6000;
// NOTE: Currently it is not possible to change the slot duration after the chain has started.
// Attempting to do so will brick block production.
pub const SLOT_DURATION: u64 = MILLI_SECS_PER_BLOCK;
}
pub use block_times::*;
// Time is measured by number of blocks.
pub const MINUTES: BlockNumber = 60_000 / (MILLI_SECS_PER_BLOCK as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;
// Unit = the base number of indivisible units for balances
pub const UNIT: Balance = 1_000_000_000_000;
pub const CENTS: Balance = UNIT / 100;
pub const MILLI_UNIT: Balance = 1_000_000_000;
pub const MICRO_UNIT: Balance = 1_000_000;
/// The existential deposit. Set to 1/10 of the Connected Relay Chain.
pub const EXISTENTIAL_DEPOSIT: Balance = MILLI_UNIT;
/// We assume that ~5% of the block weight is consumed by `on_initialize` handlers. This is
/// used to limit the maximal weight of a single extrinsic.
const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5);
/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used by
/// `Operational` extrinsics.
const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
#[docify::export(max_block_weight)]
/// We allow for 2 seconds of compute with a 6 second average block time.
const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(
WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2),
cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64,
);
#[docify::export]
mod async_backing_params {
/// Maximum number of blocks simultaneously accepted by the Runtime, not yet included
/// into the relay chain.
pub(crate) const UNINCLUDED_SEGMENT_CAPACITY: u32 = 3;
/// How many teyrchain blocks are processed by the relay chain per parent. Limits the
/// number of blocks authored per slot.
pub(crate) const BLOCK_PROCESSING_VELOCITY: u32 = 1;
/// Relay chain slot duration, in milliseconds.
pub(crate) const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000;
}
pub(crate) use async_backing_params::*;
#[docify::export]
/// Aura consensus hook
type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook<
Runtime,
RELAY_CHAIN_SLOT_DURATION_MILLIS,
BLOCK_PROCESSING_VELOCITY,
UNINCLUDED_SEGMENT_CAPACITY,
>;
/// 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() }
}
// Create the runtime by composing the FRAME pallets that were previously configured.
#[frame_support::runtime]
mod runtime {
#[runtime::runtime]
#[runtime::derive(
RuntimeCall,
RuntimeEvent,
RuntimeError,
RuntimeOrigin,
RuntimeFreezeReason,
RuntimeHoldReason,
RuntimeSlashReason,
RuntimeLockId,
RuntimeTask,
RuntimeViewFunction
)]
pub struct Runtime;
#[runtime::pallet_index(0)]
pub type System = frame_system;
#[runtime::pallet_index(1)]
pub type TeyrchainSystem = cumulus_pallet_teyrchain_system;
#[runtime::pallet_index(2)]
pub type Timestamp = pallet_timestamp;
#[runtime::pallet_index(3)]
pub type TeyrchainInfo = teyrchain_info;
#[runtime::pallet_index(4)]
pub type WeightReclaim = cumulus_pallet_weight_reclaim;
// Monetary stuff.
#[runtime::pallet_index(10)]
pub type Balances = pallet_balances;
#[runtime::pallet_index(11)]
pub type TransactionPayment = pallet_transaction_payment;
// Governance
#[runtime::pallet_index(15)]
pub type Sudo = pallet_sudo;
// Collator support. The order of these 4 are important and shall not change.
#[runtime::pallet_index(20)]
pub type Authorship = pallet_authorship;
#[runtime::pallet_index(21)]
pub type CollatorSelection = pallet_collator_selection;
#[runtime::pallet_index(22)]
pub type Session = pallet_session;
#[runtime::pallet_index(23)]
pub type Aura = pallet_aura;
#[runtime::pallet_index(24)]
pub type AuraExt = cumulus_pallet_aura_ext;
// XCM helpers.
#[runtime::pallet_index(30)]
pub type XcmpQueue = cumulus_pallet_xcmp_queue;
#[runtime::pallet_index(31)]
pub type PezkuwiXcm = pallet_xcm;
#[runtime::pallet_index(32)]
pub type CumulusXcm = cumulus_pallet_xcm;
#[runtime::pallet_index(33)]
pub type MessageQueue = pallet_message_queue;
// Template
#[runtime::pallet_index(50)]
pub type TemplatePallet = pallet_teyrchain_template;
}
#[docify::export(register_validate_block)]
cumulus_pallet_teyrchain_system::register_validate_block! {
Runtime = Runtime,
BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
}
+57
View File
@@ -0,0 +1,57 @@
// This file is part of Substrate.
// Copyright (C) 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 constants {
use pezkuwi_sdk::*;
use frame_support::{
parameter_types,
weights::{constants, Weight},
};
parameter_types! {
/// Importing a block with 0 Extrinsics.
pub const BlockExecutionWeight: Weight =
Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_000_000), 0);
}
#[cfg(test)]
mod test_weights {
use pezkuwi_sdk::*;
use frame_support::weights::constants;
/// Checks that the weight exists and is sane.
// NOTE: If this test fails but you are sure that the generated values are fine,
// you can delete it.
#[test]
fn sane() {
let w = super::constants::BlockExecutionWeight::get();
// At least 100 µs.
assert!(
w.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS,
"Weight should be at least 100 µs."
);
// At most 50 ms.
assert!(
w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS,
"Weight should be at most 50 ms."
);
}
}
}
+57
View File
@@ -0,0 +1,57 @@
// This file is part of Substrate.
// Copyright (C) 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 constants {
use pezkuwi_sdk::*;
use frame_support::{
parameter_types,
weights::{constants, Weight},
};
parameter_types! {
/// Executing a NO-OP `System::remarks` Extrinsic.
pub const ExtrinsicBaseWeight: Weight =
Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(125_000), 0);
}
#[cfg(test)]
mod test_weights {
use pezkuwi_sdk::*;
use frame_support::weights::constants;
/// Checks that the weight exists and is sane.
// NOTE: If this test fails but you are sure that the generated values are fine,
// you can delete it.
#[test]
fn sane() {
let w = super::constants::ExtrinsicBaseWeight::get();
// At least 10 µs.
assert!(
w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS,
"Weight should be at least 10 µs."
);
// At most 1 ms.
assert!(
w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS,
"Weight should be at most 1 ms."
);
}
}
}
+27
View File
@@ -0,0 +1,27 @@
// This file is part of Substrate.
// Copyright (C) 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.
//! Expose the auto generated weight files.
pub mod block_weights;
pub mod extrinsic_weights;
pub mod paritydb_weights;
pub mod rocksdb_weights;
pub use block_weights::constants::BlockExecutionWeight;
pub use extrinsic_weights::constants::ExtrinsicBaseWeight;
pub use rocksdb_weights::constants::RocksDbWeight;
+67
View File
@@ -0,0 +1,67 @@
// This file is part of Substrate.
// Copyright (C) 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 constants {
use pezkuwi_sdk::*;
use frame_support::{
parameter_types,
weights::{constants, RuntimeDbWeight},
};
parameter_types! {
/// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights
/// are available for brave runtime engineers who may want to try this out as default.
pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight {
read: 8_000 * constants::WEIGHT_REF_TIME_PER_NANOS,
write: 50_000 * constants::WEIGHT_REF_TIME_PER_NANOS,
};
}
#[cfg(test)]
mod test_db_weights {
use pezkuwi_sdk::*;
use super::constants::ParityDbWeight as W;
use frame_support::weights::constants;
/// Checks that all weights exist and have sane values.
// NOTE: If this test fails but you are sure that the generated values are fine,
// you can delete it.
#[test]
fn sane() {
// At least 1 µs.
assert!(
W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS,
"Read weight should be at least 1 µs."
);
assert!(
W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS,
"Write weight should be at least 1 µs."
);
// At most 1 ms.
assert!(
W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS,
"Read weight should be at most 1 ms."
);
assert!(
W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS,
"Write weight should be at most 1 ms."
);
}
}
}
+67
View File
@@ -0,0 +1,67 @@
// This file is part of Substrate.
// Copyright (C) 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 constants {
use pezkuwi_sdk::*;
use frame_support::{
parameter_types,
weights::{constants, RuntimeDbWeight},
};
parameter_types! {
/// By default, Substrate uses `RocksDB`, so this will be the weight used throughout
/// the runtime.
pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight {
read: 25_000 * constants::WEIGHT_REF_TIME_PER_NANOS,
write: 100_000 * constants::WEIGHT_REF_TIME_PER_NANOS,
};
}
#[cfg(test)]
mod test_db_weights {
use pezkuwi_sdk::*;
use super::constants::RocksDbWeight as W;
use frame_support::weights::constants;
/// Checks that all weights exist and have sane values.
// NOTE: If this test fails but you are sure that the generated values are fine,
// you can delete it.
#[test]
fn sane() {
// At least 1 µs.
assert!(
W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS,
"Read weight should be at least 1 µs."
);
assert!(
W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS,
"Write weight should be at least 1 µs."
);
// At most 1 ms.
assert!(
W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS,
"Read weight should be at most 1 ms."
);
assert!(
W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS,
"Write weight should be at most 1 ms."
);
}
}
}
+22
View File
@@ -0,0 +1,22 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Cumulus is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
// The teyrchain-template crate helps with keeping the README.md in sync
// with code sections across the components under the template: node,
// pallets & runtime, by using `docify`.
#[cfg(feature = "generate-readme")]
docify::compile_markdown!("README.docify.md", "README.md");
+22
View File
@@ -0,0 +1,22 @@
[relaychain]
default_command = "pezkuwi"
chain = "pezkuwichain-local"
[[relaychain.nodes]]
name = "alice"
validator = true
ws_port = 9944
[[relaychain.nodes]]
name = "bob"
validator = true
ws_port = 9955
[[teyrchains]]
id = 1000
chain_spec_path = "./dev_chain_spec.json"
[teyrchains.collator]
name = "charlie"
ws_port = 9988
command = "pezkuwi-omni-node"
+21
View File
@@ -0,0 +1,21 @@
[relaychain]
default_command = "pezkuwi"
chain = "pezkuwichain-local"
[[relaychain.nodes]]
name = "alice"
validator = true
ws_port = 9944
[[relaychain.nodes]]
name = "bob"
validator = true
ws_port = 9955
[[teyrchains]]
id = 1000
[teyrchains.collator]
name = "charlie"
ws_port = 9988
command = "teyrchain-template-node"