Compare commits
No commits in common. "main" and "mridkwya" have entirely different histories.
59
Cargo.lock
generated
@ -1,6 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "Inflector"
|
||||
@ -1186,7 +1186,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "casper-runtime"
|
||||
version = "3.5.31"
|
||||
version = "3.5.19"
|
||||
dependencies = [
|
||||
"casper-runtime-constants",
|
||||
"frame-benchmarking",
|
||||
@ -1203,7 +1203,6 @@ dependencies = [
|
||||
"ghost-networks",
|
||||
"ghost-runtime-common",
|
||||
"ghost-slow-clap",
|
||||
"ghost-sudo",
|
||||
"log",
|
||||
"pallet-alliance",
|
||||
"pallet-authority-discovery",
|
||||
@ -3505,7 +3504,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-claims"
|
||||
version = "0.2.4"
|
||||
version = "0.2.2"
|
||||
dependencies = [
|
||||
"frame-benchmarking",
|
||||
"frame-support",
|
||||
@ -3529,7 +3528,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-cli"
|
||||
version = "0.8.2"
|
||||
version = "0.7.179"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"clap 4.5.4",
|
||||
@ -3561,7 +3560,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-client-cli"
|
||||
version = "0.1.4"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"array-bytes",
|
||||
"clap 4.5.4",
|
||||
@ -3585,7 +3584,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-machine-primitives"
|
||||
version = "0.8.2"
|
||||
version = "0.7.179"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"sc-sysinfo",
|
||||
@ -3594,7 +3593,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-metrics"
|
||||
version = "0.8.2"
|
||||
version = "0.7.179"
|
||||
dependencies = [
|
||||
"assert_cmd",
|
||||
"bs58 0.5.1",
|
||||
@ -3617,7 +3616,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-miner"
|
||||
version = "1.5.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
@ -3649,17 +3648,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-networks"
|
||||
version = "0.1.16"
|
||||
version = "0.7.179"
|
||||
dependencies = [
|
||||
"frame-benchmarking",
|
||||
"frame-support",
|
||||
"frame-system",
|
||||
"ghost-core-primitives",
|
||||
"ghost-traits",
|
||||
"num-traits",
|
||||
"pallet-balances",
|
||||
"pallet-staking",
|
||||
"pallet-staking-reward-curve",
|
||||
"parity-scale-codec",
|
||||
"scale-info",
|
||||
"sp-io 30.0.0",
|
||||
@ -3669,7 +3665,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-node"
|
||||
version = "0.8.2"
|
||||
version = "0.7.179"
|
||||
dependencies = [
|
||||
"assert_cmd",
|
||||
"color-eyre",
|
||||
@ -3685,7 +3681,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-remote-ext-tests-bags-list"
|
||||
version = "1.0.1"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"casper-runtime",
|
||||
"casper-runtime-constants",
|
||||
@ -3700,7 +3696,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-rpc"
|
||||
version = "0.8.2"
|
||||
version = "0.7.179"
|
||||
dependencies = [
|
||||
"ghost-core-primitives",
|
||||
"jsonrpsee",
|
||||
@ -3729,7 +3725,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-runtime-common"
|
||||
version = "0.4.3"
|
||||
version = "0.4.2"
|
||||
dependencies = [
|
||||
"frame-support",
|
||||
"frame-system",
|
||||
@ -3752,7 +3748,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-service"
|
||||
version = "0.8.2"
|
||||
version = "0.7.179"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"async-trait",
|
||||
@ -3836,7 +3832,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-slow-clap"
|
||||
version = "0.3.40"
|
||||
version = "0.3.14"
|
||||
dependencies = [
|
||||
"frame-benchmarking",
|
||||
"frame-support",
|
||||
@ -3845,8 +3841,6 @@ dependencies = [
|
||||
"log",
|
||||
"pallet-balances",
|
||||
"pallet-session",
|
||||
"pallet-staking",
|
||||
"pallet-staking-reward-curve",
|
||||
"parity-scale-codec",
|
||||
"scale-info",
|
||||
"serde",
|
||||
@ -3861,7 +3855,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-staging-chain-spec-builder"
|
||||
version = "1.6.2"
|
||||
version = "1.6.1"
|
||||
dependencies = [
|
||||
"clap 4.5.4",
|
||||
"log",
|
||||
@ -3870,24 +3864,9 @@ dependencies = [
|
||||
"sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.12.0)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ghost-sudo"
|
||||
version = "0.0.2"
|
||||
dependencies = [
|
||||
"docify",
|
||||
"frame-benchmarking",
|
||||
"frame-support",
|
||||
"frame-system",
|
||||
"parity-scale-codec",
|
||||
"scale-info",
|
||||
"sp-io 30.0.0",
|
||||
"sp-runtime 31.0.1",
|
||||
"sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.12.0)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ghost-traits"
|
||||
version = "0.3.23"
|
||||
version = "0.3.19"
|
||||
dependencies = [
|
||||
"frame-support",
|
||||
"sp-runtime 31.0.1",
|
||||
@ -3895,7 +3874,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-voter-bags"
|
||||
version = "0.3.7"
|
||||
version = "0.3.6"
|
||||
dependencies = [
|
||||
"casper-runtime",
|
||||
"clap 4.5.4",
|
||||
@ -3905,7 +3884,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghostkey"
|
||||
version = "0.3.16"
|
||||
version = "0.3.15"
|
||||
dependencies = [
|
||||
"clap 4.5.4",
|
||||
"ghost-client-cli",
|
||||
|
31
Cargo.toml
@ -17,7 +17,7 @@ homepage.workspace = true
|
||||
[workspace.package]
|
||||
license = "GPL-3.0-only"
|
||||
authors = ["571nky", "57r37ch", "f4750"]
|
||||
version = "0.8.2"
|
||||
version = "0.7.179"
|
||||
edition = "2021"
|
||||
homepage = "https://ghostchain.io"
|
||||
repository = "https://git.ghostchain.io/ghostchain/ghost-node"
|
||||
@ -69,7 +69,6 @@ bs58 = { version = "0.5.0" }
|
||||
prometheus-parse = { version = "0.2.2" }
|
||||
rustc-hex = { version = "2.1.0", default-features = false }
|
||||
log = { version = "0.4", default-features = false }
|
||||
num-traits = { version = "0.2.17", default-features = false }
|
||||
libsecp256k1 = { version = "0.7", default-features = false }
|
||||
bip39 = { package = "parity-bip39", version = "2.0.1" }
|
||||
sha3 = { version = "0.10", default-features = false }
|
||||
@ -230,7 +229,6 @@ ghost-traits = { path = "pallets/traits", default-features = false }
|
||||
ghost-networks = { path = "pallets/networks", default-features = false }
|
||||
ghost-claims = { path = "pallets/claims", default-features = false }
|
||||
ghost-slow-clap = { path = "pallets/slow-clap", default-features = false }
|
||||
ghost-sudo = { path = "pallets/sudo", default-features = false }
|
||||
ghost-runtime-constants = { package = "ghost-runtime-constants", path = "runtime/ghost/constants", default-features = false }
|
||||
casper-runtime = { path = "runtime/casper", default-features = false }
|
||||
casper-runtime-constants = { package = "casper-runtime-constants", path = "runtime/casper/constants", default-features = false }
|
||||
@ -260,25 +258,24 @@ substrate-build-script-utils = { workspace = true }
|
||||
resolver = "2"
|
||||
|
||||
members = [
|
||||
"core-primitives",
|
||||
"core-primitives",
|
||||
"cli",
|
||||
"rpc",
|
||||
"service",
|
||||
"rpc",
|
||||
"service",
|
||||
"metrics",
|
||||
"client/cli",
|
||||
"primitives/machine",
|
||||
"runtime/common",
|
||||
"runtime/casper",
|
||||
"runtime/casper/constants",
|
||||
"pallets/networks",
|
||||
"pallets/claims",
|
||||
"pallets/slow-clap",
|
||||
"pallets/sudo",
|
||||
"utils/bags-list",
|
||||
"utils/chain-spec-builder",
|
||||
"utils/generate-bags",
|
||||
"runtime/common",
|
||||
"runtime/casper",
|
||||
"runtime/casper/constants",
|
||||
"pallets/networks",
|
||||
"pallets/claims",
|
||||
"pallets/slow-clap",
|
||||
"utils/bags-list",
|
||||
"utils/chain-spec-builder",
|
||||
"utils/generate-bags",
|
||||
"utils/ghostkey",
|
||||
"utils/staking-miner",
|
||||
"utils/staking-miner",
|
||||
]
|
||||
|
||||
[badges]
|
||||
|
0
LICENSE.md
Normal file → Executable file
572
README.md
Normal file → Executable file
@ -1,571 +1 @@
|
||||
# Notes
|
||||
|
||||
Arrows will mark the places where your input is needed
|
||||
|
||||
# Update system
|
||||
|
||||
Update Your System: Before installing any new software,
|
||||
it's a good practice to update your system's package list and
|
||||
upgrade the existing packages to their latest versions.
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt upgrade
|
||||
```
|
||||
|
||||
# Firewall
|
||||
|
||||
Install Ubuntu firewall
|
||||
```bash
|
||||
sudo apt install ufw
|
||||
```
|
||||
|
||||
If you want to connect to your node-machine, allow connection to the SSH port
|
||||
```bash
|
||||
sudo ufw allow ssh
|
||||
```
|
||||

|
||||
|
||||
Enable firewall, confirm the operation
|
||||
```bash
|
||||
sudo ufw enable
|
||||
```
|
||||

|
||||
|
||||
Check firewall status. You should see `Status: active`
|
||||
```bash
|
||||
sudo ufw numbered
|
||||
```
|
||||

|
||||
|
||||
# SSH
|
||||
## Install SSH
|
||||
|
||||
Once you have installed the proper Operating System on you machine
|
||||
we recommend that you enable SSH. Most people have a Daily Driver machine.
|
||||
GHOST requires a separate machine. Adding an extra machine to your life could be cumbersome.
|
||||
Chances are you had to use an external monitor to install Ubuntu on GHOST Node,
|
||||
the same screen regularly used by the Daily Driver machine.
|
||||
SSH enables you to manage your GHOST Nodes remotely from the comfort of your Daily Driver.
|
||||
|
||||
Install OpenSSH Server: With your system updated, the next step is to install
|
||||
the OpenSSH server package. This package contains the necessary software to run
|
||||
an SSH server.
|
||||
|
||||
```bash
|
||||
sudo apt install openssh-server
|
||||
```
|
||||
|
||||
Start SSH Service using _systemctl_.
|
||||
|
||||
```bash
|
||||
sudo systemctl start ssh
|
||||
```
|
||||
|
||||
Enable SSH Service to Start on Boot: To ensure that the SSH service automatically
|
||||
starts after a reboot, you need to enable it using _systemctl_.
|
||||
|
||||
```bash
|
||||
sudo systemctl enable ssh
|
||||
```
|
||||
|
||||
To check the status of the SSH service, run the following command:
|
||||
|
||||
```bash
|
||||
sudo systemctl status ssh
|
||||
```
|
||||
|
||||
You should be seeing something like this:
|
||||
|
||||

|
||||
|
||||
## Connect by SSH
|
||||
|
||||
With SSH enabled and the firewall configured, you can now connect
|
||||
to your node machine from another computer using SSH.
|
||||
You have to know your username and your local network ip
|
||||
|
||||
```bash
|
||||
ssh [username]@[your_server_ip_OR_hostname]
|
||||
```
|
||||
|
||||
# Install GHOST Application
|
||||
## Allow Ports
|
||||
Allow `port 30333` on GHOST Node:
|
||||
```bash
|
||||
sudo ufw allow 30333
|
||||
```
|
||||

|
||||
|
||||
To ensure that the ports are allowed, run the following command:
|
||||
```bash
|
||||
sudo ufw numbered
|
||||
```
|
||||

|
||||
|
||||
## Install Substrate Libraries
|
||||
Click [here](https://docs.substrate.io/install/linux/) for a detailed Rust guide if you want to dive deep into the documentation. Otherwise let's proceed.
|
||||
|
||||
### Install Dependencies
|
||||
Check the documentation for your operating system for information about
|
||||
the packages that are installed and how to download and install
|
||||
any additional packages you might need. For example,
|
||||
if you use Debian/Ubuntu, you can use the Advanced Packaging Tool (apt)
|
||||
to install packages:
|
||||
|
||||
```bash
|
||||
sudo apt install -y build-essential clang curl git make libssl-dev protobuf-compiler llvm libudev-dev
|
||||
```
|
||||
|
||||
### Rust Install
|
||||
|
||||
Download the rustup installation program and use it to install Rust by running the following command:
|
||||
```bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
```
|
||||
|
||||
Press Enter for using default options:
|
||||
|
||||

|
||||
|
||||
Update your current shell to include Cargo by running the following command:
|
||||
```bash
|
||||
source $HOME/.cargo/env
|
||||
```
|
||||
|
||||
Verify your installation by running the following command:
|
||||
```bash
|
||||
rustc --version
|
||||
```
|
||||
|
||||
You should see something like this:
|
||||
|
||||

|
||||
|
||||
Configure the Rust toolchain to default to the latest stable version by running the following commands:
|
||||
```bash
|
||||
rustup default stable
|
||||
```
|
||||
```bash
|
||||
rustup update
|
||||
```
|
||||
|
||||
Add the nightly release and the nightly WebAssembly (wasm) targets
|
||||
to your development environment by running the following commands:
|
||||
```bash
|
||||
rustup update nightly
|
||||
```
|
||||
|
||||
```bash
|
||||
rustup target add wasm32-unknown-unknown --toolchain nightly
|
||||
```
|
||||
|
||||
```bash
|
||||
rustup target add wasm32-unknown-unknown --toolchain stable-x86_64-unknown-linux-gnu
|
||||
```
|
||||
|
||||
If you are trying to install WebAssembly (wasm) on an ARM-based processor like the ones in Raspberry Pi try this instead:
|
||||
```bash
|
||||
rustup target add wasm32-unknown-unknown --toolchain stable-aarch64-unknown-linux-gnu
|
||||
```
|
||||
|
||||
**_IF error try_**
|
||||
```bash
|
||||
rustup target add wasm32-unknown-unknown --toolchain default
|
||||
```
|
||||
|
||||
Verify the configuration of your development environment by running
|
||||
the following command:
|
||||
```bash
|
||||
rustup show
|
||||
```
|
||||
|
||||
```bash
|
||||
rustup +nightly show
|
||||
```
|
||||
|
||||
You should see something like this:
|
||||
|
||||

|
||||

|
||||
|
||||
Now run:
|
||||
```bash
|
||||
rustup component add rust-src --toolchain stable
|
||||
```
|
||||
|
||||
**_IF error try_**
|
||||
```bash
|
||||
rustup component add rust-src --toolchain default
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Install GHOST
|
||||
|
||||
Check if Git is already installed:
|
||||
```bash
|
||||
git --version
|
||||
```
|
||||

|
||||
|
||||
Make a GHOST Directory and go to it:
|
||||
```bash
|
||||
mkdir ghost && cd ghost
|
||||
```
|
||||
|
||||
Clone GHOST Node Git:
|
||||
```bash
|
||||
git clone https://git.ghostchain.io/ghostchain/ghost-node.git
|
||||
```
|
||||
|
||||
Go to ghost-node directory:
|
||||
```bash
|
||||
cd ghost-node
|
||||
```
|
||||
|
||||
Compile the node template by running the following command:
|
||||
```bash
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
The build can take up to 20 minutes depending on the specifications of your machine.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
# Boot Node Qualification
|
||||
|
||||
## Boot Node Qualification Test
|
||||
|
||||
Becoming a Boot Node on GHOST Chain is an absolute MUST if we want the network
|
||||
to be sufficiently decentralized. However, due to certain ISP limitations
|
||||
some countries make it being a Boot Node easier than others.
|
||||
Hence, the GHOST Dev team came up with a Boot Node Qualification Test.
|
||||
|
||||
First we should install TRACEROUTE:
|
||||
```bash
|
||||
sudo apt install traceroute
|
||||
```
|
||||
|
||||
Then we must determine the public IP for your GHOST Node Machine.
|
||||
|
||||
```bash
|
||||
curl -4 icanhazip.com
|
||||
```
|
||||

|
||||
|
||||
Then type the following command replacing `<YOUR_IP_FROM_PREVIOUS_STEP>` with an actual IP address from previous step:
|
||||
```bash
|
||||
traceroute <YOUR_IP_FROM_PREVIOUS_STEP>
|
||||
```
|
||||
|
||||
If your GHOST Node is **not behind a NAT** your terminal window should look something like this:
|
||||
|
||||

|
||||
|
||||
If your GHOST Node is **behind NAT** your terminal window should look something like this:
|
||||
|
||||

|
||||
|
||||
If your GHOST Node is NOT behind the NAT then your node can be a Boot Node.
|
||||
If your GHOST Node is behind the NAT then your node CANNOT be a Boot Node
|
||||
and you will have to use some kind of proxy to rectify the situation.
|
||||
|
||||
Afterwards, post the screenshot of your terminal window in the Whales group.
|
||||
Feel free to blur out your IP.
|
||||
|
||||
## Setting Proper Firewall Rules
|
||||
|
||||
You must enable `port 30333` on your router
|
||||
|
||||
Based on prior instructions you may have configured your firewall in way that is
|
||||
no longer needed. For the purpose of GHOST Chain you should only
|
||||
open `port 30333` and close other ports.
|
||||
|
||||
### Checking Firewall
|
||||
|
||||
Check the ports that are opened on your firewall:
|
||||
```bash
|
||||
sudo ufw numbered
|
||||
```
|
||||

|
||||
|
||||
If `port 9945` is opened then close it:
|
||||
```bash
|
||||
sudo ufw deny 9945
|
||||
```
|
||||
|
||||
### Configuring Router
|
||||
|
||||
Enable port forwarding for port 30333 on your router. Be mindful that different networks and routers have different ways of setting this up. It is best to search for portforwarding instruction for the specific router model.
|
||||
|
||||

|
||||
|
||||
### Checking Ports
|
||||
Simulate a broadcasting node by running a dummy GHOST Node launch command:
|
||||
```bash
|
||||
./target/release/ghost --port=30333 --rpc-port=9945 --chain=dev --node-key=0000000000000000000000000000000000000000000000000000000000000001 --base-path=/tmp/alice --alice --validator --unsafe-rpc-external --no-telemetry --state-pruning=archive
|
||||
```
|
||||
|
||||
To check ports go to [Port Checker Website](https://dnschecker.org/port-scanner.php) and check following ports:
|
||||
```
|
||||
30333, 9945
|
||||
```
|
||||
|
||||
Only `port 30333` should be opened.
|
||||
|
||||

|
||||
|
||||
Press _CTRL+C_ to stop the node.
|
||||
|
||||
# Launching GHOST TestNet 3.1
|
||||
|
||||
Switch to main GIT branch:
|
||||
```bash
|
||||
git switch main
|
||||
```
|
||||
|
||||
Make sure `ghost-node` is up to date:
|
||||
```bash
|
||||
git pull origin main
|
||||
```
|
||||
|
||||
## Generating keys
|
||||
Create ghost configuration directory:
|
||||
```bash
|
||||
sudo mkdir /etc/ghost
|
||||
```
|
||||
|
||||
Give the user permission to the directory:
|
||||
```bash
|
||||
sudo chown $(whoami) /etc/ghost
|
||||
```
|
||||
|
||||
To generate the node key use the following command:
|
||||
```bash
|
||||
./target/release/ghost key generate-node-key --bin --file=/etc/ghost/node-key
|
||||
```
|
||||
|
||||
Generate Wallet Key file with the following command:
|
||||
```bash
|
||||
./target/release/ghost key generate | grep "Secret seed" | awk '{$1=$2=""; sub(/^[ \t]+/, ""); print}' > /etc/ghost/wallet-key
|
||||
```
|
||||
|
||||
Display the wallet-key on the screen by using cat command:
|
||||
```bash
|
||||
./target/release/ghost key inspect $(cat /etc/ghost/wallet-key)
|
||||
```
|
||||

|
||||
|
||||
Feel free to back the file on a separate storage device.
|
||||
|
||||
Generate Stash Key file with the following command:
|
||||
```bash
|
||||
./target/release/ghost key generate | grep "Secret seed" | awk '{$1=$2=""; sub(/^[ \t]+/, ""); print}' > /etc/ghost/stash-key
|
||||
```
|
||||
|
||||
Display the stash-key on the screen by using cat command:
|
||||
```bash
|
||||
./target/release/ghost key inspect $(cat /etc/ghost/stash-key)
|
||||
```
|
||||

|
||||
|
||||
Generate Session Key file with the following command:
|
||||
```bash
|
||||
./target/release/ghost key generate | grep "Secret seed" | awk '{$1=$2=""; sub(/^[ \t]+/, ""); print}' > /etc/ghost/session-key
|
||||
```
|
||||
You have generates 4 types of Session Keys:
|
||||
|
||||
1. Session Key – AUDI
|
||||
2. Session Key – BABE
|
||||
3. Session Key – SLOW
|
||||
4. Session Key – GRAN
|
||||
|
||||
Now let's display them!
|
||||
|
||||
Display the session-key//audi on the screen by using cat command:
|
||||
```bash
|
||||
./target/release/ghost key inspect "$(cat /etc/ghost/session-key)//audi"
|
||||
```
|
||||

|
||||
|
||||
Display the session-key//babe on the screen by using cat command:
|
||||
```bash
|
||||
./target/release/ghost key inspect "$(cat /etc/ghost/session-key)//babe"
|
||||
```
|
||||

|
||||
|
||||
Display the session-key//slow on the screen by using cat command:
|
||||
```bash
|
||||
./target/release/ghost key inspect "$(cat /etc/ghost/session-key)//slow"
|
||||
```
|
||||

|
||||
|
||||
Display the session-key//gran on the screen by using cat command:
|
||||
```bash
|
||||
./target/release/ghost key inspect "$(cat /etc/ghost/session-key)//gran" --scheme=ed25519
|
||||
```
|
||||

|
||||
|
||||
## Build and start the ghost-node
|
||||
|
||||
Recompile `ghost-node` using `starter.sh` and `--release` flag.
|
||||
Make `ghost-node` service being able to be started by default user
|
||||
using `--make-global`:
|
||||
```bash
|
||||
./scripts/starter.sh --release --make-global
|
||||
```
|
||||
|
||||
We need to recompile so type y and press Enter to proceed:
|
||||
|
||||

|
||||
|
||||
Recompiling will take some time!
|
||||
|
||||
The script needs higher permissions to write the ghost-node startup file, so it may ask for your user's password
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Check the hash of the build:
|
||||
```bash
|
||||
sha256sum /etc/ghost/casper.json
|
||||
```
|
||||
|
||||
You should see:
|
||||
```
|
||||
ad653233c978bfd00c5e4525b17628632bc4319c5f5f4b4dcc2f050ef3c3d145
|
||||
```
|
||||
|
||||
Create running `ghost-node` service that starts on system boot using `--unit-file` flag.
|
||||
And we must set up the `ghost-node` launch command by setting arguments using
|
||||
`--set-arguments` flag:
|
||||
```bash
|
||||
./scripts/starter.sh --unit-file --set-arguments
|
||||
```
|
||||
|
||||
Only change the defaults if you are advanced otherwise press _Enter_ for
|
||||
the following prompts.
|
||||
|
||||
If this is your first node simply press _Enter_ to proceed with the default.
|
||||
If this is your second node you should type a different port here,
|
||||
for example `30334`, and then you should open this port on your firewall
|
||||
and create a dedicated port forwarding rule on your router as specified
|
||||
in the Testing Connectivity Part:
|
||||
```
|
||||
specify p2p protocol TCP port (default: 30333): 30334
|
||||
```
|
||||
|
||||
To choose default options press Enter here:
|
||||
|
||||

|
||||
|
||||
Currently, you have to qualify to become a validator node through [GHOST Whales](https://ghostchain.io/whales-apply).
|
||||
If you were NOT included in the [ghosties file](https://git.ghostchain.io/ghostchain/ghost-node/src/branch/main/service/ghosties) then you cannot be a validator node,
|
||||
and you can only be a full node so for `disable validator mode? [y/N]` type `y`.
|
||||
If you were included in the ghosties file you can press Enter:
|
||||
```
|
||||
disable validator mode? [y/N]: y
|
||||
```
|
||||

|
||||
|
||||
Press _Enter_ for reject enabling Prometheus:
|
||||
|
||||

|
||||
|
||||
For the following prompt:
|
||||
```
|
||||
list of bootnodes if any:
|
||||
```
|
||||
|
||||
Paste one of available **Boot Node** addresses.
|
||||
|
||||
Official **Boot Node** addresses:
|
||||
```
|
||||
/dns/bootnode69.chain.ghostchain.io/tcp/30334/p2p/12D3KooWF9SWxz9dmy6vfndQhoxqCa7PESaoFWEiF8Jkqh4xKDRf
|
||||
```
|
||||
```
|
||||
/dns/bootnode70.chain.ghostchain.io/tcp/30333/p2p/12D3KooWP3h5dSdqcpvsCr7fp1jyfqDj291QDZ68a4gY6VQ8T1nW
|
||||
```
|
||||
|
||||
A full list of available **Boot Nodes** can be found on [the guide page](https://blog.ghostchain.io/launching-ghost-testnet-3-1/#Boot_Node).
|
||||
|
||||

|
||||
|
||||
Press _Enter_:
|
||||
|
||||

|
||||
|
||||
Changing `unit-file` name is optional, otherwise press _Enter_:
|
||||
|
||||

|
||||
|
||||
Type `y` and press _Enter_ for create dedicated user for running `ghost-node`:
|
||||
|
||||

|
||||
|
||||
**DO NOT start and DO NOT enable** `ghost-node.service` (press _Enter_):
|
||||
|
||||

|
||||
|
||||
Now you can check whether or not the keys on your GHOST Node match those
|
||||
in the [ghosties file](https://git.ghostchain.io/ghostchain/ghost-node/src/branch/main/service/ghosties) on GHOST Git.
|
||||
If you are running a **Validator Node** and if you have followed
|
||||
the Generating Keys Part you will see all `[+]`.
|
||||
If you are a running a **Full Node** you will see errors:
|
||||
|
||||
(Press _Enter_ for prompts)
|
||||
```bash
|
||||
./scripts/starter.sh --check-keys
|
||||
```
|
||||
|
||||
Full Node:
|
||||
|
||||

|
||||
|
||||
Validator Node:
|
||||
|
||||

|
||||
|
||||
Start `ghost-node`:
|
||||
```bash
|
||||
sudo systemctl start ghost-node
|
||||
```
|
||||
|
||||
Wait 60 seconds!
|
||||
|
||||
Check node is started:
|
||||
```bash
|
||||
sudo systemctl status ghost-node
|
||||
```
|
||||

|
||||
|
||||
For exit press _CTRL+C_
|
||||
|
||||
In order to insert keys run the following flags `--check-keys` `--insert-keys`:
|
||||
```bash
|
||||
./scripts/starter.sh --check-keys --insert-keys
|
||||
```
|
||||
|
||||
Restart `ghost-node`:
|
||||
```bash
|
||||
sudo systemctl restart ghost-node
|
||||
```
|
||||
|
||||
Enable `ghost-node`:
|
||||
```bash
|
||||
sudo systemctl enable ghost-node
|
||||
```
|
||||

|
||||
|
||||
To see the logs produced by your `ghost-node`:
|
||||
```bash
|
||||
journalctl -f -u ghost-node
|
||||
```
|
||||
|
||||
To exit press _CTRL+C_.
|
||||
|
||||
Congratulations! You have an operational GHOST Node.
|
||||
TODO
|
||||
|
14
cli/Cargo.toml
Normal file → Executable file
@ -52,14 +52,14 @@ substrate-build-script-utils = { workspace = true }
|
||||
default = ["cli", "db", "full-node"]
|
||||
db = ["service/db"]
|
||||
cli = [
|
||||
"clap",
|
||||
"clap",
|
||||
"frame-benchmarking-cli",
|
||||
"sc-cli",
|
||||
"sc-service",
|
||||
"sc-tracing",
|
||||
"service",
|
||||
"ghost-client-cli",
|
||||
"ghost-machine-primitives",
|
||||
"sc-cli",
|
||||
"sc-service",
|
||||
"sc-tracing",
|
||||
"service",
|
||||
"ghost-client-cli",
|
||||
"ghost-machine-primitives",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"frame-benchmarking-cli?/runtime-benchmarks",
|
||||
|
2
cli/build.rs
Normal file → Executable file
@ -1,4 +1,4 @@
|
||||
fn main() {
|
||||
fn main () {
|
||||
if let Ok(profile) = std::env::var("PROFILE") {
|
||||
println!("cargo:rustc-cfg=build_type=\"{}\"", profile);
|
||||
}
|
||||
|
2
cli/src/cli.rs
Normal file → Executable file
@ -84,7 +84,7 @@ pub struct RunCmd {
|
||||
#[arg(long)]
|
||||
pub no_hardware_benchmarks: bool,
|
||||
|
||||
/// Enable the block authoring backoff that is triggered when finality is
|
||||
/// Enable the block authoring backoff that is triggered when finality is
|
||||
/// lagging.
|
||||
#[arg(long)]
|
||||
pub force_authoring_backoff: bool,
|
||||
|
191
cli/src/command.rs
Normal file → Executable file
@ -1,13 +1,14 @@
|
||||
use crate::cli::{Cli, Subcommand};
|
||||
use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory};
|
||||
use futures::future::TryFutureExt;
|
||||
use keyring::Sr25519Keyring;
|
||||
use sc_cli::SubstrateCli;
|
||||
use service::{
|
||||
self,
|
||||
benchmarking::{benchmark_inherent_data, RemarkBuilder, TransferKeepAliveBuilder},
|
||||
IdentifyVariant,
|
||||
self, IdentifyVariant,
|
||||
benchmarking::{
|
||||
benchmark_inherent_data, RemarkBuilder, TransferKeepAliveBuilder
|
||||
},
|
||||
};
|
||||
use keyring::Sr25519Keyring;
|
||||
|
||||
pub use crate::{error::Error, service::BlockId};
|
||||
#[cfg(feature = "pyroscope")]
|
||||
@ -67,35 +68,28 @@ impl SubstrateCli for Cli {
|
||||
#[cfg(feature = "casper-native")]
|
||||
"casper" => Box::new(service::chain_spec::casper_config()?),
|
||||
#[cfg(feature = "casper-native")]
|
||||
"casper-dev" | "dev" | "development" => {
|
||||
Box::new(service::chain_spec::casper_development_config()?)
|
||||
}
|
||||
"casper-dev" | "dev" | "development" => Box::new(service::chain_spec::casper_development_config()?),
|
||||
#[cfg(feature = "casper-native")]
|
||||
"casper-local" | "local" => {
|
||||
Box::new(service::chain_spec::casper_local_testnet_config()?)
|
||||
}
|
||||
"casper-local" | "local" => Box::new(service::chain_spec::casper_local_testnet_config()?),
|
||||
#[cfg(feature = "casper-native")]
|
||||
"casper-staging" | "staging" => {
|
||||
Box::new(service::chain_spec::casper_staging_testnet_config()?)
|
||||
}
|
||||
"casper-staging" | "staging" => Box::new(service::chain_spec::casper_staging_testnet_config()?),
|
||||
#[cfg(not(feature = "casper-native"))]
|
||||
name if name.starts_with("casper-") && !name.ends_with(".json") => Err(format!(
|
||||
"`{}` only supported with `casper-native` feature enabled.",
|
||||
name
|
||||
))?,
|
||||
name if name.starts_with("casper-") && !name.ends_with(".json") =>
|
||||
Err(format!("`{}` only supported with `casper-native` feature enabled.", name))?,
|
||||
#[cfg(feature = "casper-native")]
|
||||
path => {
|
||||
let path = std::path::PathBuf::from(path);
|
||||
|
||||
let chain_spec = Box::new(service::GenericChainSpec::from_json_file(path.clone())?)
|
||||
as Box<dyn service::ChainSpec>;
|
||||
let chain_spec = Box::new(
|
||||
service::GenericChainSpec::from_json_file(path.clone())?
|
||||
) as Box<dyn service::ChainSpec>;
|
||||
|
||||
if chain_spec.is_casper() {
|
||||
Box::new(service::CasperChainSpec::from_json_file(path)?)
|
||||
Box::new(service::CasperChainSpec::from_json_file(path)?)
|
||||
} else {
|
||||
chain_spec
|
||||
chain_spec
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -115,7 +109,10 @@ fn set_ss58_version(spec: &Box<dyn service::ChainSpec>) {
|
||||
sp_core::crypto::set_default_ss58_version(ss58_version);
|
||||
}
|
||||
|
||||
fn run_node_inner<F>(cli: Cli, logger_hook: F) -> Result<()>
|
||||
fn run_node_inner<F>(
|
||||
cli: Cli,
|
||||
logger_hook: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration),
|
||||
{
|
||||
@ -131,8 +128,7 @@ where
|
||||
.then_some(config.database.path().map(|database_path| {
|
||||
let _ = std::fs::create_dir_all(&database_path);
|
||||
sc_sysinfo::gather_hwbench(Some(database_path))
|
||||
}))
|
||||
.flatten();
|
||||
})).flatten();
|
||||
|
||||
let database_source = config.database.clone();
|
||||
let task_manager = service::build_full(
|
||||
@ -142,8 +138,7 @@ where
|
||||
telemetry_worker_handle: None,
|
||||
hwbench,
|
||||
},
|
||||
)
|
||||
.map(|full| full.task_manager)?;
|
||||
).map(|full| full.task_manager)?;
|
||||
|
||||
if let Some(path) = database_source.path() {
|
||||
sc_storage_monitor::StorageMonitorService::try_spawn(
|
||||
@ -172,9 +167,7 @@ pub fn run() -> Result<()> {
|
||||
let agent = pyro::Pyroscope::builder(
|
||||
"http://".to_owned() + address.to_string().as_str(),
|
||||
"ghost".to_owned(),
|
||||
)
|
||||
.backend(pprof_backend(PprofConfig::new().sample_rate(113)))
|
||||
.build()?;
|
||||
).backend(pprof_backend(PprofConfig::new().sample_rate(113))).build()?;
|
||||
|
||||
Some(agent.start()?)
|
||||
} else {
|
||||
@ -183,7 +176,7 @@ pub fn run() -> Result<()> {
|
||||
|
||||
#[cfg(not(feature = "pyroscope"))]
|
||||
if cli.run.pyroscope_server.is_some() {
|
||||
return Err(Error::PyroscopeNotCompiledIn);
|
||||
return Err(Error::PyroscopeNotCompiledIn)
|
||||
}
|
||||
|
||||
match &cli.subcommand {
|
||||
@ -191,7 +184,7 @@ pub fn run() -> Result<()> {
|
||||
Some(Subcommand::BuildSpec(cmd)) => {
|
||||
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
|
||||
Ok(runner.sync_run(|config| cmd.run(config.chain_spec, config.network))?)
|
||||
}
|
||||
},
|
||||
Some(Subcommand::CheckBlock(cmd)) => {
|
||||
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
|
||||
let chain_spec = &runner.config().chain_spec;
|
||||
@ -199,13 +192,11 @@ pub fn run() -> Result<()> {
|
||||
set_ss58_version(chain_spec);
|
||||
|
||||
runner.async_run(|mut config| {
|
||||
let (client, _, import_queue, task_manager) = service::new_chain_ops(&mut config)?;
|
||||
Ok((
|
||||
cmd.run(client, import_queue).map_err(Error::SubstrateCli),
|
||||
task_manager,
|
||||
))
|
||||
let (client, _, import_queue, task_manager) =
|
||||
service::new_chain_ops(&mut config)?;
|
||||
Ok((cmd.run(client, import_queue).map_err(Error::SubstrateCli), task_manager))
|
||||
})
|
||||
}
|
||||
},
|
||||
Some(Subcommand::ExportBlocks(cmd)) => {
|
||||
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
|
||||
let chain_spec = &runner.config().chain_spec;
|
||||
@ -213,14 +204,11 @@ pub fn run() -> Result<()> {
|
||||
set_ss58_version(chain_spec);
|
||||
|
||||
Ok(runner.async_run(|mut config| {
|
||||
let (client, _, _, task_manager) = service::new_chain_ops(&mut config)?;
|
||||
Ok((
|
||||
cmd.run(client, config.database)
|
||||
.map_err(Error::SubstrateCli),
|
||||
task_manager,
|
||||
))
|
||||
let ( client, _, _, task_manager ) =
|
||||
service::new_chain_ops(&mut config)?;
|
||||
Ok((cmd.run(client, config.database).map_err(Error::SubstrateCli), task_manager))
|
||||
})?)
|
||||
}
|
||||
},
|
||||
Some(Subcommand::ExportState(cmd)) => {
|
||||
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
|
||||
let chain_spec = &runner.config().chain_spec;
|
||||
@ -228,14 +216,11 @@ pub fn run() -> Result<()> {
|
||||
set_ss58_version(chain_spec);
|
||||
|
||||
Ok(runner.async_run(|mut config| {
|
||||
let (client, _, _, task_manager) = service::new_chain_ops(&mut config)?;
|
||||
Ok((
|
||||
cmd.run(client, config.chain_spec)
|
||||
.map_err(Error::SubstrateCli),
|
||||
task_manager,
|
||||
))
|
||||
let ( client, _, _, task_manager ) =
|
||||
service::new_chain_ops(&mut config)?;
|
||||
Ok((cmd.run(client, config.chain_spec).map_err(Error::SubstrateCli), task_manager))
|
||||
})?)
|
||||
}
|
||||
},
|
||||
Some(Subcommand::ImportBlocks(cmd)) => {
|
||||
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
|
||||
let chain_spec = &runner.config().chain_spec;
|
||||
@ -243,17 +228,15 @@ pub fn run() -> Result<()> {
|
||||
set_ss58_version(chain_spec);
|
||||
|
||||
Ok(runner.async_run(|mut config| {
|
||||
let (client, _, import_queue, task_manager) = service::new_chain_ops(&mut config)?;
|
||||
Ok((
|
||||
cmd.run(client, import_queue).map_err(Error::SubstrateCli),
|
||||
task_manager,
|
||||
))
|
||||
let ( client, _, import_queue, task_manager ) =
|
||||
service::new_chain_ops(&mut config)?;
|
||||
Ok((cmd.run(client, import_queue).map_err(Error::SubstrateCli), task_manager))
|
||||
})?)
|
||||
}
|
||||
},
|
||||
Some(Subcommand::PurgeChain(cmd)) => {
|
||||
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
|
||||
Ok(runner.sync_run(|config| cmd.run(config.database))?)
|
||||
}
|
||||
},
|
||||
Some(Subcommand::Revert(cmd)) => {
|
||||
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
|
||||
let chain_spec = &runner.config().chain_spec;
|
||||
@ -261,59 +244,62 @@ pub fn run() -> Result<()> {
|
||||
set_ss58_version(chain_spec);
|
||||
|
||||
Ok(runner.async_run(|mut config| {
|
||||
let (client, backend, _, task_manager) = service::new_chain_ops(&mut config)?;
|
||||
let (client, backend, _, task_manager) =
|
||||
service::new_chain_ops(&mut config)?;
|
||||
|
||||
let aux_revert = Box::new(|client, backend, blocks| {
|
||||
service::revert_backend(client, backend, blocks).map_err(|err| match err {
|
||||
service::Error::Blockchain(err) => err.into(),
|
||||
err => sc_cli::Error::Application(err.into()),
|
||||
service::revert_backend(client, backend, blocks).map_err(|err| {
|
||||
match err {
|
||||
service::Error::Blockchain(err) => err.into(),
|
||||
err => sc_cli::Error::Application(err.into()),
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
Ok((
|
||||
cmd.run(client, backend, Some(aux_revert))
|
||||
.map_err(Error::SubstrateCli),
|
||||
task_manager,
|
||||
cmd.run(client, backend, Some(aux_revert)).map_err(Error::SubstrateCli),
|
||||
task_manager
|
||||
))
|
||||
})?)
|
||||
}
|
||||
},
|
||||
Some(Subcommand::Benchmark(cmd)) => {
|
||||
let runner = cli.create_runner(cmd).map_err(Error::SubstrateCli)?;
|
||||
let chain_spec = &runner.config().chain_spec;
|
||||
|
||||
match cmd {
|
||||
#[cfg(not(feature = "runtime-benchmarks"))]
|
||||
BenchmarkCmd::Storage(_) => {
|
||||
BenchmarkCmd::Storage(_) =>
|
||||
return Err(sc_cli::Error::Input(
|
||||
"Compile with `--feature=runtime-benchmarks \
|
||||
to enable storage benchmarks."
|
||||
.into(),
|
||||
)
|
||||
.into())
|
||||
}
|
||||
to enable storage benchmarks.".into()
|
||||
).into()),
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
BenchmarkCmd::Storage(cmd) => runner.sync_run(|mut config| {
|
||||
let (client, backend, _, _) = service::new_chain_ops(&mut config)?;
|
||||
let (client, backend, _, _,) =
|
||||
service::new_chain_ops(&mut config)?;
|
||||
let db = backend.expose_db();
|
||||
let storage = backend.expose_storage();
|
||||
|
||||
cmd.run(config, client.clone(), db, storage)
|
||||
.map_err(Error::SubstrateCli)
|
||||
cmd.run(config, client.clone(), db, storage).map_err(Error::SubstrateCli)
|
||||
}),
|
||||
BenchmarkCmd::Block(cmd) => runner.sync_run(|mut config| {
|
||||
let (client, _, _, _) = service::new_chain_ops(&mut config)?;
|
||||
let (client, _, _, _,) =
|
||||
service::new_chain_ops(&mut config)?;
|
||||
cmd.run(client.clone()).map_err(Error::SubstrateCli)
|
||||
}),
|
||||
// These commands are very similar and can be handled in nearly the same way
|
||||
BenchmarkCmd::Extrinsic(_) | BenchmarkCmd::Overhead(_) => {
|
||||
BenchmarkCmd::Extrinsic(_) | BenchmarkCmd::Overhead(_) =>
|
||||
runner.sync_run(|mut config| {
|
||||
let (client, _, _, _) = service::new_chain_ops(&mut config)?;
|
||||
let (client, _, _, _) =
|
||||
service::new_chain_ops(&mut config)?;
|
||||
|
||||
let inherent_data = benchmark_inherent_data()
|
||||
.map_err(|e| format!("generating inherent data: {:?}", e))?;
|
||||
|
||||
let remark_builder =
|
||||
RemarkBuilder::new(client.clone(), config.chain_spec.identify_chain());
|
||||
let remark_builder = RemarkBuilder::new(
|
||||
client.clone(),
|
||||
config.chain_spec.identify_chain(),
|
||||
);
|
||||
|
||||
match cmd {
|
||||
BenchmarkCmd::Extrinsic(cmd) => {
|
||||
@ -330,20 +316,17 @@ pub fn run() -> Result<()> {
|
||||
|
||||
cmd.run(client.clone(), inherent_data, Vec::new(), &ext_factory)
|
||||
.map_err(Error::SubstrateCli)
|
||||
}
|
||||
BenchmarkCmd::Overhead(cmd) => cmd
|
||||
.run(
|
||||
config,
|
||||
client.clone(),
|
||||
inherent_data,
|
||||
Vec::new(),
|
||||
&remark_builder,
|
||||
)
|
||||
.map_err(Error::SubstrateCli),
|
||||
},
|
||||
BenchmarkCmd::Overhead(cmd) => cmd.run(
|
||||
config,
|
||||
client.clone(),
|
||||
inherent_data,
|
||||
Vec::new(),
|
||||
&remark_builder,
|
||||
).map_err(Error::SubstrateCli),
|
||||
_ => unreachable!("Ensured by the outside match; qed"),
|
||||
}
|
||||
})
|
||||
}
|
||||
}),
|
||||
BenchmarkCmd::Pallet(cmd) => {
|
||||
set_ss58_version(chain_spec);
|
||||
|
||||
@ -351,36 +334,30 @@ pub fn run() -> Result<()> {
|
||||
runner.sync_run(|config| {
|
||||
cmd.run_with_spec::<sp_runtime::traits::HashingFor<service::Block>, ()>(
|
||||
Some(config.chain_spec),
|
||||
)
|
||||
.map_err(|e| Error::SubstrateCli(e))
|
||||
).map_err(|e| Error::SubstrateCli(e))
|
||||
})
|
||||
} else {
|
||||
Err(sc_cli::Error::Input(
|
||||
"Benchmarking wasn't enabled when building the node. \
|
||||
You can enable it with `--features=runtime-benchmarks`."
|
||||
.into(),
|
||||
)
|
||||
.into())
|
||||
You can enable it with `--features=runtime-benchmarks`.".into()
|
||||
).into())
|
||||
}
|
||||
}
|
||||
},
|
||||
BenchmarkCmd::Machine(cmd) => runner.sync_run(|config| {
|
||||
cmd.run(
|
||||
&config,
|
||||
ghost_machine_primitives::GHOST_NODE_REFERENCE_HARDWARE.clone(),
|
||||
)
|
||||
.map_err(Error::SubstrateCli)
|
||||
cmd.run(&config, ghost_machine_primitives::GHOST_NODE_REFERENCE_HARDWARE.clone())
|
||||
.map_err(Error::SubstrateCli)
|
||||
}),
|
||||
// Note: this allows to implement additional new benchmark
|
||||
// commands.
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => Err(Error::CommandNotImplemented),
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?),
|
||||
Some(Subcommand::ChainInfo(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
Ok(runner.sync_run(|config| cmd.run::<service::Block>(&config))?)
|
||||
}
|
||||
},
|
||||
}?;
|
||||
|
||||
#[cfg(feature = "pyroscope")]
|
||||
|
0
cli/src/error.rs
Normal file → Executable file
4
cli/src/lib.rs
Normal file → Executable file
@ -6,7 +6,9 @@ mod command;
|
||||
mod error;
|
||||
|
||||
#[cfg(feature = "service")]
|
||||
pub use service::{self, Block, CoreApi, IdentifyVariant, ProvideRuntimeApi, TFullClient};
|
||||
pub use service::{
|
||||
self, Block, CoreApi, IdentifyVariant, ProvideRuntimeApi, TFullClient,
|
||||
};
|
||||
|
||||
#[cfg(feature = "cli")]
|
||||
pub use cli::*;
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ghost-client-cli"
|
||||
version = "0.1.4"
|
||||
version = "0.1.3"
|
||||
description = "Ghost CLI interface"
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
|
@ -3,10 +3,13 @@
|
||||
use bip39::Mnemonic;
|
||||
use clap::Parser;
|
||||
use itertools::Itertools;
|
||||
use sc_cli::{with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams, OutputTypeFlag};
|
||||
use sc_cli::{
|
||||
with_crypto_scheme, KeystoreParams, OutputTypeFlag,
|
||||
CryptoSchemeFlag, Error,
|
||||
};
|
||||
|
||||
use crate::commands::utils::print_from_uri;
|
||||
use crate::params::NetworkSchemeFlag;
|
||||
use crate::commands::utils::print_from_uri;
|
||||
|
||||
/// The `generate` command
|
||||
#[derive(Debug, Clone, Parser)]
|
||||
@ -14,58 +17,58 @@ use crate::params::NetworkSchemeFlag;
|
||||
pub struct GenerateCmd {
|
||||
/// The number of words in the phrase to generate. One of 12 (default),
|
||||
/// 15, 18, 21 and 24.
|
||||
#[arg(short = 'w', long, value_name = "WORDS")]
|
||||
words: Option<usize>,
|
||||
#[arg(short = 'w', long, value_name = "WORDS")]
|
||||
words: Option<usize>,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub keystore_params: KeystoreParams,
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub keystore_params: KeystoreParams,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub network_scheme: NetworkSchemeFlag,
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub network_scheme: NetworkSchemeFlag,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub output_scheme: OutputTypeFlag,
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub output_scheme: OutputTypeFlag,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub crypto_scheme: CryptoSchemeFlag,
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub crypto_scheme: CryptoSchemeFlag,
|
||||
}
|
||||
|
||||
impl GenerateCmd {
|
||||
/// Run the command
|
||||
pub fn run(&self) -> Result<(), Error> {
|
||||
let words = match self.words {
|
||||
/// Run the command
|
||||
pub fn run(&self) -> Result<(), Error> {
|
||||
let words = match self.words {
|
||||
Some(words_count) if [12, 15, 18, 21, 24].contains(&words_count) => Ok(words_count),
|
||||
Some(_) => Err(Error::Input(
|
||||
"Invalid number of words given for phrase: must be 12/15/18/21/24".into(),
|
||||
)),
|
||||
None => Ok(12),
|
||||
}?;
|
||||
let mnemonic = Mnemonic::generate(words)
|
||||
}?;
|
||||
let mnemonic = Mnemonic::generate(words)
|
||||
.map_err(|e| Error::Input(format!("Mnemonic generation failed: {e}").into()))?;
|
||||
let password = self.keystore_params.read_password()?;
|
||||
let output = self.output_scheme.output_type;
|
||||
let password = self.keystore_params.read_password()?;
|
||||
let output = self.output_scheme.output_type;
|
||||
|
||||
let phrase = mnemonic.words().join(" ");
|
||||
|
||||
with_crypto_scheme!(
|
||||
self.crypto_scheme.scheme,
|
||||
print_from_uri(&phrase, password, self.network_scheme.network, output)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
with_crypto_scheme!(
|
||||
self.crypto_scheme.scheme,
|
||||
print_from_uri(&phrase, password, self.network_scheme.network, output)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn generate() {
|
||||
let generate = GenerateCmd::parse_from(&["generate", "--password", "12345"]);
|
||||
assert!(generate.run().is_ok())
|
||||
}
|
||||
#[test]
|
||||
fn generate() {
|
||||
let generate = GenerateCmd::parse_from(&["generate", "--password", "12345"]);
|
||||
assert!(generate.run().is_ok())
|
||||
}
|
||||
}
|
||||
|
@ -1,101 +1,102 @@
|
||||
//! Implementation of the `inspect` subcommand
|
||||
|
||||
use crate::commands::utils::{print_from_public, print_from_uri};
|
||||
use crate::params::NetworkSchemeFlag;
|
||||
use clap::Parser;
|
||||
use sc_cli::{
|
||||
utils::read_uri, with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams, OutputTypeFlag,
|
||||
};
|
||||
use sp_core::crypto::{ExposeSecret, SecretString, SecretUri, Ss58Codec};
|
||||
use std::str::FromStr;
|
||||
use sc_cli::{
|
||||
with_crypto_scheme, KeystoreParams, OutputTypeFlag, CryptoSchemeFlag, Error,
|
||||
utils::read_uri,
|
||||
};
|
||||
use crate::params::NetworkSchemeFlag;
|
||||
use crate::commands::utils::{print_from_public, print_from_uri};
|
||||
|
||||
/// The `inspect` command
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(
|
||||
name = "inspect",
|
||||
about = "Gets a public key and a SS58 address from the provided Secret URI"
|
||||
name = "inspect",
|
||||
about = "Gets a public key and a SS58 address from the provided Secret URI"
|
||||
)]
|
||||
pub struct InspectKeyCmd {
|
||||
/// A Key URI to be inspected. May be a secret seed, secret URI
|
||||
/// (with derivation paths and password), SS58, public URI or a hex encoded public key.
|
||||
///
|
||||
/// If it is a hex encoded public key, `--public` needs to be given as argument.
|
||||
///
|
||||
/// If the given value is a file, the file content will be used
|
||||
/// as URI.
|
||||
///
|
||||
/// If omitted, you will be prompted for the URI.
|
||||
uri: Option<String>,
|
||||
/// A Key URI to be inspected. May be a secret seed, secret URI
|
||||
/// (with derivation paths and password), SS58, public URI or a hex encoded public key.
|
||||
///
|
||||
/// If it is a hex encoded public key, `--public` needs to be given as argument.
|
||||
///
|
||||
/// If the given value is a file, the file content will be used
|
||||
/// as URI.
|
||||
///
|
||||
/// If omitted, you will be prompted for the URI.
|
||||
uri: Option<String>,
|
||||
|
||||
/// Is the given `uri` a hex encoded public key?
|
||||
#[arg(long)]
|
||||
public: bool,
|
||||
/// Is the given `uri` a hex encoded public key?
|
||||
#[arg(long)]
|
||||
public: bool,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub keystore_params: KeystoreParams,
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub keystore_params: KeystoreParams,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub network_scheme: NetworkSchemeFlag,
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub network_scheme: NetworkSchemeFlag,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub output_scheme: OutputTypeFlag,
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub output_scheme: OutputTypeFlag,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub crypto_scheme: CryptoSchemeFlag,
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
pub crypto_scheme: CryptoSchemeFlag,
|
||||
|
||||
/// Expect that `--uri` has the given public key/account-id.
|
||||
///
|
||||
/// If `--uri` has any derivations, the public key is checked against the base `uri`, i.e. the
|
||||
/// `uri` without any derivation applied. However, if `uri` has a password or there is one
|
||||
/// given by `--password`, it will be used to decrypt `uri` before comparing the public
|
||||
/// key/account-id.
|
||||
///
|
||||
/// If there is no derivation in `--uri`, the public key will be checked against the public key
|
||||
/// of `--uri` directly.
|
||||
#[arg(long, conflicts_with = "public")]
|
||||
pub expect_public: Option<String>,
|
||||
/// Expect that `--uri` has the given public key/account-id.
|
||||
///
|
||||
/// If `--uri` has any derivations, the public key is checked against the base `uri`, i.e. the
|
||||
/// `uri` without any derivation applied. However, if `uri` has a password or there is one
|
||||
/// given by `--password`, it will be used to decrypt `uri` before comparing the public
|
||||
/// key/account-id.
|
||||
///
|
||||
/// If there is no derivation in `--uri`, the public key will be checked against the public key
|
||||
/// of `--uri` directly.
|
||||
#[arg(long, conflicts_with = "public")]
|
||||
pub expect_public: Option<String>,
|
||||
}
|
||||
|
||||
impl InspectKeyCmd {
|
||||
/// Run the command
|
||||
pub fn run(&self) -> Result<(), Error> {
|
||||
let uri = read_uri(self.uri.as_ref())?;
|
||||
let password = self.keystore_params.read_password()?;
|
||||
/// Run the command
|
||||
pub fn run(&self) -> Result<(), Error> {
|
||||
let uri = read_uri(self.uri.as_ref())?;
|
||||
let password = self.keystore_params.read_password()?;
|
||||
|
||||
if self.public {
|
||||
with_crypto_scheme!(
|
||||
self.crypto_scheme.scheme,
|
||||
print_from_public(
|
||||
&uri,
|
||||
self.network_scheme.network,
|
||||
self.output_scheme.output_type,
|
||||
)
|
||||
)?;
|
||||
} else {
|
||||
if let Some(ref expect_public) = self.expect_public {
|
||||
with_crypto_scheme!(
|
||||
self.crypto_scheme.scheme,
|
||||
expect_public_from_phrase(expect_public, &uri, password.as_ref())
|
||||
)?;
|
||||
}
|
||||
if self.public {
|
||||
with_crypto_scheme!(
|
||||
self.crypto_scheme.scheme,
|
||||
print_from_public(
|
||||
&uri,
|
||||
self.network_scheme.network,
|
||||
self.output_scheme.output_type,
|
||||
)
|
||||
)?;
|
||||
} else {
|
||||
if let Some(ref expect_public) = self.expect_public {
|
||||
with_crypto_scheme!(
|
||||
self.crypto_scheme.scheme,
|
||||
expect_public_from_phrase(expect_public, &uri, password.as_ref())
|
||||
)?;
|
||||
}
|
||||
|
||||
with_crypto_scheme!(
|
||||
self.crypto_scheme.scheme,
|
||||
print_from_uri(
|
||||
&uri,
|
||||
password,
|
||||
self.network_scheme.network,
|
||||
self.output_scheme.output_type,
|
||||
)
|
||||
);
|
||||
}
|
||||
with_crypto_scheme!(
|
||||
self.crypto_scheme.scheme,
|
||||
print_from_uri(
|
||||
&uri,
|
||||
password,
|
||||
self.network_scheme.network,
|
||||
self.output_scheme.output_type,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that `expect_public` is the public key of `suri`.
|
||||
@ -105,156 +106,148 @@ impl InspectKeyCmd {
|
||||
///
|
||||
/// Returns an error if the public key does not match.
|
||||
fn expect_public_from_phrase<Pair: sp_core::Pair>(
|
||||
expect_public: &str,
|
||||
suri: &str,
|
||||
password: Option<&SecretString>,
|
||||
expect_public: &str,
|
||||
suri: &str,
|
||||
password: Option<&SecretString>,
|
||||
) -> Result<(), Error> {
|
||||
let secret_uri = SecretUri::from_str(suri).map_err(|e| format!("{:?}", e))?;
|
||||
let expected_public = if let Some(public) = expect_public.strip_prefix("0x") {
|
||||
let hex_public = array_bytes::hex2bytes(public)
|
||||
.map_err(|_| format!("Invalid expected public key hex: `{}`", expect_public))?;
|
||||
Pair::Public::try_from(&hex_public)
|
||||
.map_err(|_| format!("Invalid expected public key: `{}`", expect_public))?
|
||||
} else {
|
||||
Pair::Public::from_string_with_version(expect_public)
|
||||
.map_err(|_| format!("Invalid expected account id: `{}`", expect_public))?
|
||||
.0
|
||||
};
|
||||
let secret_uri = SecretUri::from_str(suri).map_err(|e| format!("{:?}", e))?;
|
||||
let expected_public = if let Some(public) = expect_public.strip_prefix("0x") {
|
||||
let hex_public = array_bytes::hex2bytes(public)
|
||||
.map_err(|_| format!("Invalid expected public key hex: `{}`", expect_public))?;
|
||||
Pair::Public::try_from(&hex_public)
|
||||
.map_err(|_| format!("Invalid expected public key: `{}`", expect_public))?
|
||||
} else {
|
||||
Pair::Public::from_string_with_version(expect_public)
|
||||
.map_err(|_| format!("Invalid expected account id: `{}`", expect_public))?
|
||||
.0
|
||||
};
|
||||
|
||||
let pair = Pair::from_string_with_seed(
|
||||
secret_uri.phrase.expose_secret().as_str(),
|
||||
password
|
||||
.or_else(|| secret_uri.password.as_ref())
|
||||
.map(|p| p.expose_secret().as_str()),
|
||||
)
|
||||
.map_err(|_| format!("Invalid secret uri: {}", suri))?
|
||||
.0;
|
||||
let pair = Pair::from_string_with_seed(
|
||||
secret_uri.phrase.expose_secret().as_str(),
|
||||
password
|
||||
.or_else(|| secret_uri.password.as_ref())
|
||||
.map(|p| p.expose_secret().as_str()),
|
||||
)
|
||||
.map_err(|_| format!("Invalid secret uri: {}", suri))?
|
||||
.0;
|
||||
|
||||
if pair.public() == expected_public {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(format!("Expected public ({}) key does not match.", expect_public).into())
|
||||
}
|
||||
if pair.public() == expected_public {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(format!("Expected public ({}) key does not match.", expect_public).into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sp_core::crypto::{ByteArray, Pair};
|
||||
use sp_runtime::traits::IdentifyAccount;
|
||||
use super::*;
|
||||
use sp_core::crypto::{ByteArray, Pair};
|
||||
use sp_runtime::traits::IdentifyAccount;
|
||||
|
||||
#[test]
|
||||
fn inspect() {
|
||||
let words =
|
||||
"remember fiber forum demise paper uniform squirrel feel access exclude casual effort";
|
||||
let seed = "0xad1fb77243b536b90cfe5f0d351ab1b1ac40e3890b41dc64f766ee56340cfca5";
|
||||
#[test]
|
||||
fn inspect() {
|
||||
let words =
|
||||
"remember fiber forum demise paper uniform squirrel feel access exclude casual effort";
|
||||
let seed = "0xad1fb77243b536b90cfe5f0d351ab1b1ac40e3890b41dc64f766ee56340cfca5";
|
||||
|
||||
let inspect = InspectKeyCmd::parse_from(&["inspect-key", words, "--password", "12345"]);
|
||||
assert!(inspect.run().is_ok());
|
||||
let inspect = InspectKeyCmd::parse_from(&["inspect-key", words, "--password", "12345"]);
|
||||
assert!(inspect.run().is_ok());
|
||||
|
||||
let inspect = InspectKeyCmd::parse_from(&["inspect-key", seed]);
|
||||
assert!(inspect.run().is_ok());
|
||||
}
|
||||
let inspect = InspectKeyCmd::parse_from(&["inspect-key", seed]);
|
||||
assert!(inspect.run().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inspect_public_key() {
|
||||
let public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069";
|
||||
#[test]
|
||||
fn inspect_public_key() {
|
||||
let public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069";
|
||||
|
||||
let inspect = InspectKeyCmd::parse_from(&["inspect-key", "--public", public]);
|
||||
assert!(inspect.run().is_ok());
|
||||
}
|
||||
let inspect = InspectKeyCmd::parse_from(&["inspect-key", "--public", public]);
|
||||
assert!(inspect.run().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inspect_with_expected_public_key() {
|
||||
let check_cmd = |seed, expected_public, success| {
|
||||
let inspect = InspectKeyCmd::parse_from(&[
|
||||
"inspect-key",
|
||||
"--expect-public",
|
||||
expected_public,
|
||||
seed,
|
||||
]);
|
||||
let res = inspect.run();
|
||||
#[test]
|
||||
fn inspect_with_expected_public_key() {
|
||||
let check_cmd = |seed, expected_public, success| {
|
||||
let inspect = InspectKeyCmd::parse_from(&[
|
||||
"inspect-key",
|
||||
"--expect-public",
|
||||
expected_public,
|
||||
seed,
|
||||
]);
|
||||
let res = inspect.run();
|
||||
|
||||
if success {
|
||||
assert!(res.is_ok());
|
||||
} else {
|
||||
assert!(res.unwrap_err().to_string().contains(&format!(
|
||||
"Expected public ({}) key does not match.",
|
||||
expected_public
|
||||
)));
|
||||
}
|
||||
};
|
||||
if success {
|
||||
assert!(res.is_ok());
|
||||
} else {
|
||||
assert!(res.unwrap_err().to_string().contains(&format!(
|
||||
"Expected public ({}) key does not match.",
|
||||
expected_public
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
let seed =
|
||||
"remember fiber forum demise paper uniform squirrel feel access exclude casual effort";
|
||||
let invalid_public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069";
|
||||
let valid_public = sp_core::sr25519::Pair::from_string_with_seed(seed, None)
|
||||
.expect("Valid")
|
||||
.0
|
||||
.public();
|
||||
let valid_public_hex = array_bytes::bytes2hex("0x", valid_public.as_slice());
|
||||
let valid_accountid = format!("{}", valid_public.into_account());
|
||||
let seed =
|
||||
"remember fiber forum demise paper uniform squirrel feel access exclude casual effort";
|
||||
let invalid_public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069";
|
||||
let valid_public = sp_core::sr25519::Pair::from_string_with_seed(seed, None)
|
||||
.expect("Valid")
|
||||
.0
|
||||
.public();
|
||||
let valid_public_hex = array_bytes::bytes2hex("0x", valid_public.as_slice());
|
||||
let valid_accountid = format!("{}", valid_public.into_account());
|
||||
|
||||
// It should fail with the invalid public key
|
||||
check_cmd(seed, invalid_public, false);
|
||||
// It should fail with the invalid public key
|
||||
check_cmd(seed, invalid_public, false);
|
||||
|
||||
// It should work with the valid public key & account id
|
||||
check_cmd(seed, &valid_public_hex, true);
|
||||
check_cmd(seed, &valid_accountid, true);
|
||||
// It should work with the valid public key & account id
|
||||
check_cmd(seed, &valid_public_hex, true);
|
||||
check_cmd(seed, &valid_accountid, true);
|
||||
|
||||
let password = "test12245";
|
||||
let seed_with_password = format!("{}///{}", seed, password);
|
||||
let valid_public_with_password =
|
||||
sp_core::sr25519::Pair::from_string_with_seed(&seed_with_password, Some(password))
|
||||
.expect("Valid")
|
||||
.0
|
||||
.public();
|
||||
let valid_public_hex_with_password =
|
||||
array_bytes::bytes2hex("0x", valid_public_with_password.as_slice());
|
||||
let valid_accountid_with_password =
|
||||
format!("{}", &valid_public_with_password.into_account());
|
||||
let password = "test12245";
|
||||
let seed_with_password = format!("{}///{}", seed, password);
|
||||
let valid_public_with_password =
|
||||
sp_core::sr25519::Pair::from_string_with_seed(&seed_with_password, Some(password))
|
||||
.expect("Valid")
|
||||
.0
|
||||
.public();
|
||||
let valid_public_hex_with_password =
|
||||
array_bytes::bytes2hex("0x", valid_public_with_password.as_slice());
|
||||
let valid_accountid_with_password =
|
||||
format!("{}", &valid_public_with_password.into_account());
|
||||
|
||||
// Only the public key that corresponds to the seed with password should be accepted.
|
||||
check_cmd(&seed_with_password, &valid_public_hex, false);
|
||||
check_cmd(&seed_with_password, &valid_accountid, false);
|
||||
// Only the public key that corresponds to the seed with password should be accepted.
|
||||
check_cmd(&seed_with_password, &valid_public_hex, false);
|
||||
check_cmd(&seed_with_password, &valid_accountid, false);
|
||||
|
||||
check_cmd(&seed_with_password, &valid_public_hex_with_password, true);
|
||||
check_cmd(&seed_with_password, &valid_accountid_with_password, true);
|
||||
check_cmd(&seed_with_password, &valid_public_hex_with_password, true);
|
||||
check_cmd(&seed_with_password, &valid_accountid_with_password, true);
|
||||
|
||||
let seed_with_password_and_derivation = format!("{}//test//account///{}", seed, password);
|
||||
let seed_with_password_and_derivation = format!("{}//test//account///{}", seed, password);
|
||||
|
||||
let valid_public_with_password_and_derivation =
|
||||
sp_core::sr25519::Pair::from_string_with_seed(
|
||||
&seed_with_password_and_derivation,
|
||||
Some(password),
|
||||
)
|
||||
.expect("Valid")
|
||||
.0
|
||||
.public();
|
||||
let valid_public_hex_with_password_and_derivation =
|
||||
array_bytes::bytes2hex("0x", valid_public_with_password_and_derivation.as_slice());
|
||||
let valid_public_with_password_and_derivation =
|
||||
sp_core::sr25519::Pair::from_string_with_seed(
|
||||
&seed_with_password_and_derivation,
|
||||
Some(password),
|
||||
)
|
||||
.expect("Valid")
|
||||
.0
|
||||
.public();
|
||||
let valid_public_hex_with_password_and_derivation =
|
||||
array_bytes::bytes2hex("0x", valid_public_with_password_and_derivation.as_slice());
|
||||
|
||||
// They should still be valid, because we check the base secret key.
|
||||
check_cmd(
|
||||
&seed_with_password_and_derivation,
|
||||
&valid_public_hex_with_password,
|
||||
true,
|
||||
);
|
||||
check_cmd(
|
||||
&seed_with_password_and_derivation,
|
||||
&valid_accountid_with_password,
|
||||
true,
|
||||
);
|
||||
// They should still be valid, because we check the base secret key.
|
||||
check_cmd(&seed_with_password_and_derivation, &valid_public_hex_with_password, true);
|
||||
check_cmd(&seed_with_password_and_derivation, &valid_accountid_with_password, true);
|
||||
|
||||
// And these should be invalid.
|
||||
check_cmd(&seed_with_password_and_derivation, &valid_public_hex, false);
|
||||
check_cmd(&seed_with_password_and_derivation, &valid_accountid, false);
|
||||
// And these should be invalid.
|
||||
check_cmd(&seed_with_password_and_derivation, &valid_public_hex, false);
|
||||
check_cmd(&seed_with_password_and_derivation, &valid_accountid, false);
|
||||
|
||||
// The public of the derived account should fail.
|
||||
check_cmd(
|
||||
&seed_with_password_and_derivation,
|
||||
&valid_public_hex_with_password_and_derivation,
|
||||
false,
|
||||
);
|
||||
}
|
||||
// The public of the derived account should fail.
|
||||
check_cmd(
|
||||
&seed_with_password_and_derivation,
|
||||
&valid_public_hex_with_password_and_derivation,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,37 +1,40 @@
|
||||
//! Key related CLI utilities
|
||||
|
||||
use super::{generate::GenerateCmd, inspect_key::InspectKeyCmd};
|
||||
use sc_cli::{Error, GenerateKeyCmdCommon, InsertKeyCmd, InspectNodeKeyCmd, SubstrateCli};
|
||||
use sc_cli::{
|
||||
GenerateKeyCmdCommon, InsertKeyCmd, InspectNodeKeyCmd, Error,
|
||||
SubstrateCli,
|
||||
};
|
||||
|
||||
/// Key utilities for the cli.
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
pub enum KeySubcommand {
|
||||
/// Generate a random node key, write it to a file or stdout and write the
|
||||
/// corresponding peer-id to stderr
|
||||
GenerateNodeKey(GenerateKeyCmdCommon),
|
||||
/// Generate a random node key, write it to a file or stdout and write the
|
||||
/// corresponding peer-id to stderr
|
||||
GenerateNodeKey(GenerateKeyCmdCommon),
|
||||
|
||||
/// Generate a Substrate-based random account
|
||||
Generate(GenerateCmd),
|
||||
/// Generate a Substrate-based random account
|
||||
Generate(GenerateCmd),
|
||||
|
||||
/// Gets a public key and a SS58 address from the provided Secret URI
|
||||
Inspect(InspectKeyCmd),
|
||||
/// Gets a public key and a SS58 address from the provided Secret URI
|
||||
Inspect(InspectKeyCmd),
|
||||
|
||||
/// Load a node key from a file or stdin and print the corresponding peer-id
|
||||
InspectNodeKey(InspectNodeKeyCmd),
|
||||
/// Load a node key from a file or stdin and print the corresponding peer-id
|
||||
InspectNodeKey(InspectNodeKeyCmd),
|
||||
|
||||
/// Insert a key to the keystore of a node.
|
||||
Insert(InsertKeyCmd),
|
||||
/// Insert a key to the keystore of a node.
|
||||
Insert(InsertKeyCmd),
|
||||
}
|
||||
|
||||
impl KeySubcommand {
|
||||
/// run the key subcommands
|
||||
pub fn run<C: SubstrateCli>(&self, cli: &C) -> Result<(), Error> {
|
||||
match self {
|
||||
KeySubcommand::GenerateNodeKey(cmd) => cmd.run(),
|
||||
KeySubcommand::Generate(cmd) => cmd.run(),
|
||||
KeySubcommand::Inspect(cmd) => cmd.run(),
|
||||
KeySubcommand::Insert(cmd) => cmd.run(cli),
|
||||
KeySubcommand::InspectNodeKey(cmd) => cmd.run(),
|
||||
}
|
||||
}
|
||||
/// run the key subcommands
|
||||
pub fn run<C: SubstrateCli>(&self, cli: &C) -> Result<(), Error> {
|
||||
match self {
|
||||
KeySubcommand::GenerateNodeKey(cmd) => cmd.run(),
|
||||
KeySubcommand::Generate(cmd) => cmd.run(),
|
||||
KeySubcommand::Inspect(cmd) => cmd.run(),
|
||||
KeySubcommand::Insert(cmd) => cmd.run(cli),
|
||||
KeySubcommand::InspectNodeKey(cmd) => cmd.run(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,11 @@
|
||||
mod generate;
|
||||
mod inspect_key;
|
||||
mod key;
|
||||
mod utils;
|
||||
mod generate;
|
||||
mod vanity;
|
||||
mod inspect_key;
|
||||
mod utils;
|
||||
|
||||
pub use self::{
|
||||
key::KeySubcommand, vanity::VanityCmd, inspect_key::InspectKeyCmd,
|
||||
generate::GenerateCmd,
|
||||
inspect_key::InspectKeyCmd,
|
||||
key::KeySubcommand,
|
||||
utils::{print_from_public, print_from_uri, unwrap_or_default_ss58_name},
|
||||
vanity::VanityCmd,
|
||||
utils::{unwrap_or_default_ss58_name, print_from_uri, print_from_public},
|
||||
};
|
||||
|
@ -1,206 +1,194 @@
|
||||
use sc_cli::{
|
||||
utils::{PublicFor, SeedFor},
|
||||
OutputType,
|
||||
};
|
||||
use serde_json::json;
|
||||
use sc_cli::{
|
||||
OutputType,
|
||||
utils::{PublicFor, SeedFor},
|
||||
};
|
||||
use sp_runtime::{traits::IdentifyAccount, MultiSigner};
|
||||
use sp_core::{
|
||||
crypto::{
|
||||
unwrap_or_default_ss58_version, ExposeSecret, SecretString, Ss58AddressFormat, Ss58Codec,
|
||||
unwrap_or_default_ss58_version,
|
||||
Ss58Codec, ExposeSecret, Ss58AddressFormat, SecretString,
|
||||
},
|
||||
hexdisplay::HexDisplay,
|
||||
};
|
||||
use sp_runtime::{traits::IdentifyAccount, MultiSigner};
|
||||
|
||||
pub fn print_from_uri<Pair>(
|
||||
uri: &str,
|
||||
password: Option<SecretString>,
|
||||
network_override: Option<Ss58AddressFormat>,
|
||||
output: OutputType,
|
||||
uri: &str,
|
||||
password: Option<SecretString>,
|
||||
network_override: Option<Ss58AddressFormat>,
|
||||
output: OutputType,
|
||||
) where
|
||||
Pair: sp_core::Pair,
|
||||
Pair::Public: Into<MultiSigner>,
|
||||
Pair: sp_core::Pair,
|
||||
Pair::Public: Into<MultiSigner>,
|
||||
{
|
||||
let password = password.as_ref().map(|s| s.expose_secret().as_str());
|
||||
let network_id = unwrap_or_default_ss58_name(network_override);
|
||||
let password = password.as_ref().map(|s| s.expose_secret().as_str());
|
||||
let network_id = unwrap_or_default_ss58_name(network_override);
|
||||
|
||||
if let Ok((pair, seed)) = Pair::from_phrase(uri, password) {
|
||||
let public_key = pair.public();
|
||||
let network_override = unwrap_or_default_ss58_version(network_override);
|
||||
if let Ok((pair, seed)) = Pair::from_phrase(uri, password) {
|
||||
let public_key = pair.public();
|
||||
let network_override = unwrap_or_default_ss58_version(network_override);
|
||||
|
||||
match output {
|
||||
OutputType::Json => {
|
||||
let json = json!({
|
||||
"secretPhrase": uri,
|
||||
"networkId": network_id,
|
||||
"secretSeed": format_seed::<Pair>(seed),
|
||||
"publicKey": format_public_key::<Pair>(public_key.clone()),
|
||||
"ss58PublicKey": public_key.to_ss58check_with_version(network_override),
|
||||
"accountId": format_account_id::<Pair>(public_key),
|
||||
"ss58Address": pair.public().into().into_account().to_ss58check_with_version(network_override),
|
||||
});
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&json).expect("Json pretty print failed")
|
||||
);
|
||||
}
|
||||
OutputType::Text => {
|
||||
println!(
|
||||
"Secret phrase: {}\n \
|
||||
match output {
|
||||
OutputType::Json => {
|
||||
let json = json!({
|
||||
"secretPhrase": uri,
|
||||
"networkId": network_id,
|
||||
"secretSeed": format_seed::<Pair>(seed),
|
||||
"publicKey": format_public_key::<Pair>(public_key.clone()),
|
||||
"ss58PublicKey": public_key.to_ss58check_with_version(network_override),
|
||||
"accountId": format_account_id::<Pair>(public_key),
|
||||
"ss58Address": pair.public().into().into_account().to_ss58check_with_version(network_override),
|
||||
});
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&json).expect("Json pretty print failed")
|
||||
);
|
||||
},
|
||||
OutputType::Text => {
|
||||
println!(
|
||||
"Secret phrase: {}\n \
|
||||
Network ID: {}\n \
|
||||
Secret seed: {}\n \
|
||||
Public key (hex): {}\n \
|
||||
Account ID: {}\n \
|
||||
Public key (SS58): {}\n \
|
||||
SS58 Address: {}",
|
||||
uri,
|
||||
network_id,
|
||||
format_seed::<Pair>(seed),
|
||||
format_public_key::<Pair>(public_key.clone()),
|
||||
format_account_id::<Pair>(public_key.clone()),
|
||||
public_key.to_ss58check_with_version(network_override),
|
||||
pair.public()
|
||||
.into()
|
||||
.into_account()
|
||||
.to_ss58check_with_version(network_override),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if let Ok((pair, seed)) = Pair::from_string_with_seed(uri, password) {
|
||||
let public_key = pair.public();
|
||||
let network_override = unwrap_or_default_ss58_version(network_override);
|
||||
uri,
|
||||
network_id,
|
||||
format_seed::<Pair>(seed),
|
||||
format_public_key::<Pair>(public_key.clone()),
|
||||
format_account_id::<Pair>(public_key.clone()),
|
||||
public_key.to_ss58check_with_version(network_override),
|
||||
pair.public().into().into_account().to_ss58check_with_version(network_override),
|
||||
);
|
||||
},
|
||||
}
|
||||
} else if let Ok((pair, seed)) = Pair::from_string_with_seed(uri, password) {
|
||||
let public_key = pair.public();
|
||||
let network_override = unwrap_or_default_ss58_version(network_override);
|
||||
|
||||
match output {
|
||||
OutputType::Json => {
|
||||
let json = json!({
|
||||
"secretKeyUri": uri,
|
||||
"networkId": network_id,
|
||||
"secretSeed": if let Some(seed) = seed { format_seed::<Pair>(seed) } else { "n/a".into() },
|
||||
"publicKey": format_public_key::<Pair>(public_key.clone()),
|
||||
"ss58PublicKey": public_key.to_ss58check_with_version(network_override),
|
||||
"accountId": format_account_id::<Pair>(public_key),
|
||||
"ss58Address": pair.public().into().into_account().to_ss58check_with_version(network_override),
|
||||
});
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&json).expect("Json pretty print failed")
|
||||
);
|
||||
}
|
||||
OutputType::Text => {
|
||||
println!(
|
||||
"Secret Key URI `{}` is account:\n \
|
||||
match output {
|
||||
OutputType::Json => {
|
||||
let json = json!({
|
||||
"secretKeyUri": uri,
|
||||
"networkId": network_id,
|
||||
"secretSeed": if let Some(seed) = seed { format_seed::<Pair>(seed) } else { "n/a".into() },
|
||||
"publicKey": format_public_key::<Pair>(public_key.clone()),
|
||||
"ss58PublicKey": public_key.to_ss58check_with_version(network_override),
|
||||
"accountId": format_account_id::<Pair>(public_key),
|
||||
"ss58Address": pair.public().into().into_account().to_ss58check_with_version(network_override),
|
||||
});
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&json).expect("Json pretty print failed")
|
||||
);
|
||||
},
|
||||
OutputType::Text => {
|
||||
println!(
|
||||
"Secret Key URI `{}` is account:\n \
|
||||
Network ID: {}\n \
|
||||
Secret seed: {}\n \
|
||||
Public key (hex): {}\n \
|
||||
Account ID: {}\n \
|
||||
Public key (SS58): {}\n \
|
||||
SS58 Address: {}",
|
||||
uri,
|
||||
network_id,
|
||||
if let Some(seed) = seed {
|
||||
format_seed::<Pair>(seed)
|
||||
} else {
|
||||
"n/a".into()
|
||||
},
|
||||
format_public_key::<Pair>(public_key.clone()),
|
||||
format_account_id::<Pair>(public_key.clone()),
|
||||
public_key.to_ss58check_with_version(network_override),
|
||||
pair.public()
|
||||
.into()
|
||||
.into_account()
|
||||
.to_ss58check_with_version(network_override),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if let Ok((public_key, network)) = Pair::Public::from_string_with_version(uri) {
|
||||
let network_override = network_override.unwrap_or(network);
|
||||
uri,
|
||||
network_id,
|
||||
if let Some(seed) = seed { format_seed::<Pair>(seed) } else { "n/a".into() },
|
||||
format_public_key::<Pair>(public_key.clone()),
|
||||
format_account_id::<Pair>(public_key.clone()),
|
||||
public_key.to_ss58check_with_version(network_override),
|
||||
pair.public().into().into_account().to_ss58check_with_version(network_override),
|
||||
);
|
||||
},
|
||||
}
|
||||
} else if let Ok((public_key, network)) = Pair::Public::from_string_with_version(uri) {
|
||||
let network_override = network_override.unwrap_or(network);
|
||||
|
||||
match output {
|
||||
OutputType::Json => {
|
||||
let json = json!({
|
||||
"publicKeyUri": uri,
|
||||
"networkId": String::from(network_override),
|
||||
"publicKey": format_public_key::<Pair>(public_key.clone()),
|
||||
"accountId": format_account_id::<Pair>(public_key.clone()),
|
||||
"ss58PublicKey": public_key.to_ss58check_with_version(network_override),
|
||||
"ss58Address": public_key.to_ss58check_with_version(network_override),
|
||||
});
|
||||
match output {
|
||||
OutputType::Json => {
|
||||
let json = json!({
|
||||
"publicKeyUri": uri,
|
||||
"networkId": String::from(network_override),
|
||||
"publicKey": format_public_key::<Pair>(public_key.clone()),
|
||||
"accountId": format_account_id::<Pair>(public_key.clone()),
|
||||
"ss58PublicKey": public_key.to_ss58check_with_version(network_override),
|
||||
"ss58Address": public_key.to_ss58check_with_version(network_override),
|
||||
});
|
||||
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&json).expect("Json pretty print failed")
|
||||
);
|
||||
}
|
||||
OutputType::Text => {
|
||||
println!(
|
||||
"Public Key URI `{}` is account:\n \
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&json).expect("Json pretty print failed")
|
||||
);
|
||||
},
|
||||
OutputType::Text => {
|
||||
println!(
|
||||
"Public Key URI `{}` is account:\n \
|
||||
Network ID/Version: {}\n \
|
||||
Public key (hex): {}\n \
|
||||
Account ID: {}\n \
|
||||
Public key (SS58): {}\n \
|
||||
SS58 Address: {}",
|
||||
uri,
|
||||
String::from(network_override),
|
||||
format_public_key::<Pair>(public_key.clone()),
|
||||
format_account_id::<Pair>(public_key.clone()),
|
||||
public_key.to_ss58check_with_version(network_override),
|
||||
public_key.to_ss58check_with_version(network_override),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("Invalid phrase/URI given");
|
||||
}
|
||||
uri,
|
||||
String::from(network_override),
|
||||
format_public_key::<Pair>(public_key.clone()),
|
||||
format_account_id::<Pair>(public_key.clone()),
|
||||
public_key.to_ss58check_with_version(network_override),
|
||||
public_key.to_ss58check_with_version(network_override),
|
||||
);
|
||||
},
|
||||
}
|
||||
} else {
|
||||
println!("Invalid phrase/URI given");
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to parse given `public` as hex encoded public key and print relevant information.
|
||||
pub fn print_from_public<Pair>(
|
||||
public_str: &str,
|
||||
network_override: Option<Ss58AddressFormat>,
|
||||
output: OutputType,
|
||||
public_str: &str,
|
||||
network_override: Option<Ss58AddressFormat>,
|
||||
output: OutputType,
|
||||
) -> Result<(), sc_cli::Error>
|
||||
where
|
||||
Pair: sp_core::Pair,
|
||||
Pair::Public: Into<MultiSigner>,
|
||||
Pair: sp_core::Pair,
|
||||
Pair::Public: Into<MultiSigner>,
|
||||
{
|
||||
let public = array_bytes::hex2bytes(public_str)?;
|
||||
let public = array_bytes::hex2bytes(public_str)?;
|
||||
|
||||
let public_key = Pair::Public::try_from(&public)
|
||||
.map_err(|_| "Failed to construct public key from given hex")?;
|
||||
let public_key = Pair::Public::try_from(&public)
|
||||
.map_err(|_| "Failed to construct public key from given hex")?;
|
||||
|
||||
let network_override = unwrap_or_default_ss58_version(network_override);
|
||||
let network_override = unwrap_or_default_ss58_version(network_override);
|
||||
|
||||
match output {
|
||||
OutputType::Json => {
|
||||
let json = json!({
|
||||
"networkId": String::from(network_override),
|
||||
"publicKey": format_public_key::<Pair>(public_key.clone()),
|
||||
"accountId": format_account_id::<Pair>(public_key.clone()),
|
||||
"ss58PublicKey": public_key.to_ss58check_with_version(network_override),
|
||||
"ss58Address": public_key.to_ss58check_with_version(network_override),
|
||||
});
|
||||
match output {
|
||||
OutputType::Json => {
|
||||
let json = json!({
|
||||
"networkId": String::from(network_override),
|
||||
"publicKey": format_public_key::<Pair>(public_key.clone()),
|
||||
"accountId": format_account_id::<Pair>(public_key.clone()),
|
||||
"ss58PublicKey": public_key.to_ss58check_with_version(network_override),
|
||||
"ss58Address": public_key.to_ss58check_with_version(network_override),
|
||||
});
|
||||
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&json).expect("Json pretty print failed")
|
||||
);
|
||||
}
|
||||
OutputType::Text => {
|
||||
println!(
|
||||
"Network ID/Version: {}\n \
|
||||
println!("{}", serde_json::to_string_pretty(&json).expect("Json pretty print failed"));
|
||||
},
|
||||
OutputType::Text => {
|
||||
println!(
|
||||
"Network ID/Version: {}\n \
|
||||
Public key (hex): {}\n \
|
||||
Account ID: {}\n \
|
||||
Public key (SS58): {}\n \
|
||||
SS58 Address: {}",
|
||||
String::from(network_override),
|
||||
format_public_key::<Pair>(public_key.clone()),
|
||||
format_account_id::<Pair>(public_key.clone()),
|
||||
public_key.to_ss58check_with_version(network_override),
|
||||
public_key.to_ss58check_with_version(network_override),
|
||||
);
|
||||
}
|
||||
}
|
||||
String::from(network_override),
|
||||
format_public_key::<Pair>(public_key.clone()),
|
||||
format_account_id::<Pair>(public_key.clone()),
|
||||
public_key.to_ss58check_with_version(network_override),
|
||||
public_key.to_ss58check_with_version(network_override),
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unwrap_or_default_ss58_name(x: Option<Ss58AddressFormat>) -> String {
|
||||
@ -228,8 +216,5 @@ fn format_account_id<P: sp_core::Pair>(public_key: PublicFor<P>) -> String
|
||||
where
|
||||
PublicFor<P>: Into<MultiSigner>,
|
||||
{
|
||||
format!(
|
||||
"0x{}",
|
||||
HexDisplay::from(&public_key.into().into_account().as_ref())
|
||||
)
|
||||
format!("0x{}", HexDisplay::from(&public_key.into().into_account().as_ref()))
|
||||
}
|
||||
|
@ -2,218 +2,213 @@
|
||||
|
||||
use clap::Parser;
|
||||
use rand::{rngs::OsRng, RngCore};
|
||||
use sc_cli::{utils::format_seed, with_crypto_scheme, CryptoSchemeFlag, Error, OutputTypeFlag};
|
||||
use sp_core::crypto::{unwrap_or_default_ss58_version, Ss58AddressFormat, Ss58Codec};
|
||||
use sp_core::crypto::{
|
||||
unwrap_or_default_ss58_version, Ss58AddressFormat, Ss58Codec,
|
||||
};
|
||||
use sp_runtime::traits::IdentifyAccount;
|
||||
use sc_cli::{
|
||||
with_crypto_scheme, Error, OutputTypeFlag, CryptoSchemeFlag,
|
||||
utils::format_seed,
|
||||
};
|
||||
|
||||
use crate::commands::utils::print_from_uri;
|
||||
use crate::params::NetworkSchemeFlag;
|
||||
|
||||
/// The `vanity` command
|
||||
#[derive(Debug, Clone, Parser)]
|
||||
#[command(
|
||||
name = "vanity",
|
||||
about = "Generate a seed that provides a vanity address"
|
||||
)]
|
||||
#[command(name = "vanity", about = "Generate a seed that provides a vanity address")]
|
||||
pub struct VanityCmd {
|
||||
/// Desired pattern
|
||||
#[arg(long, value_parser = assert_non_empty_string)]
|
||||
pattern: String,
|
||||
/// Desired pattern
|
||||
#[arg(long, value_parser = assert_non_empty_string)]
|
||||
pattern: String,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
network_scheme: NetworkSchemeFlag,
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
network_scheme: NetworkSchemeFlag,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
output_scheme: OutputTypeFlag,
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
output_scheme: OutputTypeFlag,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
crypto_scheme: CryptoSchemeFlag,
|
||||
#[allow(missing_docs)]
|
||||
#[clap(flatten)]
|
||||
crypto_scheme: CryptoSchemeFlag,
|
||||
}
|
||||
|
||||
impl VanityCmd {
|
||||
/// Run the command
|
||||
pub fn run(&self) -> Result<(), Error> {
|
||||
let formated_seed = with_crypto_scheme!(
|
||||
self.crypto_scheme.scheme,
|
||||
generate_key(
|
||||
&self.pattern,
|
||||
unwrap_or_default_ss58_version(self.network_scheme.network)
|
||||
),
|
||||
)?;
|
||||
/// Run the command
|
||||
pub fn run(&self) -> Result<(), Error> {
|
||||
let formated_seed = with_crypto_scheme!(
|
||||
self.crypto_scheme.scheme,
|
||||
generate_key(
|
||||
&self.pattern,
|
||||
unwrap_or_default_ss58_version(self.network_scheme.network)
|
||||
),
|
||||
)?;
|
||||
|
||||
with_crypto_scheme!(
|
||||
self.crypto_scheme.scheme,
|
||||
print_from_uri(
|
||||
&formated_seed,
|
||||
None,
|
||||
self.network_scheme.network,
|
||||
self.output_scheme.output_type,
|
||||
),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
with_crypto_scheme!(
|
||||
self.crypto_scheme.scheme,
|
||||
print_from_uri(
|
||||
&formated_seed,
|
||||
None,
|
||||
self.network_scheme.network,
|
||||
self.output_scheme.output_type,
|
||||
),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// genertae a key based on given pattern
|
||||
fn generate_key<Pair>(
|
||||
desired: &str,
|
||||
network_override: Ss58AddressFormat,
|
||||
desired: &str,
|
||||
network_override: Ss58AddressFormat,
|
||||
) -> Result<String, &'static str>
|
||||
where
|
||||
Pair: sp_core::Pair,
|
||||
Pair::Public: IdentifyAccount,
|
||||
<Pair::Public as IdentifyAccount>::AccountId: Ss58Codec,
|
||||
Pair: sp_core::Pair,
|
||||
Pair::Public: IdentifyAccount,
|
||||
<Pair::Public as IdentifyAccount>::AccountId: Ss58Codec,
|
||||
{
|
||||
println!("Generating key containing pattern '{}'", desired);
|
||||
println!("Generating key containing pattern '{}'", desired);
|
||||
|
||||
let top = 45 + (desired.len() * 48);
|
||||
let mut best = 0;
|
||||
let mut seed = Pair::Seed::default();
|
||||
let mut done = 0;
|
||||
let top = 45 + (desired.len() * 48);
|
||||
let mut best = 0;
|
||||
let mut seed = Pair::Seed::default();
|
||||
let mut done = 0;
|
||||
|
||||
loop {
|
||||
if done % 100000 == 0 {
|
||||
OsRng.fill_bytes(seed.as_mut());
|
||||
} else {
|
||||
next_seed(seed.as_mut());
|
||||
}
|
||||
loop {
|
||||
if done % 100000 == 0 {
|
||||
OsRng.fill_bytes(seed.as_mut());
|
||||
} else {
|
||||
next_seed(seed.as_mut());
|
||||
}
|
||||
|
||||
let p = Pair::from_seed(&seed);
|
||||
let ss58 = p
|
||||
.public()
|
||||
.into_account()
|
||||
.to_ss58check_with_version(network_override);
|
||||
let p = Pair::from_seed(&seed);
|
||||
let ss58 = p.public().into_account().to_ss58check_with_version(network_override);
|
||||
println!("{:?}", ss58);
|
||||
let score = calculate_score(desired, &ss58);
|
||||
if score > best || desired.len() < 2 {
|
||||
best = score;
|
||||
if best >= top {
|
||||
println!("best: {} == top: {}", best, top);
|
||||
return Ok(format_seed::<Pair>(seed.clone()));
|
||||
}
|
||||
}
|
||||
done += 1;
|
||||
let score = calculate_score(desired, &ss58);
|
||||
if score > best || desired.len() < 2 {
|
||||
best = score;
|
||||
if best >= top {
|
||||
println!("best: {} == top: {}", best, top);
|
||||
return Ok(format_seed::<Pair>(seed.clone()))
|
||||
}
|
||||
}
|
||||
done += 1;
|
||||
|
||||
if done % good_waypoint(done) == 0 {
|
||||
println!("{} keys searched; best is {}/{} complete", done, best, top);
|
||||
}
|
||||
}
|
||||
if done % good_waypoint(done) == 0 {
|
||||
println!("{} keys searched; best is {}/{} complete", done, best, top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn good_waypoint(done: u64) -> u64 {
|
||||
match done {
|
||||
0..=1_000_000 => 100_000,
|
||||
1_000_001..=10_000_000 => 1_000_000,
|
||||
10_000_001..=100_000_000 => 10_000_000,
|
||||
100_000_001.. => 100_000_000,
|
||||
}
|
||||
match done {
|
||||
0..=1_000_000 => 100_000,
|
||||
1_000_001..=10_000_000 => 1_000_000,
|
||||
10_000_001..=100_000_000 => 10_000_000,
|
||||
100_000_001.. => 100_000_000,
|
||||
}
|
||||
}
|
||||
|
||||
fn next_seed(seed: &mut [u8]) {
|
||||
for s in seed {
|
||||
match s {
|
||||
255 => {
|
||||
*s = 0;
|
||||
}
|
||||
_ => {
|
||||
*s += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for s in seed {
|
||||
match s {
|
||||
255 => {
|
||||
*s = 0;
|
||||
},
|
||||
_ => {
|
||||
*s += 1;
|
||||
break
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate the score of a key based on the desired
|
||||
/// input.
|
||||
fn calculate_score(_desired: &str, key: &str) -> usize {
|
||||
for truncate in 0.._desired.len() {
|
||||
let snip_size = _desired.len() - truncate;
|
||||
let truncated = &_desired[0..snip_size];
|
||||
if let Some(pos) = key.find(truncated) {
|
||||
return (47 - pos) + (snip_size * 48);
|
||||
}
|
||||
}
|
||||
0
|
||||
for truncate in 0.._desired.len() {
|
||||
let snip_size = _desired.len() - truncate;
|
||||
let truncated = &_desired[0..snip_size];
|
||||
if let Some(pos) = key.find(truncated) {
|
||||
return (47 - pos) + (snip_size * 48)
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
/// checks that `pattern` is non-empty
|
||||
fn assert_non_empty_string(pattern: &str) -> Result<String, &'static str> {
|
||||
if pattern.is_empty() {
|
||||
Err("Pattern must not be empty")
|
||||
} else {
|
||||
Ok(pattern.to_string())
|
||||
}
|
||||
if pattern.is_empty() {
|
||||
Err("Pattern must not be empty")
|
||||
} else {
|
||||
Ok(pattern.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sp_core::{
|
||||
crypto::{default_ss58_version, Ss58AddressFormatRegistry, Ss58Codec},
|
||||
sr25519, Pair,
|
||||
};
|
||||
use super::*;
|
||||
use sp_core::{
|
||||
crypto::{default_ss58_version, Ss58AddressFormatRegistry, Ss58Codec},
|
||||
sr25519, Pair,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn vanity() {
|
||||
let vanity = VanityCmd::parse_from(&["vanity", "--pattern", "j"]);
|
||||
assert!(vanity.run().is_ok());
|
||||
}
|
||||
#[test]
|
||||
fn vanity() {
|
||||
let vanity = VanityCmd::parse_from(&["vanity", "--pattern", "j"]);
|
||||
assert!(vanity.run().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation_with_single_char() {
|
||||
let seed = generate_key::<sr25519::Pair>("ab", default_ss58_version()).unwrap();
|
||||
assert!(
|
||||
sr25519::Pair::from_seed_slice(&array_bytes::hex2bytes_unchecked(&seed))
|
||||
.unwrap()
|
||||
.public()
|
||||
.to_ss58check()
|
||||
.contains("ab")
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_generation_with_single_char() {
|
||||
let seed = generate_key::<sr25519::Pair>("ab", default_ss58_version()).unwrap();
|
||||
assert!(sr25519::Pair::from_seed_slice(&array_bytes::hex2bytes_unchecked(&seed))
|
||||
.unwrap()
|
||||
.public()
|
||||
.to_ss58check()
|
||||
.contains("ab"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generate_key_respects_network_override() {
|
||||
let seed =
|
||||
generate_key::<sr25519::Pair>("ab", Ss58AddressFormatRegistry::PolkadotAccount.into())
|
||||
.unwrap();
|
||||
assert!(
|
||||
sr25519::Pair::from_seed_slice(&array_bytes::hex2bytes_unchecked(&seed))
|
||||
.unwrap()
|
||||
.public()
|
||||
.to_ss58check_with_version(Ss58AddressFormatRegistry::PolkadotAccount.into())
|
||||
.contains("ab")
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn generate_key_respects_network_override() {
|
||||
let seed =
|
||||
generate_key::<sr25519::Pair>("ab", Ss58AddressFormatRegistry::PolkadotAccount.into())
|
||||
.unwrap();
|
||||
assert!(sr25519::Pair::from_seed_slice(&array_bytes::hex2bytes_unchecked(&seed))
|
||||
.unwrap()
|
||||
.public()
|
||||
.to_ss58check_with_version(Ss58AddressFormatRegistry::PolkadotAccount.into())
|
||||
.contains("ab"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_score_1_char_100() {
|
||||
let score = calculate_score("j", "sYrjWiZkEP1PQe2kKEZiC1Bi9L8yFSsB5RPEkzEPd5NThsB5H");
|
||||
assert_eq!(score, 96);
|
||||
}
|
||||
#[test]
|
||||
fn test_score_1_char_100() {
|
||||
let score = calculate_score("j", "sYrjWiZkEP1PQe2kKEZiC1Bi9L8yFSsB5RPEkzEPd5NThsB5H");
|
||||
assert_eq!(score, 96);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_score_100() {
|
||||
let score = calculate_score("ghst", "sYsghstuhYd9p6unUC3kPxjD2gv2zRCztYQaEDCMJpYrPTqTG");
|
||||
assert_eq!(score, 246);
|
||||
}
|
||||
#[test]
|
||||
fn test_score_100() {
|
||||
let score = calculate_score("ghst", "sYsghstuhYd9p6unUC3kPxjD2gv2zRCztYQaEDCMJpYrPTqTG");
|
||||
assert_eq!(score, 246);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_score_50_2() {
|
||||
// 50% for the position + 50% for the size
|
||||
assert_eq!(
|
||||
calculate_score("ghst", "sYsghXXuhYd9p6unUC3kPxjD2gv2zRCztYQaEDCMJpYrPTqTG"),
|
||||
146
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_score_50_2() {
|
||||
// 50% for the position + 50% for the size
|
||||
assert_eq!(
|
||||
calculate_score("ghst", "sYsghXXuhYd9p6unUC3kPxjD2gv2zRCztYQaEDCMJpYrPTqTG"),
|
||||
146
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_score_0() {
|
||||
assert_eq!(
|
||||
calculate_score("ghst", "sYrjWiZkEP1PQe2kKEZiC1Bi9L8yFSsB5RPEkzEPd5NThsB5H"),
|
||||
0
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_score_0() {
|
||||
assert_eq!(
|
||||
calculate_score("ghst", "sYrjWiZkEP1PQe2kKEZiC1Bi9L8yFSsB5RPEkzEPd5NThsB5H"),
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub mod commands;
|
||||
pub mod params;
|
||||
pub mod commands;
|
||||
|
||||
pub use commands::KeySubcommand;
|
||||
pub use commands::VanityCmd;
|
||||
|
@ -21,25 +21,19 @@ pub struct InnerSs58AddressFormat(Ss58AddressFormat);
|
||||
impl InnerSs58AddressFormat {
|
||||
#[inline]
|
||||
pub fn custom(prefix: u16) -> Self {
|
||||
Self {
|
||||
0: Ss58AddressFormat::custom(prefix),
|
||||
}
|
||||
Self { 0: Ss58AddressFormat::custom(prefix) }
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for InnerSs58AddressFormat {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{} network",
|
||||
ALL_POSSIBLE_IDS
|
||||
.binary_search(&u16::from(self.0))
|
||||
.expect("always be found")
|
||||
)
|
||||
write!(f, "{} network", ALL_POSSIBLE_IDS
|
||||
.binary_search(&u16::from(self.0))
|
||||
.expect("always be found"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a str> for InnerSs58AddressFormat {
|
||||
impl<'a>TryFrom<&'a str> for InnerSs58AddressFormat {
|
||||
type Error = ParseError;
|
||||
|
||||
fn try_from(x: &'a str) -> Result<Self, Self::Error> {
|
||||
@ -50,13 +44,13 @@ impl<'a> TryFrom<&'a str> for InnerSs58AddressFormat {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_s58_prefix_address_format(x: &str) -> Result<Ss58AddressFormat, String> {
|
||||
pub fn parse_s58_prefix_address_format(x: &str,) -> Result<Ss58AddressFormat, String> {
|
||||
match InnerSs58AddressFormat::try_from(x) {
|
||||
Ok(format_registry) => Ok(format_registry.0.into()),
|
||||
Err(_) => Err(format!(
|
||||
"Unable to parse variant. Known variants: {:?}",
|
||||
&ALL_POSSIBLE_NAMES
|
||||
)),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
6
core-primitives/Cargo.toml
Normal file → Executable file
@ -15,7 +15,7 @@ sp-runtime = { workspace = true }
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"sp-core/std",
|
||||
"sp-runtime/std",
|
||||
"sp-std/std",
|
||||
"sp-core/std",
|
||||
"sp-runtime/std",
|
||||
"sp-std/std",
|
||||
]
|
||||
|
0
core-primitives/src/lib.rs
Normal file → Executable file
0
file_header.txt
Normal file → Executable file
BIN
images/img.png
Before Width: | Height: | Size: 4.7 KiB |
BIN
images/img_1.png
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 49 KiB |
BIN
images/img_2.png
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 28 KiB |
BIN
images/img_3.png
Before Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 8.0 KiB |
BIN
images/img_5.png
Before Width: | Height: | Size: 4.4 KiB |
BIN
images/img_6.png
Before Width: | Height: | Size: 10 KiB |
BIN
images/img_7.png
Before Width: | Height: | Size: 15 KiB |
BIN
images/img_8.png
Before Width: | Height: | Size: 4.7 KiB |
BIN
images/img_9.png
Before Width: | Height: | Size: 22 KiB |
@ -14,7 +14,7 @@ pub fn logger_hook() -> impl FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Con
|
||||
|_logger_builder, _config| {}
|
||||
}
|
||||
|
||||
/// This module exports Prometheus types an:d defines
|
||||
/// This module exports Prometheus types an:d defines
|
||||
/// the [`Metrics`](metrics::Metrics) trait.
|
||||
pub mod metrics {
|
||||
pub use prometheus_endpoint as prometheus;
|
||||
|
@ -22,11 +22,7 @@ impl Metronome {
|
||||
/// Create a new metronome source with a defined cycle duration.
|
||||
pub fn new(cycle: Duration) -> Self {
|
||||
let period = cycle.into();
|
||||
Self {
|
||||
period,
|
||||
delay: Delay::new(period),
|
||||
state: MetronomeState::Snooze,
|
||||
}
|
||||
Self { period, delay: Delay::new(period), state: MetronomeState::Snooze }
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,14 +36,14 @@ impl futures::Stream for Metronome {
|
||||
let val = self.period;
|
||||
self.delay.reset(val);
|
||||
self.state = MetronomeState::Snooze;
|
||||
}
|
||||
},
|
||||
MetronomeState::Snooze => {
|
||||
if !Pin::new(&mut self.delay).poll(cx).is_ready() {
|
||||
break;
|
||||
break
|
||||
}
|
||||
self.state = MetronomeState::SetAlarm;
|
||||
return Poll::Ready(Some(()));
|
||||
}
|
||||
return Poll::Ready(Some(()))
|
||||
},
|
||||
}
|
||||
}
|
||||
Poll::Pending
|
||||
|
@ -2,16 +2,19 @@
|
||||
|
||||
use codec::Decode;
|
||||
use core_primitives::{
|
||||
metrics_definitions::{CounterDefinition, CounterVecDefinition, HistogramDefinition},
|
||||
metrics_definitions::{
|
||||
CounterDefinition, CounterVecDefinition, HistogramDefinition,
|
||||
},
|
||||
RuntimeMetricLabelValues, RuntimeMetricOp, RuntimeMetricUpdate,
|
||||
};
|
||||
use prometheus_endpoint::{
|
||||
register, Counter, CounterVec, Histogram, HistogramOpts, Opts, PrometheusError, Registry, U64,
|
||||
register, Counter, CounterVec, Histogram, HistogramOpts, Opts, Registry,
|
||||
PrometheusError, U64,
|
||||
};
|
||||
use std::{
|
||||
collections::hash_map::HashMap,
|
||||
sync::{Arc, Mutex, MutexGuard},
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Metrics {
|
||||
@ -29,15 +32,13 @@ impl RuntimeMetricsProvider {
|
||||
|
||||
pub fn register_countervec(&self, countervec: CounterVecDefinition) {
|
||||
self.with_counter_vecs_lock_held(|mut hashmap| {
|
||||
hashmap
|
||||
.entry(countervec.name.to_owned())
|
||||
.or_insert(register(
|
||||
CounterVec::new(
|
||||
Opts::new(countervec.name, countervec.description),
|
||||
countervec.labels,
|
||||
)?,
|
||||
&self.0,
|
||||
)?);
|
||||
hashmap.entry(countervec.name.to_owned()).or_insert(register(
|
||||
CounterVec::new(
|
||||
Opts::new(countervec.name, countervec.description),
|
||||
countervec.labels,
|
||||
)?,
|
||||
&self.0,
|
||||
)?);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@ -45,7 +46,10 @@ impl RuntimeMetricsProvider {
|
||||
pub fn register_counter(&self, counter: CounterDefinition) {
|
||||
self.with_counters_lock_held(|mut hashmap| {
|
||||
hashmap.entry(counter.name.to_owned()).or_insert(register(
|
||||
Counter::new(counter.name, counter.description)?,
|
||||
Counter::new(
|
||||
counter.name,
|
||||
counter.description,
|
||||
)?,
|
||||
&self.0,
|
||||
)?);
|
||||
Ok(())
|
||||
@ -56,7 +60,8 @@ impl RuntimeMetricsProvider {
|
||||
self.with_histograms_lock_held(|mut hashmap| {
|
||||
hashmap.entry(hist.name.to_owned()).or_insert(register(
|
||||
Histogram::with_opts(
|
||||
HistogramOpts::new(hist.name, hist.description).buckets(hist.buckets.to_vec()),
|
||||
HistogramOpts::new(hist.name, hist.description)
|
||||
.buckets(hist.buckets.to_vec()),
|
||||
)?,
|
||||
&self.0,
|
||||
)?);
|
||||
@ -64,21 +69,23 @@ impl RuntimeMetricsProvider {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn inc_counter_vec_by(&self, name: &str, value: u64, labels: &RuntimeMetricsProvider) {
|
||||
pub fn inc_counter_vec_by(
|
||||
&self,
|
||||
name: &str,
|
||||
value: u64,
|
||||
labels: &RuntimeMetricsProvider,
|
||||
) {
|
||||
self.with_counter_vecs_lock_held(|mut hashmap| {
|
||||
hashmap.entry(name.to_owned()).and_modify(|counter_vec| {
|
||||
counter_vec
|
||||
.with_label_values(&labels.as_str_vec())
|
||||
.inc_by(value)
|
||||
counter_vec.with_label_values(&labels.as_str_vec()).inc_by(value)
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
pub fn inc_counter_by(&self, name: &str, value: u64) {
|
||||
self.with_counters_lock_held(|mut hashmap| {
|
||||
hashmap
|
||||
.entry(name.to_owned())
|
||||
hashmap.entry(name.to_owned())
|
||||
.and_modify(|counter_vec| counter_vec.inc_by(value));
|
||||
Ok(())
|
||||
})
|
||||
@ -86,9 +93,8 @@ impl RuntimeMetricsProvider {
|
||||
|
||||
pub fn observe_histogram(&self, name: &str, value: u128) {
|
||||
self.with_histograms_lock_held(|mut hashmap| {
|
||||
hashmap
|
||||
.entry(name.to_owned())
|
||||
.and_modify(|histogram| histogram.observe(value as f64 / 1_000_000_000.0));
|
||||
hashmap.entry(name.to_owned())
|
||||
and_modify(|histogram| histogram.observe(value as f64 / 1_000_000_000.0));
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@ -97,36 +103,21 @@ impl RuntimeMetricsProvider {
|
||||
where
|
||||
F: FnOnce(MutexGuard<'_, HashMap<String, Counter<U64>>>) -> Result<(), PrometheusError>,
|
||||
{
|
||||
let _ = self
|
||||
.1
|
||||
.counters
|
||||
.lock()
|
||||
.map(do_something)
|
||||
.or_else(|error| Err(error));
|
||||
let _ = self.1.counters.lock().map(do_something).or_else(|error| Err(error));
|
||||
}
|
||||
|
||||
fn with_counter_vecs_lock_held<F>(&self, do_something: F)
|
||||
where
|
||||
F: FnOnce(MutexGuard<'_, HashMap<String, CounterVec<U64>>>) -> Result<(), PrometheusError>,
|
||||
{
|
||||
let _ = self
|
||||
.1
|
||||
.counter_vecs
|
||||
.lock()
|
||||
.map(do_something)
|
||||
.or_else(|error| Err(error));
|
||||
let _ = self.1.counter_vecs.lock().map(do_something).or_else(|error| Err(error));
|
||||
}
|
||||
|
||||
fn with_histograms_lock_held<F>(&self, do_something: F)
|
||||
where
|
||||
F: FnOnce(MutexGuard<'_, HashMap<String, Histogram>>) -> Result<(), PrometheusError>,
|
||||
{
|
||||
let _ = self
|
||||
.1
|
||||
.histograms
|
||||
.lock()
|
||||
.map(do_something)
|
||||
.or_else(|error| Err(error));
|
||||
let _ = self.1.histograms.lock().map(do_something).or_else(|error| Err(error));
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,7 +131,7 @@ impl sc_tracing::TraceHandler for RuntimeMetricsProvider {
|
||||
.unwrap_or(&String::default())
|
||||
.ne("metrics")
|
||||
{
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
if let Some(update_op_bs58) = event.values.string_values.get("params") {
|
||||
@ -150,7 +141,7 @@ impl sc_tracing::TraceHandler for RuntimeMetricsProvider {
|
||||
.as_slice(),
|
||||
) {
|
||||
Ok(update_op) => self.parse_metric_update(update_op),
|
||||
Err(_) => {}
|
||||
Err(_) => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,15 +150,12 @@ impl sc_tracing::TraceHandler for RuntimeMetricsProvider {
|
||||
impl RuntimeMetricsProvider {
|
||||
fn parse_metric_update(&self, update: RuntimeMetricUpdate) {
|
||||
match update.op {
|
||||
RuntimeMetricOp::IncrementCounterVec(value, ref labels) => {
|
||||
self.inc_counter_vec_by(update.metric_name(), value, labels)
|
||||
}
|
||||
RuntimeMetricOp::IncrementCounter(value) => {
|
||||
self.inc_counter_by(update.metric_name(), value)
|
||||
}
|
||||
RuntimeMetricOp::ObserveHistogram(value) => {
|
||||
self.observe_histogram(update.metric_name(), value)
|
||||
}
|
||||
RuntimeMetricOp::IncrementCounterVec(value, ref labels) =>
|
||||
self.inc_counter_vec_by(update.metric_name(), value, labels),
|
||||
RuntimeMetricOp::IncrementCounter(value) =>
|
||||
self.inc_counter_by(update.metric_name(), value),
|
||||
RuntimeMetricOp::ObserveHistogram(value) =>
|
||||
self.observe_histogram(update.metric_name(), value),
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,7 +178,7 @@ impl RuntimeMetricsProvider {
|
||||
pub fn logger_hook() -> impl FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration) -> () {
|
||||
|logger_builder, config| {
|
||||
if config.prometheus_registry().is_none() {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
let registry = config.prometheus_registry().cloned().unwrap();
|
||||
|
@ -1,5 +1,5 @@
|
||||
use ghost_test_service::{node_config, run_validator_node, test_prometheus_config};
|
||||
use hyper::{Client, Uri};
|
||||
use ghost_test_service::{node_config, run_validator_node, test_prometheus_config};
|
||||
use keyring::AccountKeyring::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@ -7,13 +7,8 @@ const DEFAULT_PROMETHEUS_PORT: u16 = 9616;
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn runtime_can_publish_metrics() {
|
||||
let mut alice_config = node_config(
|
||||
|| {},
|
||||
tokio::runtime::Handle::current(),
|
||||
Alice,
|
||||
Vec::new(),
|
||||
true,
|
||||
);
|
||||
let mut alice_config =
|
||||
node_config(|| {}, tokio::runtime::Handle::current(), Alice, Vec::new(), true);
|
||||
|
||||
// Enable prometheus metrics for Alice.
|
||||
alice_config.prometheus_config = Some(test_prometheus_config(DEFAULT_PROMETHEUS_PORT));
|
||||
@ -31,13 +26,8 @@ async fn runtime_can_publish_metrics() {
|
||||
// Start validator Alice
|
||||
let alice = run_validator_node(alice_config, None);
|
||||
|
||||
let bob_config = node_config(
|
||||
|| {},
|
||||
tokio::runtime::Handle::current(),
|
||||
Bob,
|
||||
vec![alice.addr.clone()],
|
||||
true,
|
||||
);
|
||||
let bob_config =
|
||||
node_config(|| {}, tokio::runtime::Handle::current(), Bob, vec![alice.addr.clone()], true);
|
||||
|
||||
// Start validator Bob
|
||||
let _bob = run_validator_node(bob_config, None);
|
||||
@ -58,25 +48,19 @@ async fn scrape_prometheus_metrics(metrics_uri: &str) -> HashMap<String, u64> {
|
||||
.expect("GET request failed");
|
||||
|
||||
let body = String::from_utf8(
|
||||
hyper::body::to_bytes(res)
|
||||
.await
|
||||
.expect("can't get body as bytes")
|
||||
.to_vec(),
|
||||
)
|
||||
.expect("body is not an UTF8 string");
|
||||
hyper::body::to_bytes(res).await.expect("can't get body as bytes").to_vec(),
|
||||
).expect("body is not an UTF8 string");
|
||||
|
||||
let lines: Vec<_> = body.lines().map(|s| Ok(s.to_owned())).collect();
|
||||
prometheus_parse::Scrape::parse(lines.into_iter())
|
||||
.expect("Scraper failed to parse Prometheus metrics")
|
||||
.samples
|
||||
.into_iter()
|
||||
.filter_map(
|
||||
|prometheus_parse::Sample { metric, value, .. }| match value {
|
||||
prometheus_parse::Value::Counter(value) => Some((metric, value as u64)),
|
||||
prometheus_parse::Value::Gauge(value) => Some((metric, value as u64)),
|
||||
prometheus_parse::Value::Untyped(value) => Some((metric, value as u64)),
|
||||
_ => None,
|
||||
},
|
||||
)
|
||||
.filter_map(|prometheus_parse::Sample { metric, value, .. }| match value {
|
||||
prometheus_parse::Value::Counter(value) => Some((metric, value as u64)),
|
||||
prometheus_parse::Value::Gauge(value) => Some((metric, value as u64)),
|
||||
prometheus_parse::Value::Untyped(value) => Some((metric, value as u64)),
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ghost-claims"
|
||||
version = "0.2.4"
|
||||
version = "0.2.2"
|
||||
description = "Ghost balance and rank claims based on EVM actions"
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
@ -37,17 +37,17 @@ serde_json = { workspace = true, default-features = true }
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"frame-benchmarking?/std",
|
||||
"frame-benchmarking?/std",
|
||||
"serde/std",
|
||||
"codec/std",
|
||||
"codec/std",
|
||||
"scale-info/std",
|
||||
"libsecp256k1/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
"sp-core/std",
|
||||
"sp-runtime/std",
|
||||
"sp-io/std",
|
||||
"sp-std/std",
|
||||
"libsecp256k1/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
"sp-core/std",
|
||||
"sp-runtime/std",
|
||||
"sp-io/std",
|
||||
"sp-std/std",
|
||||
"pallet-ranked-collective/std",
|
||||
"pallet-vesting/std",
|
||||
"pallet-balances/std",
|
||||
@ -56,19 +56,19 @@ std = [
|
||||
runtime-benchmarks = [
|
||||
"libsecp256k1/hmac",
|
||||
"libsecp256k1/static-context",
|
||||
"frame-benchmarking/runtime-benchmarks",
|
||||
"frame-support/runtime-benchmarks",
|
||||
"frame-system/runtime-benchmarks",
|
||||
"pallet-ranked-collective/runtime-benchmarks",
|
||||
"pallet-vesting/runtime-benchmarks",
|
||||
"pallet-balances/runtime-benchmarks",
|
||||
"sp-runtime/runtime-benchmarks",
|
||||
"frame-benchmarking/runtime-benchmarks",
|
||||
"frame-support/runtime-benchmarks",
|
||||
"frame-system/runtime-benchmarks",
|
||||
"pallet-ranked-collective/runtime-benchmarks",
|
||||
"pallet-vesting/runtime-benchmarks",
|
||||
"pallet-balances/runtime-benchmarks",
|
||||
"sp-runtime/runtime-benchmarks",
|
||||
]
|
||||
try-runtime = [
|
||||
"frame-support/try-runtime",
|
||||
"frame-system/try-runtime",
|
||||
"pallet-ranked-collective/try-runtime",
|
||||
"pallet-vesting/try-runtime",
|
||||
"pallet-balances/try-runtime",
|
||||
"sp-runtime/try-runtime",
|
||||
"frame-support/try-runtime",
|
||||
"frame-system/try-runtime",
|
||||
"pallet-ranked-collective/try-runtime",
|
||||
"pallet-vesting/try-runtime",
|
||||
"pallet-balances/try-runtime",
|
||||
"sp-runtime/try-runtime",
|
||||
]
|
||||
|
@ -6,14 +6,14 @@ use frame_benchmarking::v2::*;
|
||||
#[instance_benchmarks]
|
||||
mod benchmarks {
|
||||
use super::*;
|
||||
use frame_support::dispatch::RawOrigin;
|
||||
use pallet_ranked_collective::Pallet as Club;
|
||||
use frame_support::dispatch::RawOrigin;
|
||||
|
||||
#[benchmark]
|
||||
fn claim() {
|
||||
let i = 1337u32;
|
||||
let ethereum_secret_key =
|
||||
libsecp256k1::SecretKey::parse(&keccak_256(&i.to_le_bytes())).unwrap();
|
||||
let ethereum_secret_key = libsecp256k1::SecretKey::parse(
|
||||
&keccak_256(&i.to_le_bytes())).unwrap();
|
||||
let eth_address = crate::secp_utils::eth(ðereum_secret_key);
|
||||
|
||||
let balance = CurrencyOf::<T, I>::minimum_balance();
|
||||
@ -22,30 +22,23 @@ mod benchmarks {
|
||||
Total::<T, I>::put(balance);
|
||||
|
||||
let pseudo_rank = 5u16;
|
||||
let _ = Club::<T, I>::do_add_member_to_rank(pseudo_account.clone(), pseudo_rank, false);
|
||||
let _ = Club::<T, I>::do_add_member_to_rank(
|
||||
pseudo_account.clone(),
|
||||
pseudo_rank,
|
||||
false,
|
||||
);
|
||||
|
||||
let user_account: T::AccountId = account("user", i, 0);
|
||||
let signature =
|
||||
crate::secp_utils::sig::<T, I>(ðereum_secret_key, &user_account.encode());
|
||||
|
||||
let signature = crate::secp_utils::sig::<T, I>(ðereum_secret_key, &user_account.encode());
|
||||
|
||||
let prev_balance = CurrencyOf::<T, I>::free_balance(&user_account);
|
||||
let prev_rank = Club::<T, I>::rank_of(&user_account);
|
||||
|
||||
#[extrinsic_call]
|
||||
claim(
|
||||
RawOrigin::Signed(user_account.clone()),
|
||||
eth_address,
|
||||
signature,
|
||||
);
|
||||
claim(RawOrigin::Signed(user_account.clone()), eth_address, signature);
|
||||
|
||||
assert_eq!(
|
||||
CurrencyOf::<T, I>::free_balance(&user_account),
|
||||
prev_balance + balance
|
||||
);
|
||||
assert_eq!(
|
||||
CurrencyOf::<T, I>::free_balance(&pseudo_account),
|
||||
balance - balance
|
||||
);
|
||||
assert_eq!(CurrencyOf::<T, I>::free_balance(&user_account), prev_balance + balance);
|
||||
assert_eq!(CurrencyOf::<T, I>::free_balance(&pseudo_account), balance - balance);
|
||||
|
||||
let rank = match prev_rank {
|
||||
Some(current_rank) if pseudo_rank <= current_rank => Some(current_rank),
|
||||
@ -55,5 +48,9 @@ mod benchmarks {
|
||||
assert_eq!(Club::<T, I>::rank_of(&pseudo_account), None);
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test,);
|
||||
impl_benchmark_test_suite!(
|
||||
Pallet,
|
||||
crate::mock::new_test_ext(),
|
||||
crate::mock::Test,
|
||||
);
|
||||
}
|
||||
|
@ -1,33 +1,31 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use frame_support::{
|
||||
ensure,
|
||||
pallet_prelude::*,
|
||||
ensure, pallet_prelude::*,
|
||||
traits::{
|
||||
Currency, ExistenceRequirement, Get, RankedMembers, RankedMembersSwapHandler,
|
||||
VestingSchedule,
|
||||
Currency, ExistenceRequirement, Get, RankedMembers,
|
||||
RankedMembersSwapHandler, VestingSchedule,
|
||||
},
|
||||
DefaultNoBound,
|
||||
};
|
||||
use frame_system::pallet_prelude::*;
|
||||
pub use pallet::*;
|
||||
use serde::{self, Deserialize, Deserializer, Serialize, Serializer};
|
||||
pub use pallet::*;
|
||||
|
||||
use sp_io::{crypto::secp256k1_ecdsa_recover, hashing::keccak_256};
|
||||
use sp_runtime::traits::{BlockNumberProvider, CheckedDiv, CheckedSub};
|
||||
use sp_runtime::traits::{CheckedSub, CheckedDiv, BlockNumberProvider};
|
||||
use sp_std::prelude::*;
|
||||
|
||||
extern crate alloc;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::{format, string::String};
|
||||
|
||||
mod weights;
|
||||
pub mod weights;
|
||||
pub use crate::weights::WeightInfo;
|
||||
|
||||
mod benchmarking;
|
||||
mod mock;
|
||||
mod secp_utils;
|
||||
mod tests;
|
||||
mod mock;
|
||||
mod benchmarking;
|
||||
mod secp_utils;
|
||||
|
||||
/// An ethereum address (i.e. 20 bytes, used to represent an Ethereum account).
|
||||
///
|
||||
@ -57,7 +55,7 @@ impl<'de> Deserialize<'de> for EthereumAddress {
|
||||
Err(serde::de::Error::custom(
|
||||
"Bad length of Ethereum address (should be 42 including `0x`)",
|
||||
))?;
|
||||
}
|
||||
}
|
||||
let raw: Vec<u8> = rustc_hex::FromHex::from_hex(s)
|
||||
.map_err(|e| serde::de::Error::custom(format!("{:?}", e)))?;
|
||||
let mut r = Self::default();
|
||||
@ -82,14 +80,15 @@ impl sp_std::fmt::Debug for EcdsaSignature {
|
||||
}
|
||||
|
||||
type CurrencyOf<T, I> = <<T as Config<I>>::VestingSchedule as VestingSchedule<
|
||||
<T as frame_system::Config>::AccountId,
|
||||
<T as frame_system::Config>::AccountId
|
||||
>>::Currency;
|
||||
|
||||
type BalanceOf<T, I> =
|
||||
<CurrencyOf<T, I> as Currency<<T as frame_system::Config>::AccountId>>::Balance;
|
||||
type BalanceOf<T, I> = <CurrencyOf<T, I> as Currency<
|
||||
<T as frame_system::Config>::AccountId>
|
||||
>::Balance;
|
||||
|
||||
type RankOf<T, I> = <pallet_ranked_collective::Pallet<T, I> as RankedMembers>::Rank;
|
||||
type AccountIdOf<T, I> = <pallet_ranked_collective::Pallet<T, I> as RankedMembers>::AccountId;
|
||||
type RankOf<T, I> = <pallet_ranked_collective::Pallet::<T, I> as RankedMembers>::Rank;
|
||||
type AccountIdOf<T, I> = <pallet_ranked_collective::Pallet::<T, I> as RankedMembers>::AccountId;
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
@ -100,11 +99,8 @@ pub mod pallet {
|
||||
pub struct Pallet<T, I = ()>(_);
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config<I: 'static = ()>:
|
||||
frame_system::Config + pallet_ranked_collective::Config<I>
|
||||
{
|
||||
type RuntimeEvent: From<Event<Self, I>>
|
||||
+ IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
pub trait Config<I: 'static = ()>: frame_system::Config + pallet_ranked_collective::Config<I> {
|
||||
type RuntimeEvent: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
|
||||
type VestingSchedule: VestingSchedule<Self::AccountId, Moment = BlockNumberFor<Self>>;
|
||||
type BlockNumberProvider: BlockNumberProvider<BlockNumber = BlockNumberFor<Self>>;
|
||||
@ -121,13 +117,13 @@ pub mod pallet {
|
||||
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config<I>, I: 'static = ()> {
|
||||
Claimed {
|
||||
receiver: T::AccountId,
|
||||
donor: T::AccountId,
|
||||
receiver: T::AccountId,
|
||||
donor: T::AccountId,
|
||||
amount: BalanceOf<T, I>,
|
||||
rank: Option<RankOf<T, I>>,
|
||||
},
|
||||
@ -162,16 +158,12 @@ pub mod pallet {
|
||||
.map(|(account_id, rank)| {
|
||||
assert!(
|
||||
pallet_ranked_collective::Pallet::<T, I>::do_add_member_to_rank(
|
||||
account_id.clone(),
|
||||
*rank,
|
||||
false
|
||||
)
|
||||
.is_ok(),
|
||||
"error during adding and promotion"
|
||||
account_id.clone(), *rank, false).is_ok(),
|
||||
"error during adding and promotion"
|
||||
);
|
||||
account_id
|
||||
})
|
||||
.collect();
|
||||
.collect();
|
||||
|
||||
assert!(
|
||||
self.members_and_ranks.len() == cult_accounts.len(),
|
||||
@ -193,13 +185,13 @@ pub mod pallet {
|
||||
) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
let data = who.using_encoded(to_ascii_hex);
|
||||
let recovered_address = Self::recover_ethereum_address(ðereum_signature, &data)
|
||||
.ok_or(Error::<T, I>::InvalidEthereumSignature)?;
|
||||
let recovered_address = Self::recover_ethereum_address(
|
||||
ðereum_signature,
|
||||
&data,
|
||||
).ok_or(Error::<T, I>::InvalidEthereumSignature)?;
|
||||
|
||||
ensure!(
|
||||
recovered_address == ethereum_address,
|
||||
Error::<T, I>::InvalidEthereumAddress
|
||||
);
|
||||
ensure!(recovered_address == ethereum_address,
|
||||
Error::<T, I>::InvalidEthereumAddress);
|
||||
|
||||
Self::do_claim(who, ethereum_address)
|
||||
}
|
||||
@ -207,37 +199,37 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
fn to_ascii_hex(data: &[u8]) -> Vec<u8> {
|
||||
let mut r = Vec::with_capacity(data.len() * 2);
|
||||
let mut push_nibble = |n| r.push(if n < 10 { b'0' + n } else { b'a' - 10 + n });
|
||||
for &b in data.iter() {
|
||||
push_nibble(b / 16);
|
||||
push_nibble(b % 16);
|
||||
}
|
||||
r
|
||||
let mut r = Vec::with_capacity(data.len() * 2);
|
||||
let mut push_nibble = |n| r.push(if n < 10 { b'0' + n } else { b'a' - 10 + n });
|
||||
for &b in data.iter() {
|
||||
push_nibble(b / 16);
|
||||
push_nibble(b % 16);
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
fn ethereum_signable_message(what: &[u8]) -> Vec<u8> {
|
||||
let prefix = T::Prefix::get();
|
||||
let mut l = prefix.len() + what.len();
|
||||
let mut rev = Vec::new();
|
||||
while l > 0 {
|
||||
rev.push(b'0' + (l % 10) as u8);
|
||||
l /= 10;
|
||||
}
|
||||
let mut v = b"\x19Ethereum Signed Message:\n".to_vec();
|
||||
v.extend(rev.into_iter().rev());
|
||||
v.extend_from_slice(prefix);
|
||||
v.extend_from_slice(what);
|
||||
v
|
||||
let mut l = prefix.len() + what.len();
|
||||
let mut rev = Vec::new();
|
||||
while l > 0 {
|
||||
rev.push(b'0' + (l % 10) as u8);
|
||||
l /= 10;
|
||||
}
|
||||
let mut v = b"\x19Ethereum Signed Message:\n".to_vec();
|
||||
v.extend(rev.into_iter().rev());
|
||||
v.extend_from_slice(prefix);
|
||||
v.extend_from_slice(what);
|
||||
v
|
||||
}
|
||||
|
||||
fn recover_ethereum_address(s: &EcdsaSignature, what: &[u8]) -> Option<EthereumAddress> {
|
||||
let msg = keccak_256(&Self::ethereum_signable_message(what));
|
||||
let mut res = EthereumAddress::default();
|
||||
res.0
|
||||
.copy_from_slice(&keccak_256(&secp256k1_ecdsa_recover(&s.0, &msg).ok()?[..])[12..]);
|
||||
Some(res)
|
||||
let mut res = EthereumAddress::default();
|
||||
res.0
|
||||
.copy_from_slice(&keccak_256(&secp256k1_ecdsa_recover(&s.0, &msg).ok()?[..])[12..]);
|
||||
Some(res)
|
||||
}
|
||||
|
||||
fn into_account_id(address: EthereumAddress) -> Result<T::AccountId, codec::Error> {
|
||||
@ -250,24 +242,21 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
}
|
||||
|
||||
fn do_claim(receiver: T::AccountId, ethereum_address: EthereumAddress) -> DispatchResult {
|
||||
let donor = Self::into_account_id(ethereum_address)
|
||||
.ok()
|
||||
let donor = Self::into_account_id(ethereum_address).ok()
|
||||
.ok_or(Error::<T, I>::AddressDecodingFailed)?;
|
||||
|
||||
let balance_due = CurrencyOf::<T, I>::free_balance(&donor);
|
||||
ensure!(
|
||||
balance_due >= CurrencyOf::<T, I>::minimum_balance(),
|
||||
Error::<T, I>::NoBalanceToClaim
|
||||
);
|
||||
ensure!(balance_due >= CurrencyOf::<T, I>::minimum_balance(),
|
||||
Error::<T, I>::NoBalanceToClaim);
|
||||
|
||||
let new_total = Total::<T, I>::get()
|
||||
.checked_sub(&balance_due)
|
||||
.ok_or(Error::<T, I>::PotUnderflow)?;
|
||||
|
||||
CurrencyOf::<T, I>::transfer(
|
||||
&donor,
|
||||
&receiver,
|
||||
balance_due,
|
||||
&donor,
|
||||
&receiver,
|
||||
balance_due,
|
||||
ExistenceRequirement::AllowDeath,
|
||||
)?;
|
||||
|
||||
@ -283,40 +272,28 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
.ok_or(Error::<T, I>::ArithmeticError)?;
|
||||
|
||||
T::VestingSchedule::add_vesting_schedule(
|
||||
&receiver,
|
||||
&receiver,
|
||||
vesting_balance,
|
||||
per_block_balance,
|
||||
T::BlockNumberProvider::current_block_number(),
|
||||
)?;
|
||||
}
|
||||
|
||||
let rank = if let Some(rank) =
|
||||
<pallet_ranked_collective::Pallet<T, I> as RankedMembers>::rank_of(&donor)
|
||||
{
|
||||
let rank = if let Some(rank) = <pallet_ranked_collective::Pallet::<T, I> as RankedMembers>::rank_of(&donor) {
|
||||
pallet_ranked_collective::Pallet::<T, I>::do_remove_member_from_rank(&donor, rank)?;
|
||||
let new_rank =
|
||||
match <pallet_ranked_collective::Pallet<T, I> as RankedMembers>::rank_of(&receiver)
|
||||
{
|
||||
Some(current_rank) if current_rank >= rank => current_rank,
|
||||
Some(current_rank) if current_rank < rank => {
|
||||
for _ in 0..rank - current_rank {
|
||||
pallet_ranked_collective::Pallet::<T, I>::do_promote_member(
|
||||
receiver.clone(),
|
||||
None,
|
||||
false,
|
||||
)?;
|
||||
}
|
||||
rank
|
||||
let new_rank = match <pallet_ranked_collective::Pallet::<T, I> as RankedMembers>::rank_of(&receiver) {
|
||||
Some(current_rank) if current_rank >= rank => current_rank,
|
||||
Some(current_rank) if current_rank < rank => {
|
||||
for _ in 0..rank - current_rank {
|
||||
pallet_ranked_collective::Pallet::<T, I>::do_promote_member(receiver.clone(), None, false)?;
|
||||
}
|
||||
_ => {
|
||||
pallet_ranked_collective::Pallet::<T, I>::do_add_member_to_rank(
|
||||
receiver.clone(),
|
||||
rank,
|
||||
false,
|
||||
)?;
|
||||
rank
|
||||
}
|
||||
};
|
||||
rank
|
||||
},
|
||||
_ => {
|
||||
pallet_ranked_collective::Pallet::<T, I>::do_add_member_to_rank(receiver.clone(), rank, false)?;
|
||||
rank
|
||||
},
|
||||
};
|
||||
<T as pallet::Config<I>>::MemberSwappedHandler::swapped(&donor, &receiver, new_rank);
|
||||
Some(new_rank)
|
||||
} else {
|
||||
@ -325,7 +302,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
|
||||
Total::<T, I>::put(new_total);
|
||||
Self::deposit_event(Event::<T, I>::Claimed {
|
||||
receiver,
|
||||
receiver,
|
||||
donor,
|
||||
amount: balance_due,
|
||||
rank,
|
||||
|
@ -4,113 +4,51 @@ use super::*;
|
||||
|
||||
pub use crate as ghost_claims;
|
||||
use frame_support::{
|
||||
derive_impl, parameter_types,
|
||||
traits::{ConstU16, ConstU64, PollStatus, Polling, WithdrawReasons},
|
||||
parameter_types, derive_impl,
|
||||
traits::{PollStatus, Polling, WithdrawReasons, ConstU16, ConstU64},
|
||||
};
|
||||
use frame_system::EnsureRootWithSuccess;
|
||||
pub use pallet_ranked_collective::{Rank, TallyOf};
|
||||
use sp_runtime::{traits::Convert, BuildStorage};
|
||||
use sp_runtime::{BuildStorage, traits::Convert};
|
||||
pub use pallet_ranked_collective::{TallyOf, Rank};
|
||||
|
||||
pub mod eth_keys {
|
||||
use crate::{mock::Test, EcdsaSignature, EthereumAddress};
|
||||
use codec::Encode;
|
||||
use crate::{
|
||||
mock::Test,
|
||||
EcdsaSignature, EthereumAddress,
|
||||
};
|
||||
use hex_literal::hex;
|
||||
use codec::Encode;
|
||||
|
||||
pub fn total_claims() -> u64 {
|
||||
10 + 100 + 1000
|
||||
}
|
||||
pub fn alice_account_id() -> <Test as frame_system::Config>::AccountId {
|
||||
69
|
||||
}
|
||||
pub fn bob_account_id() -> <Test as frame_system::Config>::AccountId {
|
||||
1337
|
||||
}
|
||||
pub fn total_claims() -> u64 { 10 + 100 + 1000 }
|
||||
pub fn alice_account_id() -> <Test as frame_system::Config>::AccountId { 69 }
|
||||
pub fn bob_account_id() -> <Test as frame_system::Config>::AccountId { 1337 }
|
||||
|
||||
pub fn first_eth_public_known() -> EthereumAddress {
|
||||
EthereumAddress(hex!("1A69d2D5568D1878023EeB121a73d33B9116A760"))
|
||||
}
|
||||
pub fn second_eth_public_known() -> EthereumAddress {
|
||||
EthereumAddress(hex!("2f86cfBED3fbc1eCf2989B9aE5fc019a837A9C12"))
|
||||
}
|
||||
pub fn third_eth_public_known() -> EthereumAddress {
|
||||
EthereumAddress(hex!("e83f67361Ac74D42A48E2DAfb6706eb047D8218D"))
|
||||
}
|
||||
pub fn fourth_eth_public_known() -> EthereumAddress {
|
||||
EthereumAddress(hex!("827ee4ad9b259b6fa1390ed60921508c78befd63"))
|
||||
}
|
||||
pub fn first_eth_public_known() -> EthereumAddress { EthereumAddress(hex!("1A69d2D5568D1878023EeB121a73d33B9116A760")) }
|
||||
pub fn second_eth_public_known() -> EthereumAddress { EthereumAddress(hex!("2f86cfBED3fbc1eCf2989B9aE5fc019a837A9C12")) }
|
||||
pub fn third_eth_public_known() -> EthereumAddress { EthereumAddress(hex!("e83f67361Ac74D42A48E2DAfb6706eb047D8218D")) }
|
||||
pub fn fourth_eth_public_known() -> EthereumAddress { EthereumAddress(hex!("827ee4ad9b259b6fa1390ed60921508c78befd63")) }
|
||||
|
||||
fn first_eth_private_key() -> libsecp256k1::SecretKey {
|
||||
libsecp256k1::SecretKey::parse(&hex!(
|
||||
"01c928771aea942a1e7ac06adf2b73dfbc9a25d9eaa516e3673116af7f345198"
|
||||
))
|
||||
.unwrap()
|
||||
}
|
||||
fn second_eth_private_key() -> libsecp256k1::SecretKey {
|
||||
libsecp256k1::SecretKey::parse(&hex!(
|
||||
"b19a435901872f817185f7234a1484eae837613f9d10cf21927a23c2d8cb9139"
|
||||
))
|
||||
.unwrap()
|
||||
}
|
||||
fn third_eth_private_key() -> libsecp256k1::SecretKey {
|
||||
libsecp256k1::SecretKey::parse(&hex!(
|
||||
"d3baf57b74d65719b2dc33f5a464176022d0cc5edbca002234229f3e733875fc"
|
||||
))
|
||||
.unwrap()
|
||||
}
|
||||
fn fourth_eth_private_key() -> libsecp256k1::SecretKey {
|
||||
libsecp256k1::SecretKey::parse(&hex!(
|
||||
"c4683d566436af6b58b4a59c8f501319226e85b21869bf93d5eeb4596d4791d4"
|
||||
))
|
||||
.unwrap()
|
||||
}
|
||||
fn wrong_eth_private_key() -> libsecp256k1::SecretKey {
|
||||
libsecp256k1::SecretKey::parse(&hex!(
|
||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||
))
|
||||
.unwrap()
|
||||
}
|
||||
fn first_eth_private_key() -> libsecp256k1::SecretKey { libsecp256k1::SecretKey::parse(&hex!("01c928771aea942a1e7ac06adf2b73dfbc9a25d9eaa516e3673116af7f345198")).unwrap() }
|
||||
fn second_eth_private_key() -> libsecp256k1::SecretKey { libsecp256k1::SecretKey::parse(&hex!("b19a435901872f817185f7234a1484eae837613f9d10cf21927a23c2d8cb9139")).unwrap() }
|
||||
fn third_eth_private_key() -> libsecp256k1::SecretKey { libsecp256k1::SecretKey::parse(&hex!("d3baf57b74d65719b2dc33f5a464176022d0cc5edbca002234229f3e733875fc")).unwrap() }
|
||||
fn fourth_eth_private_key() -> libsecp256k1::SecretKey { libsecp256k1::SecretKey::parse(&hex!("c4683d566436af6b58b4a59c8f501319226e85b21869bf93d5eeb4596d4791d4")).unwrap() }
|
||||
fn wrong_eth_private_key() -> libsecp256k1::SecretKey { libsecp256k1::SecretKey::parse(&hex!("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef")).unwrap() }
|
||||
|
||||
pub fn first_eth_public_key() -> EthereumAddress {
|
||||
crate::secp_utils::eth(&first_eth_private_key())
|
||||
}
|
||||
pub fn second_eth_public_key() -> EthereumAddress {
|
||||
crate::secp_utils::eth(&second_eth_private_key())
|
||||
}
|
||||
pub fn third_eth_public_key() -> EthereumAddress {
|
||||
crate::secp_utils::eth(&third_eth_private_key())
|
||||
}
|
||||
pub fn fourth_eth_public_key() -> EthereumAddress {
|
||||
crate::secp_utils::eth(&fourth_eth_private_key())
|
||||
}
|
||||
pub fn first_eth_public_key() -> EthereumAddress { crate::secp_utils::eth(&first_eth_private_key()) }
|
||||
pub fn second_eth_public_key() -> EthereumAddress { crate::secp_utils::eth(&second_eth_private_key()) }
|
||||
pub fn third_eth_public_key() -> EthereumAddress { crate::secp_utils::eth(&third_eth_private_key()) }
|
||||
pub fn fourth_eth_public_key() -> EthereumAddress { crate::secp_utils::eth(&fourth_eth_private_key()) }
|
||||
|
||||
pub fn first_account_id() -> <Test as frame_system::Config>::AccountId {
|
||||
crate::secp_utils::into_account_id::<Test, ()>(first_eth_public_key())
|
||||
}
|
||||
pub fn second_account_id() -> <Test as frame_system::Config>::AccountId {
|
||||
crate::secp_utils::into_account_id::<Test, ()>(second_eth_public_key())
|
||||
}
|
||||
pub fn third_account_id() -> <Test as frame_system::Config>::AccountId {
|
||||
crate::secp_utils::into_account_id::<Test, ()>(third_eth_public_key())
|
||||
}
|
||||
pub fn fourth_account_id() -> <Test as frame_system::Config>::AccountId {
|
||||
crate::secp_utils::into_account_id::<Test, ()>(fourth_eth_public_key())
|
||||
}
|
||||
pub fn first_account_id() -> <Test as frame_system::Config>::AccountId { crate::secp_utils::into_account_id::<Test, ()>(first_eth_public_key()) }
|
||||
pub fn second_account_id() -> <Test as frame_system::Config>::AccountId { crate::secp_utils::into_account_id::<Test, ()>(second_eth_public_key()) }
|
||||
pub fn third_account_id() -> <Test as frame_system::Config>::AccountId { crate::secp_utils::into_account_id::<Test, ()>(third_eth_public_key()) }
|
||||
pub fn fourth_account_id() -> <Test as frame_system::Config>::AccountId { crate::secp_utils::into_account_id::<Test, ()>(fourth_eth_public_key()) }
|
||||
|
||||
pub fn first_signature() -> EcdsaSignature {
|
||||
crate::secp_utils::sig::<Test, ()>(&first_eth_private_key(), &alice_account_id().encode())
|
||||
}
|
||||
pub fn second_signature() -> EcdsaSignature {
|
||||
crate::secp_utils::sig::<Test, ()>(&second_eth_private_key(), &alice_account_id().encode())
|
||||
}
|
||||
pub fn third_signature() -> EcdsaSignature {
|
||||
crate::secp_utils::sig::<Test, ()>(&third_eth_private_key(), &alice_account_id().encode())
|
||||
}
|
||||
pub fn fourth_signature() -> EcdsaSignature {
|
||||
crate::secp_utils::sig::<Test, ()>(&fourth_eth_private_key(), &bob_account_id().encode())
|
||||
}
|
||||
pub fn wrong_signature() -> EcdsaSignature {
|
||||
crate::secp_utils::sig::<Test, ()>(&wrong_eth_private_key(), &alice_account_id().encode())
|
||||
}
|
||||
pub fn first_signature() -> EcdsaSignature { crate::secp_utils::sig::<Test, ()>(&first_eth_private_key(), &alice_account_id().encode()) }
|
||||
pub fn second_signature() -> EcdsaSignature { crate::secp_utils::sig::<Test, ()>(&second_eth_private_key(), &alice_account_id().encode()) }
|
||||
pub fn third_signature() -> EcdsaSignature { crate::secp_utils::sig::<Test, ()>(&third_eth_private_key(), &alice_account_id().encode()) }
|
||||
pub fn fourth_signature() -> EcdsaSignature { crate::secp_utils::sig::<Test, ()>(&fourth_eth_private_key(), &bob_account_id().encode()) }
|
||||
pub fn wrong_signature() -> EcdsaSignature { crate::secp_utils::sig::<Test, ()>(&wrong_eth_private_key(), &alice_account_id().encode()) }
|
||||
}
|
||||
|
||||
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
|
||||
@ -128,9 +66,10 @@ impl pallet_balances::Config for Test {
|
||||
type AccountStore = System;
|
||||
}
|
||||
|
||||
|
||||
parameter_types! {
|
||||
pub const MinVestedTransfer: u64 = 1;
|
||||
pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons =
|
||||
pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons =
|
||||
WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE);
|
||||
}
|
||||
|
||||
@ -140,8 +79,9 @@ impl pallet_vesting::Config for Test {
|
||||
type BlockNumberToBalance = sp_runtime::traits::ConvertInto;
|
||||
type MinVestedTransfer = MinVestedTransfer;
|
||||
type WeightInfo = ();
|
||||
type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
|
||||
|
||||
type UnvestedFundsAllowedWithdrawReasons =
|
||||
UnvestedFundsAllowedWithdrawReasons;
|
||||
|
||||
type BlockNumberProvider = System;
|
||||
const MAX_VESTING_SCHEDULES: u32 = 28;
|
||||
}
|
||||
@ -208,7 +148,7 @@ impl pallet_ranked_collective::Config for Test {
|
||||
type PromoteOrigin = EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>;
|
||||
type DemoteOrigin = EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>;
|
||||
type ExchangeOrigin = EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>;
|
||||
|
||||
|
||||
type Polls = TestPolls;
|
||||
type MemberSwappedHandler = ();
|
||||
type MinRankOfClass = MinRankOfClass<MinRankOfClassDelta>;
|
||||
@ -260,8 +200,8 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
|
||||
(crate::mock::eth_keys::third_account_id(), 1000),
|
||||
],
|
||||
}
|
||||
.assimilate_storage(&mut t)
|
||||
.unwrap();
|
||||
.assimilate_storage(&mut t)
|
||||
.unwrap();
|
||||
|
||||
ghost_claims::GenesisConfig::<Test> {
|
||||
total: crate::mock::eth_keys::total_claims(),
|
||||
@ -270,8 +210,8 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
|
||||
(crate::mock::eth_keys::third_account_id(), 3),
|
||||
],
|
||||
}
|
||||
.assimilate_storage(&mut t)
|
||||
.unwrap();
|
||||
.assimilate_storage(&mut t)
|
||||
.unwrap();
|
||||
|
||||
let mut ext = sp_io::TestExternalities::new(t);
|
||||
ext.execute_with(|| {
|
||||
|
@ -8,8 +8,7 @@ pub fn public(secret: &libsecp256k1::SecretKey) -> libsecp256k1::PublicKey {
|
||||
|
||||
pub fn eth(secret: &libsecp256k1::SecretKey) -> EthereumAddress {
|
||||
let mut res = EthereumAddress::default();
|
||||
res.0
|
||||
.copy_from_slice(&keccak_256(&public(secret).serialize()[1..65])[12..]);
|
||||
res.0.copy_from_slice(&keccak_256(&public(secret).serialize()[1..65])[12..]);
|
||||
res
|
||||
}
|
||||
|
||||
@ -19,14 +18,17 @@ pub fn into_account_id<T: Config<I>, I: 'static>(address: EthereumAddress) -> T:
|
||||
}
|
||||
|
||||
pub fn sig<T: Config<I>, I: 'static>(
|
||||
secret: &libsecp256k1::SecretKey,
|
||||
secret: &libsecp256k1::SecretKey,
|
||||
what: &[u8],
|
||||
) -> EcdsaSignature {
|
||||
let msg = keccak_256(&super::Pallet::<T, I>::ethereum_signable_message(
|
||||
&crate::to_ascii_hex(what)[..],
|
||||
&crate::to_ascii_hex(what)[..],
|
||||
));
|
||||
|
||||
let (sig, recovery_id) = libsecp256k1::sign(&libsecp256k1::Message::parse(&msg), secret);
|
||||
let (sig, recovery_id) = libsecp256k1::sign(
|
||||
&libsecp256k1::Message::parse(&msg),
|
||||
secret,
|
||||
);
|
||||
|
||||
let mut r = [0u8; 65];
|
||||
r[0..64].copy_from_slice(&sig.serialize()[..]);
|
||||
|
@ -1,19 +1,21 @@
|
||||
#![cfg(test)]
|
||||
|
||||
use super::*;
|
||||
use frame_support::{assert_err, assert_ok};
|
||||
use hex_literal::hex;
|
||||
use mock::{
|
||||
new_test_ext, ghost_claims,
|
||||
Test, System, Balances, Club, Vesting, Claims, RuntimeOrigin, RuntimeEvent,
|
||||
eth_keys::{
|
||||
alice_account_id, bob_account_id, first_account_id, first_eth_public_key,
|
||||
first_eth_public_known, first_signature, fourth_account_id, fourth_eth_public_key,
|
||||
fourth_eth_public_known, fourth_signature, second_account_id, second_eth_public_key,
|
||||
second_eth_public_known, second_signature, third_account_id, third_eth_public_key,
|
||||
third_eth_public_known, third_signature, total_claims, wrong_signature,
|
||||
},
|
||||
ghost_claims, new_test_ext, Balances, Claims, Club, RuntimeEvent, RuntimeOrigin, System, Test,
|
||||
Vesting,
|
||||
alice_account_id, total_claims, first_eth_public_known,
|
||||
first_eth_public_key, first_account_id, first_signature,
|
||||
second_eth_public_known, second_eth_public_key, second_account_id,
|
||||
second_signature, third_eth_public_known, third_eth_public_key,
|
||||
third_account_id, third_signature, fourth_eth_public_known,
|
||||
fourth_eth_public_key, fourth_account_id, fourth_signature,
|
||||
wrong_signature, bob_account_id,
|
||||
}
|
||||
};
|
||||
use hex_literal::hex;
|
||||
use frame_support::{assert_err, assert_ok};
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn serde_works() {
|
||||
@ -39,12 +41,12 @@ fn basic_setup_works() {
|
||||
assert_eq!(Balances::usable_balance(&first_account_id()), 10);
|
||||
assert_eq!(Balances::usable_balance(&second_account_id()), 100);
|
||||
assert_eq!(Balances::usable_balance(&third_account_id()), 1000);
|
||||
|
||||
|
||||
assert_eq!(Club::rank_of(&alice_account_id()), None);
|
||||
assert_eq!(Club::rank_of(&first_account_id()), None);
|
||||
assert_eq!(Club::rank_of(&second_account_id()), Some(1));
|
||||
assert_eq!(Club::rank_of(&third_account_id()), Some(3));
|
||||
|
||||
|
||||
assert_eq!(Vesting::vesting_balance(&alice_account_id()), None);
|
||||
assert_eq!(ghost_claims::Total::<Test, ()>::get(), total_claims());
|
||||
});
|
||||
@ -54,10 +56,9 @@ fn basic_setup_works() {
|
||||
fn small_claiming_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Claims::claim(
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
first_eth_public_key(),
|
||||
first_signature()
|
||||
));
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
first_eth_public_key(),
|
||||
first_signature()));
|
||||
|
||||
assert_eq!(Balances::usable_balance(&alice_account_id()), 10);
|
||||
assert_eq!(Balances::usable_balance(&first_account_id()), 0);
|
||||
@ -76,9 +77,9 @@ fn small_claiming_works() {
|
||||
fn medium_claiming_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Claims::claim(
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
second_eth_public_key(),
|
||||
second_signature(),
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
second_eth_public_key(),
|
||||
second_signature(),
|
||||
));
|
||||
|
||||
assert_eq!(Balances::usable_balance(&alice_account_id()), 100);
|
||||
@ -98,9 +99,9 @@ fn medium_claiming_works() {
|
||||
fn big_claiming_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Claims::claim(
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
third_eth_public_key(),
|
||||
third_signature(),
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
third_eth_public_key(),
|
||||
third_signature(),
|
||||
));
|
||||
|
||||
assert_eq!(Balances::usable_balance(&alice_account_id()), 200);
|
||||
@ -112,15 +113,11 @@ fn big_claiming_works() {
|
||||
assert_eq!(Club::rank_of(&third_account_id()), None);
|
||||
|
||||
assert_eq!(Vesting::vesting_balance(&alice_account_id()), Some(800));
|
||||
assert_eq!(
|
||||
ghost_claims::Total::<Test, ()>::get(),
|
||||
total_claims() - 1000
|
||||
);
|
||||
assert_eq!(ghost_claims::Total::<Test, ()>::get(), total_claims() - 1000);
|
||||
assert_ok!(Balances::transfer_allow_death(
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
bob_account_id(),
|
||||
200
|
||||
));
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
bob_account_id(),
|
||||
200));
|
||||
})
|
||||
}
|
||||
|
||||
@ -128,19 +125,19 @@ fn big_claiming_works() {
|
||||
fn multiple_accounts_claiming_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Claims::claim(
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
first_eth_public_key(),
|
||||
first_signature(),
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
first_eth_public_key(),
|
||||
first_signature(),
|
||||
));
|
||||
assert_ok!(Claims::claim(
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
second_eth_public_key(),
|
||||
second_signature(),
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
second_eth_public_key(),
|
||||
second_signature(),
|
||||
));
|
||||
assert_ok!(Claims::claim(
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
third_eth_public_key(),
|
||||
third_signature(),
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
third_eth_public_key(),
|
||||
third_signature(),
|
||||
));
|
||||
|
||||
assert_eq!(Balances::usable_balance(&alice_account_id()), 310);
|
||||
@ -160,19 +157,19 @@ fn multiple_accounts_claiming_works() {
|
||||
fn multiple_accounts_reverese_claiming_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Claims::claim(
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
third_eth_public_key(),
|
||||
third_signature(),
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
third_eth_public_key(),
|
||||
third_signature(),
|
||||
));
|
||||
assert_ok!(Claims::claim(
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
second_eth_public_key(),
|
||||
second_signature(),
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
second_eth_public_key(),
|
||||
second_signature(),
|
||||
));
|
||||
assert_ok!(Claims::claim(
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
first_eth_public_key(),
|
||||
first_signature(),
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
first_eth_public_key(),
|
||||
first_signature(),
|
||||
));
|
||||
|
||||
assert_eq!(Balances::usable_balance(&alice_account_id()), 310);
|
||||
@ -191,14 +188,11 @@ fn multiple_accounts_reverese_claiming_works() {
|
||||
#[test]
|
||||
fn cannot_claim_with_bad_signature() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_err!(
|
||||
Claims::claim(
|
||||
assert_err!(Claims::claim(
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
first_eth_public_key(),
|
||||
wrong_signature()
|
||||
),
|
||||
crate::Error::<Test>::InvalidEthereumAddress
|
||||
);
|
||||
wrong_signature()),
|
||||
crate::Error::<Test>::InvalidEthereumAddress);
|
||||
|
||||
assert_eq!(Balances::usable_balance(&alice_account_id()), 0);
|
||||
assert_eq!(Balances::usable_balance(&first_account_id()), 10);
|
||||
@ -218,14 +212,11 @@ fn cannot_claim_with_bad_signature() {
|
||||
#[test]
|
||||
fn cannot_claim_with_wrong_address() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_err!(
|
||||
Claims::claim(
|
||||
assert_err!(Claims::claim(
|
||||
RuntimeOrigin::signed(bob_account_id()),
|
||||
first_eth_public_key(),
|
||||
first_signature()
|
||||
),
|
||||
crate::Error::<Test>::InvalidEthereumAddress
|
||||
);
|
||||
first_signature()),
|
||||
crate::Error::<Test>::InvalidEthereumAddress);
|
||||
|
||||
assert_eq!(Balances::usable_balance(&bob_account_id()), 0);
|
||||
assert_eq!(Balances::usable_balance(&alice_account_id()), 0);
|
||||
@ -246,14 +237,11 @@ fn cannot_claim_with_wrong_address() {
|
||||
#[test]
|
||||
fn cannot_claim_nothing() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_err!(
|
||||
Claims::claim(
|
||||
assert_err!(Claims::claim(
|
||||
RuntimeOrigin::signed(bob_account_id()),
|
||||
fourth_eth_public_key(),
|
||||
fourth_signature()
|
||||
),
|
||||
crate::Error::<Test>::NoBalanceToClaim
|
||||
);
|
||||
fourth_signature()),
|
||||
crate::Error::<Test>::NoBalanceToClaim);
|
||||
assert_eq!(Balances::usable_balance(&bob_account_id()), 0);
|
||||
assert_eq!(Balances::usable_balance(&fourth_account_id()), 0);
|
||||
assert_eq!(Vesting::vesting_balance(&bob_account_id()), None);
|
||||
@ -271,15 +259,16 @@ fn event_emitted_during_claim() {
|
||||
System::reset_events();
|
||||
assert_eq!(System::event_count(), 0);
|
||||
assert_ok!(Claims::claim(
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
third_eth_public_key(),
|
||||
third_signature(),
|
||||
RuntimeOrigin::signed(alice_account_id()),
|
||||
third_eth_public_key(),
|
||||
third_signature(),
|
||||
));
|
||||
System::assert_has_event(RuntimeEvent::Claims(crate::Event::Claimed {
|
||||
receiver: alice_account_id(),
|
||||
donor: account,
|
||||
amount,
|
||||
rank,
|
||||
}));
|
||||
System::assert_has_event(RuntimeEvent::Claims(
|
||||
crate::Event::Claimed {
|
||||
receiver: alice_account_id(),
|
||||
donor: account,
|
||||
amount,
|
||||
rank,
|
||||
}));
|
||||
})
|
||||
}
|
||||
|
@ -1,104 +1,9 @@
|
||||
// This file is part of Ghost Network.
|
||||
use frame_support::weights::Weight;
|
||||
|
||||
// Ghost Network 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.
|
||||
|
||||
// Ghost Network 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 Ghost Network. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Autogenerated weights for `ghost_claims`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
|
||||
//! DATE: 2024-08-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
|
||||
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/ghost
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=casper-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=ghost_claims
|
||||
// --extrinsic=*
|
||||
// --wasm-execution=compiled
|
||||
// --heap-pages=4096
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/casper/src/weights/ghost_claims.rs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use frame_support::{
|
||||
traits::Get,
|
||||
weights::{Weight, constants::RocksDbWeight},
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// Weight functions needed for `ghost_claims`.
|
||||
pub trait WeightInfo {
|
||||
fn claim() -> Weight;
|
||||
}
|
||||
|
||||
/// Weight for ghost_claims using the Substrate node and recommended hardware.
|
||||
pub struct SubstrateWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
/// Storage: `System::Account` (r:2 w:2)
|
||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
||||
/// Storage: `GhostClaims::Total` (r:1 w:1)
|
||||
/// Proof: `GhostClaims::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `CultCollective::Members` (r:2 w:2)
|
||||
/// Proof: `CultCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CultCollective::MemberCount` (r:6 w:6)
|
||||
/// Proof: `CultCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CultCollective::IdToIndex` (r:6 w:12)
|
||||
/// Proof: `CultCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CultCollective::IndexToId` (r:0 w:6)
|
||||
/// Proof: `CultCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
fn claim() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `896`
|
||||
// Estimated: `16164`
|
||||
// Minimum execution time: 754_086_000 picoseconds.
|
||||
Weight::from_parts(756_147_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 16164))
|
||||
.saturating_add(T::DbWeight::get().reads(17))
|
||||
.saturating_add(T::DbWeight::get().writes(29))
|
||||
}
|
||||
fn claim() -> Weight;
|
||||
}
|
||||
|
||||
impl WeightInfo for () {
|
||||
/// Storage: `System::Account` (r:2 w:2)
|
||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
||||
/// Storage: `GhostClaims::Total` (r:1 w:1)
|
||||
/// Proof: `GhostClaims::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `CultCollective::Members` (r:2 w:2)
|
||||
/// Proof: `CultCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CultCollective::MemberCount` (r:6 w:6)
|
||||
/// Proof: `CultCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CultCollective::IdToIndex` (r:6 w:12)
|
||||
/// Proof: `CultCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CultCollective::IndexToId` (r:0 w:6)
|
||||
/// Proof: `CultCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
fn claim() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `896`
|
||||
// Estimated: `16164`
|
||||
// Minimum execution time: 754_086_000 picoseconds.
|
||||
Weight::from_parts(756_147_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 16164))
|
||||
.saturating_add(RocksDbWeight::get().reads(17))
|
||||
.saturating_add(RocksDbWeight::get().writes(29))
|
||||
}
|
||||
fn claim() -> Weight { Weight::zero() }
|
||||
}
|
||||
|
44
pallets/networks/Cargo.toml
Normal file → Executable file
@ -1,8 +1,8 @@
|
||||
[package]
|
||||
name = "ghost-networks"
|
||||
version = "0.1.16"
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
@ -10,48 +10,40 @@ repository.workspace = true
|
||||
[dependencies]
|
||||
scale-info = { workspace = true, features = ["derive"] }
|
||||
codec = { workspace = true, features = ["max-encoded-len"] }
|
||||
num-traits = { workspace = true }
|
||||
|
||||
frame-benchmarking = { workspace = true, optional = true }
|
||||
frame-support = { workspace = true }
|
||||
frame-system = { workspace = true }
|
||||
pallet-staking = { workspace = true }
|
||||
sp-runtime = { workspace = true }
|
||||
sp-std = { workspace = true }
|
||||
ghost-traits = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
primitives = { workspace = true }
|
||||
sp-io = { workspace = true }
|
||||
pallet-balances = { workspace = true }
|
||||
pallet-staking-reward-curve = { workspace = true }
|
||||
sp-io = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"scale-info/std",
|
||||
"codec/std",
|
||||
"num-traits/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
"frame-benchmarking?/std",
|
||||
"sp-runtime/std",
|
||||
"sp-std/std",
|
||||
"sp-io/std",
|
||||
"ghost-traits/std",
|
||||
"pallet-staking/std",
|
||||
"pallet-balances/std",
|
||||
"scale-info/std",
|
||||
"codec/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
"frame-benchmarking?/std",
|
||||
"sp-runtime/std",
|
||||
"sp-std/std",
|
||||
"sp-io/std",
|
||||
"ghost-traits/std",
|
||||
"pallet-balances/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"frame-benchmarking/runtime-benchmarks",
|
||||
"frame-support/runtime-benchmarks",
|
||||
"frame-system/runtime-benchmarks",
|
||||
"sp-runtime/runtime-benchmarks",
|
||||
"pallet-staking/runtime-benchmarks",
|
||||
"frame-benchmarking/runtime-benchmarks",
|
||||
"frame-support/runtime-benchmarks",
|
||||
"frame-system/runtime-benchmarks",
|
||||
"sp-runtime/runtime-benchmarks",
|
||||
]
|
||||
try-runtime = [
|
||||
"frame-support/try-runtime",
|
||||
"frame-system/try-runtime",
|
||||
"pallet-staking/try-runtime",
|
||||
"pallet-balances/try-runtime",
|
||||
"frame-support/try-runtime",
|
||||
"frame-system/try-runtime",
|
||||
]
|
||||
|
88
pallets/networks/src/benchmarking.rs
Normal file → Executable file
@ -8,44 +8,31 @@ use sp_runtime::Saturating;
|
||||
|
||||
const MAX_NAME_LEN: u32 = 20;
|
||||
const MAX_ENDPOINT_LEN: u32 = 150;
|
||||
const MAX_ENDPOINT_NUMBER: u32 = 20;
|
||||
|
||||
fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
|
||||
frame_system::Pallet::<T>::assert_last_event(generic_event.into());
|
||||
}
|
||||
|
||||
fn prepare_network<T: Config>(
|
||||
n: u32,
|
||||
m: u32,
|
||||
k: u32,
|
||||
n: u32, m: u32,
|
||||
) -> (<T as module::Config>::NetworkId, NetworkData) {
|
||||
let chain_id: <T as module::Config>::NetworkId = Default::default();
|
||||
let chain_id = chain_id.saturating_add((n + m).into());
|
||||
|
||||
let mut gatekeeper = b"0x".to_vec();
|
||||
for i in 0..40 {
|
||||
gatekeeper.push(i);
|
||||
}
|
||||
for i in 0..40 { gatekeeper.push(i); }
|
||||
|
||||
let mut topic_name = b"0x".to_vec();
|
||||
for i in 0..64 {
|
||||
topic_name.push(i);
|
||||
}
|
||||
|
||||
let mut default_endpoints = sp_std::vec![];
|
||||
for _ in 0..(k as usize) {
|
||||
default_endpoints.push(sp_std::vec![0x69; m as usize]);
|
||||
}
|
||||
for i in 0..64 { topic_name.push(i); }
|
||||
|
||||
let network = NetworkData {
|
||||
chain_name: sp_std::vec![0x69; n as usize],
|
||||
default_endpoints,
|
||||
default_endpoint: sp_std::vec![0x69; m as usize],
|
||||
gatekeeper,
|
||||
topic_name,
|
||||
finality_delay: Some(69),
|
||||
release_delay: Some(69),
|
||||
network_type: NetworkType::Evm,
|
||||
finality_delay: 69,
|
||||
rate_limit_delay: 69,
|
||||
block_distance: 69,
|
||||
incoming_fee: 0,
|
||||
outgoing_fee: 0,
|
||||
};
|
||||
@ -63,11 +50,8 @@ fn create_network<T: Config>(
|
||||
let authority = T::RegisterOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
GhostNetworks::<T>::register_network(
|
||||
authority.clone(),
|
||||
chain_id.clone(),
|
||||
network.clone(),
|
||||
)
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
authority.clone(), chain_id.clone(), network.clone()
|
||||
).map_err(|_| BenchmarkError::Weightless)?;
|
||||
network
|
||||
}
|
||||
};
|
||||
@ -79,9 +63,8 @@ benchmarks! {
|
||||
register_network {
|
||||
let i in 1 .. MAX_NAME_LEN;
|
||||
let j in 1 .. MAX_ENDPOINT_LEN;
|
||||
let k in 1 .. MAX_ENDPOINT_NUMBER;
|
||||
|
||||
let (chain_id, network) = prepare_network::<T>(i, j, k);
|
||||
let (chain_id, network) = prepare_network::<T>(i, j);
|
||||
let authority = T::RegisterOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
let prev_network = GhostNetworks::<T>::networks(chain_id.clone());
|
||||
@ -96,7 +79,7 @@ benchmarks! {
|
||||
update_network_name {
|
||||
let n in 1 .. MAX_NAME_LEN;
|
||||
let name = sp_std::vec![0x42; n as usize];
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1, 1);
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1);
|
||||
let authority = T::UpdateOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
let prev_network = create_network::<T>(chain_id.clone(), network.clone())?;
|
||||
@ -110,25 +93,22 @@ benchmarks! {
|
||||
|
||||
update_network_endpoint {
|
||||
let n in 1 .. MAX_ENDPOINT_LEN;
|
||||
let index_to_update = 0u32;
|
||||
let endpoint = sp_std::vec![0x42; n as usize];
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1, 1);
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1);
|
||||
let authority = T::UpdateOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
let prev_network = create_network::<T>(chain_id.clone(), network.clone())?;
|
||||
}: _<T::RuntimeOrigin>(authority, chain_id.clone(), Some(index_to_update), Some(endpoint.clone()))
|
||||
}: _<T::RuntimeOrigin>(authority, chain_id.clone(), endpoint.clone())
|
||||
verify {
|
||||
assert_last_event::<T>(Event::NetworkEndpointUpdated {
|
||||
chain_id: chain_id.clone(),
|
||||
index: index_to_update,
|
||||
endpoint,
|
||||
chain_id: chain_id.clone(), default_endpoint: endpoint,
|
||||
}.into());
|
||||
assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), prev_network);
|
||||
}
|
||||
|
||||
update_network_finality_delay {
|
||||
let delay = 1337;
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1, 1);
|
||||
let delay = Some(1337);
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1);
|
||||
let authority = T::UpdateOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
let prev_network = create_network::<T>(chain_id.clone(), network.clone())?;
|
||||
@ -140,37 +120,23 @@ benchmarks! {
|
||||
assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), prev_network);
|
||||
}
|
||||
|
||||
update_network_rate_limit_delay {
|
||||
let rate_limit = 1337;
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1, 1);
|
||||
update_network_release_delay {
|
||||
let delay = Some(1337);
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1);
|
||||
let authority = T::UpdateOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
let prev_network = create_network::<T>(chain_id.clone(), network.clone())?;
|
||||
}: _<T::RuntimeOrigin>(authority, chain_id.clone(), rate_limit)
|
||||
}: _<T::RuntimeOrigin>(authority, chain_id.clone(), delay)
|
||||
verify {
|
||||
assert_last_event::<T>(Event::NetworkRateLimitDelayUpdated {
|
||||
chain_id: chain_id.clone(), rate_limit_delay: rate_limit,
|
||||
}.into());
|
||||
assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), prev_network);
|
||||
}
|
||||
|
||||
update_network_block_distance {
|
||||
let block_distance = 1337;
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1, 1);
|
||||
let authority = T::UpdateOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
let prev_network = create_network::<T>(chain_id.clone(), network.clone())?;
|
||||
}: _<T::RuntimeOrigin>(authority, chain_id.clone(), block_distance)
|
||||
verify {
|
||||
assert_last_event::<T>(Event::NetworkBlockDistanceUpdated {
|
||||
chain_id: chain_id.clone(), block_distance,
|
||||
assert_last_event::<T>(Event::NetworkReleaseDelayUpdated {
|
||||
chain_id: chain_id.clone(), release_delay: delay,
|
||||
}.into());
|
||||
assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), prev_network);
|
||||
}
|
||||
|
||||
update_network_type {
|
||||
let network_type = NetworkType::Utxo;
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1, 1);
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1);
|
||||
let authority = T::UpdateOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
let prev_network = create_network::<T>(chain_id.clone(), network.clone())?;
|
||||
@ -185,7 +151,7 @@ benchmarks! {
|
||||
update_network_gatekeeper {
|
||||
let mut gatekeeper = b"0x".to_vec();
|
||||
for i in 0..40 { gatekeeper.push(i + 1); }
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1, 1);
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1);
|
||||
let authority = T::UpdateOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
let prev_network = create_network::<T>(chain_id.clone(), network.clone())?;
|
||||
@ -199,7 +165,7 @@ benchmarks! {
|
||||
|
||||
update_network_topic_name {
|
||||
let topic_name = b"0x9876543219876543219876543219876543219876543219876543219876543219".to_vec();
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1, 1);
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1);
|
||||
let authority = T::UpdateOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
let prev_network = create_network::<T>(chain_id.clone(), network.clone())?;
|
||||
@ -213,7 +179,7 @@ benchmarks! {
|
||||
|
||||
update_incoming_network_fee {
|
||||
let incoming_fee = 1337;
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1, 1);
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1);
|
||||
let authority = T::UpdateOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
let prev_network = create_network::<T>(chain_id.clone(), network.clone())?;
|
||||
@ -227,7 +193,7 @@ benchmarks! {
|
||||
|
||||
update_outgoing_network_fee {
|
||||
let outgoing_fee = 1337;
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1, 1);
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1);
|
||||
let authority = T::UpdateOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
let prev_network = create_network::<T>(chain_id.clone(), network.clone())?;
|
||||
@ -240,7 +206,7 @@ benchmarks! {
|
||||
}
|
||||
|
||||
remove_network {
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1, 1);
|
||||
let (chain_id, network) = prepare_network::<T>(1, 1);
|
||||
let authority = T::RemoveOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
let prev_network = create_network::<T>(chain_id.clone(), network.clone())?;
|
||||
|
488
pallets/networks/src/lib.rs
Normal file → Executable file
@ -4,29 +4,25 @@
|
||||
|
||||
use frame_support::{
|
||||
pallet_prelude::*,
|
||||
storage::PrefixIterator,
|
||||
traits::{tokens::fungible::Inspect, EnsureOrigin},
|
||||
storage::PrefixIterator, traits::EnsureOrigin,
|
||||
};
|
||||
use frame_system::pallet_prelude::*;
|
||||
use scale_info::TypeInfo;
|
||||
|
||||
use sp_runtime::{
|
||||
curve::PiecewiseLinear,
|
||||
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedSub, Member},
|
||||
traits::{AtLeast32BitUnsigned, Member},
|
||||
DispatchResult,
|
||||
};
|
||||
use sp_std::{convert::TryInto, prelude::*};
|
||||
use sp_std::prelude::*;
|
||||
|
||||
pub use ghost_traits::networks::{
|
||||
NetworkDataBasicHandler, NetworkDataInspectHandler, NetworkDataMutateHandler,
|
||||
NetworkDataBasicHandler, NetworkDataInspectHandler,
|
||||
NetworkDataMutateHandler,
|
||||
};
|
||||
|
||||
mod math;
|
||||
mod weights;
|
||||
|
||||
pub use crate::weights::WeightInfo;
|
||||
use math::MulDiv;
|
||||
pub use module::*;
|
||||
pub use crate::weights::WeightInfo;
|
||||
|
||||
#[cfg(any(feature = "runtime-benchmarks", test))]
|
||||
mod benchmarking;
|
||||
@ -35,9 +31,6 @@ mod mock;
|
||||
#[cfg(all(feature = "std", test))]
|
||||
mod tests;
|
||||
|
||||
pub type BalanceOf<T> =
|
||||
<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
|
||||
|
||||
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||
pub enum NetworkType {
|
||||
Evm = 0,
|
||||
@ -46,78 +39,22 @@ pub enum NetworkType {
|
||||
}
|
||||
|
||||
impl Default for NetworkType {
|
||||
fn default() -> Self {
|
||||
NetworkType::Evm
|
||||
}
|
||||
fn default() -> Self { NetworkType::Evm }
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||
pub struct NetworkData {
|
||||
pub chain_name: Vec<u8>,
|
||||
pub default_endpoints: Vec<Vec<u8>>,
|
||||
pub default_endpoint: Vec<u8>,
|
||||
pub gatekeeper: Vec<u8>,
|
||||
pub topic_name: Vec<u8>,
|
||||
pub finality_delay: Option<u64>,
|
||||
pub release_delay: Option<u64>,
|
||||
pub network_type: NetworkType,
|
||||
pub finality_delay: u64,
|
||||
pub rate_limit_delay: u64,
|
||||
pub block_distance: u64,
|
||||
pub incoming_fee: u32,
|
||||
pub outgoing_fee: u32,
|
||||
}
|
||||
|
||||
#[derive(Default, Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||
pub struct BridgeAdjustment<Balance> {
|
||||
pub bridged_out: Balance,
|
||||
pub bridged_in: Balance,
|
||||
}
|
||||
|
||||
pub struct BridgedInflationCurve<RewardCurve, T>(core::marker::PhantomData<(RewardCurve, T)>);
|
||||
impl<Balance, RewardCurve, T> pallet_staking::EraPayout<Balance>
|
||||
for BridgedInflationCurve<RewardCurve, T>
|
||||
where
|
||||
Balance: Default
|
||||
+ Copy
|
||||
+ From<BalanceOf<T>>
|
||||
+ AtLeast32BitUnsigned
|
||||
+ num_traits::ops::wrapping::WrappingAdd
|
||||
+ num_traits::ops::overflowing::OverflowingAdd
|
||||
+ sp_std::ops::AddAssign
|
||||
+ sp_std::ops::Not<Output = Balance>
|
||||
+ sp_std::ops::Shl<Output = Balance>
|
||||
+ sp_std::ops::Shr<Output = Balance>
|
||||
+ sp_std::ops::BitAnd<Balance, Output = Balance>,
|
||||
RewardCurve: Get<&'static PiecewiseLinear<'static>>,
|
||||
T: Config,
|
||||
{
|
||||
fn era_payout(
|
||||
total_staked: Balance,
|
||||
total_issuance: Balance,
|
||||
_era_duration_in_millis: u64,
|
||||
) -> (Balance, Balance) {
|
||||
let reward_curve = RewardCurve::get();
|
||||
let bridged_imbalance = BridgedImbalance::<T>::get();
|
||||
let accumulated_commission = AccumulatedCommission::<T>::get();
|
||||
|
||||
let accumulated_commission: Balance = accumulated_commission.into();
|
||||
let adjusted_issuance: Balance = total_issuance
|
||||
.saturating_add(bridged_imbalance.bridged_out.into())
|
||||
.saturating_sub(bridged_imbalance.bridged_in.into());
|
||||
|
||||
NullifyNeeded::<T>::set(true);
|
||||
|
||||
let estimated_reward =
|
||||
reward_curve.calculate_for_fraction_times_denominator(total_staked, adjusted_issuance);
|
||||
let payout = MulDiv::<Balance>::calculate(
|
||||
estimated_reward,
|
||||
accumulated_commission,
|
||||
adjusted_issuance,
|
||||
);
|
||||
let rest_payout = accumulated_commission.saturating_sub(payout);
|
||||
|
||||
(payout, rest_payout)
|
||||
}
|
||||
}
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod module {
|
||||
use super::*;
|
||||
@ -126,9 +63,6 @@ pub mod module {
|
||||
pub trait Config: frame_system::Config {
|
||||
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
|
||||
/// The type used for the internal balance storage.
|
||||
type Currency: Inspect<Self::AccountId>;
|
||||
|
||||
/// The type used as a unique network id.
|
||||
type NetworkId: Parameter
|
||||
+ Member
|
||||
@ -140,7 +74,7 @@ pub mod module {
|
||||
+ TypeInfo
|
||||
+ MaybeSerializeDeserialize
|
||||
+ MaxEncodedLen;
|
||||
|
||||
|
||||
/// The origin required to register new network.
|
||||
type RegisterOrigin: EnsureOrigin<Self::RuntimeOrigin>;
|
||||
/// The origin required to update network information.
|
||||
@ -167,87 +101,24 @@ pub mod module {
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(crate) fn deposit_event)]
|
||||
pub enum Event<T: Config> {
|
||||
NetworkRegistered {
|
||||
chain_id: T::NetworkId,
|
||||
network: NetworkData,
|
||||
},
|
||||
NetworkNameUpdated {
|
||||
chain_id: T::NetworkId,
|
||||
chain_name: Vec<u8>,
|
||||
},
|
||||
NetworkEndpointUpdated {
|
||||
chain_id: T::NetworkId,
|
||||
index: u32,
|
||||
endpoint: Vec<u8>,
|
||||
},
|
||||
NetworkEndpointRemoved {
|
||||
chain_id: T::NetworkId,
|
||||
index: u32,
|
||||
},
|
||||
NetworkEndpointAdded {
|
||||
chain_id: T::NetworkId,
|
||||
endpoint: Vec<u8>,
|
||||
},
|
||||
NetworkFinalityDelayUpdated {
|
||||
chain_id: T::NetworkId,
|
||||
finality_delay: u64,
|
||||
},
|
||||
NetworkRateLimitDelayUpdated {
|
||||
chain_id: T::NetworkId,
|
||||
rate_limit_delay: u64,
|
||||
},
|
||||
NetworkBlockDistanceUpdated {
|
||||
chain_id: T::NetworkId,
|
||||
block_distance: u64,
|
||||
},
|
||||
NetworkTypeUpdated {
|
||||
chain_id: T::NetworkId,
|
||||
network_type: NetworkType,
|
||||
},
|
||||
NetworkGatekeeperUpdated {
|
||||
chain_id: T::NetworkId,
|
||||
gatekeeper: Vec<u8>,
|
||||
},
|
||||
NetworkTopicNameUpdated {
|
||||
chain_id: T::NetworkId,
|
||||
topic_name: Vec<u8>,
|
||||
},
|
||||
NetworkIncomingFeeUpdated {
|
||||
chain_id: T::NetworkId,
|
||||
incoming_fee: u32,
|
||||
},
|
||||
NetworkOutgoingFeeUpdated {
|
||||
chain_id: T::NetworkId,
|
||||
outgoing_fee: u32,
|
||||
},
|
||||
NetworkRemoved {
|
||||
chain_id: T::NetworkId,
|
||||
},
|
||||
NetworkRegistered { chain_id: T::NetworkId, network: NetworkData },
|
||||
NetworkNameUpdated { chain_id: T::NetworkId, chain_name: Vec<u8> },
|
||||
NetworkEndpointUpdated { chain_id: T::NetworkId, default_endpoint: Vec<u8> },
|
||||
NetworkFinalityDelayUpdated { chain_id: T::NetworkId, finality_delay: Option<u64> },
|
||||
NetworkReleaseDelayUpdated { chain_id: T::NetworkId, release_delay: Option<u64> },
|
||||
NetworkTypeUpdated { chain_id: T::NetworkId, network_type: NetworkType },
|
||||
NetworkGatekeeperUpdated { chain_id: T::NetworkId, gatekeeper: Vec<u8> },
|
||||
NetworkTopicNameUpdated { chain_id: T::NetworkId, topic_name: Vec<u8> },
|
||||
NetworkIncomingFeeUpdated { chain_id: T::NetworkId, incoming_fee: u32 },
|
||||
NetworkOutgoingFeeUpdated { chain_id: T::NetworkId, outgoing_fee: u32 },
|
||||
NetworkRemoved { chain_id: T::NetworkId },
|
||||
}
|
||||
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn nullify_needed)]
|
||||
pub type NullifyNeeded<T: Config> = StorageValue<_, bool, ValueQuery>;
|
||||
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn bridged_imbalance)]
|
||||
pub type BridgedImbalance<T: Config> =
|
||||
StorageValue<_, BridgeAdjustment<BalanceOf<T>>, ValueQuery>;
|
||||
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn accumulated_commission)]
|
||||
pub type AccumulatedCommission<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
|
||||
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn networks)]
|
||||
pub type Networks<T: Config> =
|
||||
StorageMap<_, Twox64Concat, T::NetworkId, NetworkData, OptionQuery>;
|
||||
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn gatekeeper_amount)]
|
||||
pub type GatekeeperAmount<T: Config> =
|
||||
StorageMap<_, Twox64Concat, T::NetworkId, BalanceOf<T>, ValueQuery>;
|
||||
|
||||
#[pallet::genesis_config]
|
||||
pub struct GenesisConfig<T: Config> {
|
||||
pub networks: Vec<(T::NetworkId, Vec<u8>)>,
|
||||
@ -255,7 +126,7 @@ pub mod module {
|
||||
|
||||
impl<T: Config> Default for GenesisConfig<T> {
|
||||
fn default() -> Self {
|
||||
Self { networks: vec![] }
|
||||
Self { networks: vec![] }
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,13 +134,12 @@ pub mod module {
|
||||
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
|
||||
fn build(&self) {
|
||||
if !self.networks.is_empty() {
|
||||
self.networks
|
||||
.iter()
|
||||
.for_each(|(chain_id, network_metadata)| {
|
||||
let network = NetworkData::decode(&mut &network_metadata[..])
|
||||
.expect("Error decoding NetworkData");
|
||||
Pallet::<T>::do_register_network(chain_id.clone(), network)
|
||||
.expect("Error registering network");
|
||||
self.networks.iter().for_each(|(chain_id, network_metadata)| {
|
||||
let network =
|
||||
NetworkData::decode(&mut &network_metadata[..])
|
||||
.expect("Error decoding NetworkData");
|
||||
Pallet::<T>::do_register_network(chain_id.clone(), network)
|
||||
.expect("Error registering network");
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -280,30 +150,14 @@ pub mod module {
|
||||
pub struct Pallet<T>(PhantomData<T>);
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||
fn on_initialize(_: BlockNumberFor<T>) -> Weight {
|
||||
T::DbWeight::get().reads_writes(1, 1)
|
||||
}
|
||||
|
||||
fn on_finalize(_: BlockNumberFor<T>) {
|
||||
if Self::nullify_needed() {
|
||||
Self::nullify_commission();
|
||||
NullifyNeeded::<T>::put(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
#[pallet::call_index(0)]
|
||||
#[pallet::weight(T::WeightInfo::register_network(
|
||||
network.chain_name.len() as u32,
|
||||
network.default_endpoints
|
||||
.iter()
|
||||
.map(|endpoint| endpoint.len())
|
||||
.max()
|
||||
.unwrap_or_default() as u32,
|
||||
network.default_endpoints.len() as u32,
|
||||
network.default_endpoint.len() as u32,
|
||||
))]
|
||||
pub fn register_network(
|
||||
origin: OriginFor<T>,
|
||||
@ -324,24 +178,26 @@ pub mod module {
|
||||
chain_name: Vec<u8>,
|
||||
) -> DispatchResult {
|
||||
T::UpdateOrigin::ensure_origin_or_root(origin)?;
|
||||
Self::do_update_network_name(chain_id, chain_name)
|
||||
Self::do_update_network_name(
|
||||
chain_id,
|
||||
chain_name,
|
||||
)
|
||||
}
|
||||
|
||||
#[pallet::call_index(2)]
|
||||
#[pallet::weight(T::WeightInfo::update_network_endpoint(
|
||||
maybe_endpoint
|
||||
.as_ref()
|
||||
.map(|endpoint| endpoint.len())
|
||||
.unwrap_or_default() as u32
|
||||
default_endpoint.len() as u32
|
||||
))]
|
||||
pub fn update_network_endpoint(
|
||||
origin: OriginFor<T>,
|
||||
chain_id: T::NetworkId,
|
||||
maybe_index: Option<u32>,
|
||||
maybe_endpoint: Option<Vec<u8>>,
|
||||
default_endpoint: Vec<u8>,
|
||||
) -> DispatchResult {
|
||||
T::UpdateOrigin::ensure_origin_or_root(origin)?;
|
||||
Self::do_update_network_endpoint(chain_id, maybe_index, maybe_endpoint)
|
||||
Self::do_update_network_endpoint(
|
||||
chain_id,
|
||||
default_endpoint,
|
||||
)
|
||||
}
|
||||
|
||||
#[pallet::call_index(3)]
|
||||
@ -349,35 +205,30 @@ pub mod module {
|
||||
pub fn update_network_finality_delay(
|
||||
origin: OriginFor<T>,
|
||||
chain_id: T::NetworkId,
|
||||
finality_delay: u64,
|
||||
finality_delay: Option<u64>,
|
||||
) -> DispatchResult {
|
||||
T::UpdateOrigin::ensure_origin_or_root(origin)?;
|
||||
Self::do_update_network_finality_delay(chain_id, finality_delay)
|
||||
Self::do_update_network_finality_delay(
|
||||
chain_id,
|
||||
finality_delay,
|
||||
)
|
||||
}
|
||||
|
||||
#[pallet::call_index(4)]
|
||||
#[pallet::weight(T::WeightInfo::update_network_rate_limit_delay())]
|
||||
pub fn update_network_rate_limit_delay(
|
||||
#[pallet::weight(T::WeightInfo::update_network_release_delay())]
|
||||
pub fn update_network_release_delay(
|
||||
origin: OriginFor<T>,
|
||||
chain_id: T::NetworkId,
|
||||
rate_limit_delay: u64,
|
||||
release_delay: Option<u64>,
|
||||
) -> DispatchResult {
|
||||
T::UpdateOrigin::ensure_origin_or_root(origin)?;
|
||||
Self::do_update_network_rate_limit_delay(chain_id, rate_limit_delay)
|
||||
Self::do_update_network_release_delay(
|
||||
chain_id,
|
||||
release_delay,
|
||||
)
|
||||
}
|
||||
|
||||
#[pallet::call_index(5)]
|
||||
#[pallet::weight(T::WeightInfo::update_network_block_distance())]
|
||||
pub fn update_network_block_distance(
|
||||
origin: OriginFor<T>,
|
||||
chain_id: T::NetworkId,
|
||||
block_distance: u64,
|
||||
) -> DispatchResult {
|
||||
T::UpdateOrigin::ensure_origin_or_root(origin)?;
|
||||
Self::do_update_network_block_distance(chain_id, block_distance)
|
||||
}
|
||||
|
||||
#[pallet::call_index(6)]
|
||||
#[pallet::weight(T::WeightInfo::update_network_type())]
|
||||
pub fn update_network_type(
|
||||
origin: OriginFor<T>,
|
||||
@ -385,10 +236,13 @@ pub mod module {
|
||||
network_type: NetworkType,
|
||||
) -> DispatchResult {
|
||||
T::UpdateOrigin::ensure_origin_or_root(origin)?;
|
||||
Self::do_update_network_type(chain_id, network_type)
|
||||
Self::do_update_network_type(
|
||||
chain_id,
|
||||
network_type,
|
||||
)
|
||||
}
|
||||
|
||||
#[pallet::call_index(7)]
|
||||
#[pallet::call_index(6)]
|
||||
#[pallet::weight(T::WeightInfo::update_network_gatekeeper())]
|
||||
pub fn update_network_gatekeeper(
|
||||
origin: OriginFor<T>,
|
||||
@ -396,10 +250,13 @@ pub mod module {
|
||||
gatekeeper: Vec<u8>,
|
||||
) -> DispatchResult {
|
||||
T::UpdateOrigin::ensure_origin_or_root(origin)?;
|
||||
Self::do_update_network_gatekeeper(chain_id, gatekeeper)
|
||||
Self::do_update_network_gatekeeper(
|
||||
chain_id,
|
||||
gatekeeper,
|
||||
)
|
||||
}
|
||||
|
||||
#[pallet::call_index(8)]
|
||||
#[pallet::call_index(7)]
|
||||
#[pallet::weight(T::WeightInfo::update_network_topic_name())]
|
||||
pub fn update_network_topic_name(
|
||||
origin: OriginFor<T>,
|
||||
@ -407,10 +264,13 @@ pub mod module {
|
||||
topic_name: Vec<u8>,
|
||||
) -> DispatchResult {
|
||||
T::UpdateOrigin::ensure_origin_or_root(origin)?;
|
||||
Self::do_update_network_topic_name(chain_id, topic_name)
|
||||
Self::do_update_network_topic_name(
|
||||
chain_id,
|
||||
topic_name,
|
||||
)
|
||||
}
|
||||
|
||||
#[pallet::call_index(9)]
|
||||
#[pallet::call_index(8)]
|
||||
#[pallet::weight(T::WeightInfo::update_incoming_network_fee())]
|
||||
pub fn update_incoming_network_fee(
|
||||
origin: OriginFor<T>,
|
||||
@ -418,10 +278,13 @@ pub mod module {
|
||||
incoming_fee: u32,
|
||||
) -> DispatchResult {
|
||||
T::UpdateOrigin::ensure_origin_or_root(origin)?;
|
||||
Self::do_update_incoming_network_fee(chain_id, incoming_fee)
|
||||
Self::do_update_incoming_network_fee(
|
||||
chain_id,
|
||||
incoming_fee,
|
||||
)
|
||||
}
|
||||
|
||||
#[pallet::call_index(10)]
|
||||
#[pallet::call_index(9)]
|
||||
#[pallet::weight(T::WeightInfo::update_outgoing_network_fee())]
|
||||
pub fn update_outgoing_network_fee(
|
||||
origin: OriginFor<T>,
|
||||
@ -429,12 +292,18 @@ pub mod module {
|
||||
outgoing_fee: u32,
|
||||
) -> DispatchResult {
|
||||
T::UpdateOrigin::ensure_origin_or_root(origin)?;
|
||||
Self::do_update_outgoing_network_fee(chain_id, outgoing_fee)
|
||||
Self::do_update_outgoing_network_fee(
|
||||
chain_id,
|
||||
outgoing_fee,
|
||||
)
|
||||
}
|
||||
|
||||
#[pallet::call_index(11)]
|
||||
#[pallet::call_index(10)]
|
||||
#[pallet::weight(T::WeightInfo::remove_network())]
|
||||
pub fn remove_network(origin: OriginFor<T>, chain_id: T::NetworkId) -> DispatchResult {
|
||||
pub fn remove_network(
|
||||
origin: OriginFor<T>,
|
||||
chain_id: T::NetworkId,
|
||||
) -> DispatchResult {
|
||||
T::RemoveOrigin::ensure_origin_or_root(origin)?;
|
||||
Self::do_remove_network(chain_id)
|
||||
}
|
||||
@ -443,12 +312,12 @@ pub mod module {
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Register a new network.
|
||||
pub fn do_register_network(chain_id: T::NetworkId, network: NetworkData) -> DispatchResult {
|
||||
pub fn do_register_network(
|
||||
chain_id: T::NetworkId,
|
||||
network: NetworkData,
|
||||
) -> DispatchResult {
|
||||
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
|
||||
ensure!(
|
||||
maybe_network.is_none(),
|
||||
Error::<T>::NetworkAlreadyRegistered
|
||||
);
|
||||
ensure!(maybe_network.is_none(), Error::<T>::NetworkAlreadyRegistered);
|
||||
*maybe_network = Some(network.clone());
|
||||
Ok(())
|
||||
})?;
|
||||
@ -470,7 +339,10 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
/// Update existent network name.
|
||||
pub fn do_update_network_name(chain_id: T::NetworkId, chain_name: Vec<u8>) -> DispatchResult {
|
||||
pub fn do_update_network_name(
|
||||
chain_id: T::NetworkId,
|
||||
chain_name: Vec<u8>,
|
||||
) -> DispatchResult {
|
||||
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
|
||||
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
|
||||
let net = maybe_network.as_mut().unwrap();
|
||||
@ -489,45 +361,26 @@ impl<T: Config> Pallet<T> {
|
||||
/// Update existent network default endpoint.
|
||||
pub fn do_update_network_endpoint(
|
||||
chain_id: T::NetworkId,
|
||||
maybe_index: Option<u32>,
|
||||
maybe_endpoint: Option<Vec<u8>>,
|
||||
default_endpoint: Vec<u8>,
|
||||
) -> DispatchResult {
|
||||
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
|
||||
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
|
||||
let updated_network = maybe_network.as_mut().unwrap();
|
||||
match (maybe_index, maybe_endpoint) {
|
||||
(Some(index), Some(endpoint)) => {
|
||||
if let Some(previous_endpoint) =
|
||||
updated_network.default_endpoints.get_mut(index as usize)
|
||||
{
|
||||
*previous_endpoint = endpoint.clone();
|
||||
Self::deposit_event(Event::<T>::NetworkEndpointUpdated {
|
||||
chain_id,
|
||||
index,
|
||||
endpoint,
|
||||
});
|
||||
}
|
||||
}
|
||||
(None, Some(endpoint)) => {
|
||||
updated_network.default_endpoints.push(endpoint.clone());
|
||||
Self::deposit_event(Event::<T>::NetworkEndpointAdded { chain_id, endpoint });
|
||||
}
|
||||
(Some(index), None) => {
|
||||
updated_network.default_endpoints.remove(index as usize);
|
||||
Self::deposit_event(Event::<T>::NetworkEndpointRemoved { chain_id, index });
|
||||
}
|
||||
(None, None) => {}
|
||||
}
|
||||
*maybe_network = Some(updated_network.clone());
|
||||
let net = maybe_network.as_mut().unwrap();
|
||||
net.default_endpoint = default_endpoint.clone();
|
||||
*maybe_network = Some(net.clone());
|
||||
Ok(())
|
||||
})?;
|
||||
Self::deposit_event(Event::<T>::NetworkEndpointUpdated {
|
||||
chain_id,
|
||||
default_endpoint,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Update existent network default finality delay.
|
||||
/// Update existent network default endpoint.
|
||||
pub fn do_update_network_finality_delay(
|
||||
chain_id: T::NetworkId,
|
||||
finality_delay: u64,
|
||||
finality_delay: Option<u64>,
|
||||
) -> DispatchResult {
|
||||
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
|
||||
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
|
||||
@ -543,40 +396,21 @@ impl<T: Config> Pallet<T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Update existent network default rate limit delay.
|
||||
pub fn do_update_network_rate_limit_delay(
|
||||
/// Update existent network default endpoint.
|
||||
pub fn do_update_network_release_delay(
|
||||
chain_id: T::NetworkId,
|
||||
rate_limit_delay: u64,
|
||||
release_delay: Option<u64>,
|
||||
) -> DispatchResult {
|
||||
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
|
||||
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
|
||||
let net = maybe_network.as_mut().unwrap();
|
||||
net.rate_limit_delay = rate_limit_delay;
|
||||
net.release_delay = release_delay;
|
||||
*maybe_network = Some(net.clone());
|
||||
Ok(())
|
||||
})?;
|
||||
Self::deposit_event(Event::<T>::NetworkRateLimitDelayUpdated {
|
||||
Self::deposit_event(Event::<T>::NetworkReleaseDelayUpdated {
|
||||
chain_id,
|
||||
rate_limit_delay,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Update existent network default max distance between blocks.
|
||||
pub fn do_update_network_block_distance(
|
||||
chain_id: T::NetworkId,
|
||||
block_distance: u64,
|
||||
) -> DispatchResult {
|
||||
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
|
||||
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
|
||||
let net = maybe_network.as_mut().unwrap();
|
||||
net.block_distance = block_distance;
|
||||
*maybe_network = Some(net.clone());
|
||||
Ok(())
|
||||
})?;
|
||||
Self::deposit_event(Event::<T>::NetworkBlockDistanceUpdated {
|
||||
chain_id,
|
||||
block_distance,
|
||||
release_delay,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
@ -605,10 +439,8 @@ impl<T: Config> Pallet<T> {
|
||||
chain_id: T::NetworkId,
|
||||
gatekeeper: Vec<u8>,
|
||||
) -> DispatchResult {
|
||||
ensure!(
|
||||
gatekeeper.len() == 42 && gatekeeper[0] == 48 && gatekeeper[1] == 120,
|
||||
Error::<T>::WrongGatekeeperAddress
|
||||
);
|
||||
ensure!(gatekeeper.len() == 42 && gatekeeper[0] == 48 && gatekeeper[1] == 120,
|
||||
Error::<T>::WrongGatekeeperAddress);
|
||||
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
|
||||
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
|
||||
let net = maybe_network.as_mut().unwrap();
|
||||
@ -628,10 +460,8 @@ impl<T: Config> Pallet<T> {
|
||||
chain_id: T::NetworkId,
|
||||
topic_name: Vec<u8>,
|
||||
) -> DispatchResult {
|
||||
ensure!(
|
||||
topic_name.len() == 66 && topic_name[0] == 48 && topic_name[1] == 120,
|
||||
Error::<T>::WrongTopicName
|
||||
);
|
||||
ensure!(topic_name.len() == 66 && topic_name[0] == 48 && topic_name[1] == 120,
|
||||
Error::<T>::WrongTopicName);
|
||||
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
|
||||
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
|
||||
let net = maybe_network.as_mut().unwrap();
|
||||
@ -695,13 +525,9 @@ impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> {
|
||||
fn iter() -> PrefixIterator<(Self::NetworkId, NetworkData)> {
|
||||
Networks::<T>::iter()
|
||||
}
|
||||
|
||||
fn is_nullification_period() -> bool {
|
||||
NullifyNeeded::<T>::get()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> NetworkDataMutateHandler<NetworkData, BalanceOf<T>> for Pallet<T> {
|
||||
impl<T: Config> NetworkDataMutateHandler<NetworkData> for Pallet<T> {
|
||||
fn register(chain_id: Self::NetworkId, network: NetworkData) -> DispatchResult {
|
||||
Self::do_register_network(chain_id, network)
|
||||
}
|
||||
@ -709,94 +535,4 @@ impl<T: Config> NetworkDataMutateHandler<NetworkData, BalanceOf<T>> for Pallet<T
|
||||
fn remove(chain_id: Self::NetworkId) -> DispatchResult {
|
||||
Self::do_remove_network(chain_id)
|
||||
}
|
||||
|
||||
fn increase_gatekeeper_amount(
|
||||
network_id: &T::NetworkId,
|
||||
amount: &BalanceOf<T>,
|
||||
) -> Result<BalanceOf<T>, ()> {
|
||||
let new_gatekeeper_amount =
|
||||
GatekeeperAmount::<T>::mutate(network_id, |gatekeeper_amount| match gatekeeper_amount
|
||||
.checked_add(amount)
|
||||
{
|
||||
Some(value) => {
|
||||
*gatekeeper_amount = value;
|
||||
Ok(value)
|
||||
}
|
||||
None => Err(()),
|
||||
})?;
|
||||
|
||||
Ok(new_gatekeeper_amount)
|
||||
}
|
||||
|
||||
fn decrease_gatekeeper_amount(
|
||||
network_id: &T::NetworkId,
|
||||
amount: &BalanceOf<T>,
|
||||
) -> Result<BalanceOf<T>, ()> {
|
||||
let new_gatekeeper_amount =
|
||||
GatekeeperAmount::<T>::mutate(network_id, |gatekeeper_amount| match gatekeeper_amount
|
||||
.checked_sub(amount)
|
||||
{
|
||||
Some(value) => {
|
||||
*gatekeeper_amount = value;
|
||||
Ok(value)
|
||||
}
|
||||
None => Err(()),
|
||||
})?;
|
||||
|
||||
Ok(new_gatekeeper_amount)
|
||||
}
|
||||
|
||||
fn accumulate_outgoing_imbalance(amount: &BalanceOf<T>) -> Result<BalanceOf<T>, ()> {
|
||||
let new_bridged_out_amount = BridgedImbalance::<T>::mutate(|bridged_imbalance| {
|
||||
match bridged_imbalance.bridged_out.checked_add(amount) {
|
||||
Some(value) => {
|
||||
(*bridged_imbalance).bridged_out = value;
|
||||
Ok(value)
|
||||
}
|
||||
None => Err(()),
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(new_bridged_out_amount)
|
||||
}
|
||||
|
||||
fn accumulate_incoming_imbalance(amount: &BalanceOf<T>) -> Result<BalanceOf<T>, ()> {
|
||||
let new_bridged_in_amount = BridgedImbalance::<T>::mutate(|bridged_imbalance| {
|
||||
match bridged_imbalance.bridged_in.checked_add(amount) {
|
||||
Some(value) => {
|
||||
(*bridged_imbalance).bridged_in = value;
|
||||
Ok(value)
|
||||
}
|
||||
None => Err(()),
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(new_bridged_in_amount)
|
||||
}
|
||||
|
||||
fn accumulate_commission(commission: &BalanceOf<T>) -> Result<BalanceOf<T>, ()> {
|
||||
AccumulatedCommission::<T>::mutate(|accumulated| {
|
||||
match accumulated.checked_add(commission) {
|
||||
Some(value) => {
|
||||
*accumulated = value;
|
||||
Ok(value)
|
||||
}
|
||||
None => Err(()),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn nullify_commission() {
|
||||
AccumulatedCommission::<T>::set(Default::default());
|
||||
BridgedImbalance::<T>::set(Default::default());
|
||||
}
|
||||
|
||||
fn trigger_nullification() {
|
||||
if NullifyNeeded::<T>::get() {
|
||||
Self::nullify_commission();
|
||||
NullifyNeeded::<T>::put(false);
|
||||
} else {
|
||||
NullifyNeeded::<T>::put(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,135 +0,0 @@
|
||||
use crate::AtLeast32BitUnsigned;
|
||||
|
||||
pub struct MulDiv<Balance>(core::marker::PhantomData<Balance>);
|
||||
impl<Balance> MulDiv<Balance>
|
||||
where
|
||||
Balance: Copy
|
||||
+ AtLeast32BitUnsigned
|
||||
+ num_traits::ops::wrapping::WrappingAdd
|
||||
+ num_traits::ops::overflowing::OverflowingAdd
|
||||
+ sp_std::ops::AddAssign
|
||||
+ sp_std::ops::Not<Output = Balance>
|
||||
+ sp_std::ops::Shl<Output = Balance>
|
||||
+ sp_std::ops::Shr<Output = Balance>
|
||||
+ sp_std::ops::BitAnd<Balance, Output = Balance>,
|
||||
{
|
||||
|
||||
fn zero(&self) -> Balance {
|
||||
0u32.into()
|
||||
}
|
||||
|
||||
fn one(&self) -> Balance {
|
||||
1u32.into()
|
||||
}
|
||||
|
||||
fn bit_shift(&self) -> Balance {
|
||||
let u32_shift: u32 = core::mem::size_of::<Balance>()
|
||||
.saturating_mul(4)
|
||||
.try_into()
|
||||
.unwrap_or_default();
|
||||
u32_shift.into()
|
||||
}
|
||||
|
||||
fn least_significant_bits(&self, a: Balance) -> Balance {
|
||||
a & ((self.one() << self.bit_shift()) - self.one())
|
||||
}
|
||||
|
||||
fn most_significant_bits(&self, a: Balance) -> Balance {
|
||||
a >> self.bit_shift()
|
||||
}
|
||||
|
||||
fn two_complement(&self, a: Balance) -> Balance {
|
||||
(!a).wrapping_add(&self.one())
|
||||
}
|
||||
|
||||
fn adjusted_ratio(&self, a: Balance) -> Balance {
|
||||
(self.two_complement(a) / a).wrapping_add(&self.one())
|
||||
}
|
||||
|
||||
fn modulo(&self, a: Balance) -> Balance {
|
||||
self.two_complement(a) % a
|
||||
}
|
||||
|
||||
fn overflow_resistant_addition(
|
||||
&self,
|
||||
a0: Balance,
|
||||
a1: Balance,
|
||||
b0: Balance,
|
||||
b1: Balance,
|
||||
) -> (Balance, Balance) {
|
||||
let (r0, overflow) = a0.overflowing_add(&b0);
|
||||
let overflow: Balance = overflow.then(|| 1u32).unwrap_or_default().into();
|
||||
let r1 = a1.wrapping_add(&b1).wrapping_add(&overflow);
|
||||
(r0, r1)
|
||||
}
|
||||
|
||||
fn overflow_resistant_multiplication(&self, a: Balance, b: Balance) -> (Balance, Balance) {
|
||||
let (a0, a1) = (
|
||||
self.least_significant_bits(a),
|
||||
self.most_significant_bits(a),
|
||||
);
|
||||
let (b0, b1) = (
|
||||
self.least_significant_bits(b),
|
||||
self.most_significant_bits(b),
|
||||
);
|
||||
let (x, y) = (a1 * b0, b1 * a0);
|
||||
|
||||
let (r0, r1) = (a0 * b0, a1 * b1);
|
||||
let (r0, r1) = self.overflow_resistant_addition(
|
||||
r0,
|
||||
r1,
|
||||
self.least_significant_bits(x) << self.bit_shift(),
|
||||
self.most_significant_bits(x),
|
||||
);
|
||||
let (r0, r1) = self.overflow_resistant_addition(
|
||||
r0,
|
||||
r1,
|
||||
self.least_significant_bits(y) << self.bit_shift(),
|
||||
self.most_significant_bits(y),
|
||||
);
|
||||
|
||||
(r0, r1)
|
||||
}
|
||||
|
||||
fn overflow_resistant_division(
|
||||
&self,
|
||||
mut a0: Balance,
|
||||
mut a1: Balance,
|
||||
b: Balance,
|
||||
) -> (Balance, Balance) {
|
||||
if b == self.one() {
|
||||
return (a0, a1);
|
||||
}
|
||||
|
||||
let zero: Balance = 0u32.into();
|
||||
let (q, r) = (self.adjusted_ratio(b), self.modulo(b));
|
||||
let (mut x0, mut x1) = (zero, zero);
|
||||
|
||||
while a1 != zero {
|
||||
let (t0, t1) = self.overflow_resistant_multiplication(a1, q);
|
||||
let (new_x0, new_x1) = self.overflow_resistant_addition(x0, x1, t0, t1);
|
||||
x0 = new_x0;
|
||||
x1 = new_x1;
|
||||
|
||||
let (t0, t1) = self.overflow_resistant_multiplication(a1, r);
|
||||
let (new_a0, new_a1) = self.overflow_resistant_addition(t0, t1, a0, zero);
|
||||
a0 = new_a0;
|
||||
a1 = new_a1;
|
||||
}
|
||||
|
||||
self.overflow_resistant_addition(x0, x1, a0 / b, zero)
|
||||
}
|
||||
|
||||
fn mul_div(&self, a: Balance, b: Balance, c: Balance) -> Balance {
|
||||
let (t0, t1) = self.overflow_resistant_multiplication(a, b);
|
||||
self.overflow_resistant_division(t0, t1, c).0
|
||||
}
|
||||
|
||||
pub fn calculate(a: Balance, b: Balance, c: Balance) -> Balance {
|
||||
let inner = MulDiv(core::marker::PhantomData);
|
||||
if c == inner.zero() {
|
||||
return c;
|
||||
}
|
||||
inner.mul_div(a, b, c)
|
||||
}
|
||||
}
|
43
pallets/networks/src/mock.rs
Normal file → Executable file
@ -1,24 +1,19 @@
|
||||
use crate::{self as ghost_networks};
|
||||
use frame_support::{
|
||||
construct_runtime, ord_parameter_types, parameter_types,
|
||||
traits::{ConstU128, ConstU32, Everything},
|
||||
};
|
||||
use crate as ghost_networks;
|
||||
use frame_system::EnsureSignedBy;
|
||||
use frame_support::{
|
||||
construct_runtime, ord_parameter_types, parameter_types, traits::{ConstU128, ConstU32, Everything}
|
||||
};
|
||||
pub use primitives::{
|
||||
AccountId, Balance, BlockNumber, FreezeIdentifier, Hash, Nonce, ReserveIdentifier,
|
||||
AccountId, Balance, Nonce, BlockNumber, Hash,
|
||||
ReserveIdentifier, FreezeIdentifier,
|
||||
};
|
||||
use sp_runtime::{
|
||||
curve::PiecewiseLinear,
|
||||
traits::{AccountIdLookup, BlakeTwo256},
|
||||
traits::{BlakeTwo256, AccountIdLookup},
|
||||
BuildStorage,
|
||||
};
|
||||
|
||||
parameter_types! {
|
||||
pub const BlockHashCount: BlockNumber = 250;
|
||||
pub static SlashDeferDuration: u32 = 0;
|
||||
pub static Period: BlockNumber = 5;
|
||||
pub static Offset: BlockNumber = 0;
|
||||
pub static MaxControllersInDeprecationBatch: u32 = 5_000;
|
||||
}
|
||||
|
||||
impl frame_system::Config for Test {
|
||||
@ -69,21 +64,6 @@ impl pallet_balances::Config for Test {
|
||||
type MaxFreezes = ConstU32<50>;
|
||||
}
|
||||
|
||||
pallet_staking_reward_curve::build! {
|
||||
const REWARD_CURVE: PiecewiseLinear<'static> = curve!(
|
||||
min_inflation: 0_006_900,
|
||||
max_inflation: 1_000_000,
|
||||
ideal_stake: 0_690_000,
|
||||
falloff: 0_050_000,
|
||||
max_piece_count: 100,
|
||||
test_precision: 0_005_000,
|
||||
);
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
|
||||
}
|
||||
|
||||
ord_parameter_types! {
|
||||
pub const RegistererAccount: AccountId = AccountId::from([1u8; 32]);
|
||||
pub const UpdaterAccount: AccountId = AccountId::from([2u8; 32]);
|
||||
@ -93,15 +73,14 @@ ord_parameter_types! {
|
||||
|
||||
impl ghost_networks::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Currency = Balances;
|
||||
type NetworkId = u32;
|
||||
type RegisterOrigin = EnsureSignedBy<RegistererAccount, AccountId>;
|
||||
type UpdateOrigin = EnsureSignedBy<UpdaterAccount, AccountId>;
|
||||
type RemoveOrigin = EnsureSignedBy<RemoverAccount, AccountId>;
|
||||
type RegisterOrigin = EnsureSignedBy::<RegistererAccount, AccountId>;
|
||||
type UpdateOrigin = EnsureSignedBy::<UpdaterAccount, AccountId>;
|
||||
type RemoveOrigin = EnsureSignedBy::<RemoverAccount, AccountId>;
|
||||
type WeightInfo = crate::weights::SubstrateWeight<Test>;
|
||||
}
|
||||
|
||||
type Block = frame_system::mocking::MockBlock<Test>;
|
||||
type Block = frame_system::mocking::MockBlockU32<Test>;
|
||||
|
||||
construct_runtime!(
|
||||
pub enum Test {
|
||||
|
2260
pallets/networks/src/tests.rs
Normal file → Executable file
399
pallets/networks/src/weights.rs
Normal file → Executable file
@ -7,7 +7,7 @@
|
||||
|
||||
// Ghost Network is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
@ -15,14 +15,14 @@
|
||||
|
||||
//! Autogenerated weights for `ghost_networks`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
|
||||
//! DATE: 2025-06-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2023-11-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
|
||||
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
|
||||
//! HOSTNAME: `ghost`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("casper-dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/ghost
|
||||
// ./target/production/ghost
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=casper-dev
|
||||
@ -30,8 +30,8 @@
|
||||
// --repeat=20
|
||||
// --pallet=ghost_networks
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --heap-pages=4096
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/casper/src/weights/ghost_networks.rs
|
||||
|
||||
@ -49,12 +49,11 @@ use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions needed for ghost_networks
|
||||
pub trait WeightInfo {
|
||||
fn register_network(i: u32, j: u32, k: u32, ) -> Weight;
|
||||
fn register_network(n: u32, m: u32, ) -> Weight;
|
||||
fn update_network_name(n: u32, ) -> Weight;
|
||||
fn update_network_endpoint(n: u32, ) -> Weight;
|
||||
fn update_network_finality_delay() -> Weight;
|
||||
fn update_network_rate_limit_delay() -> Weight;
|
||||
fn update_network_block_distance() -> Weight;
|
||||
fn update_network_release_delay() -> Weight;
|
||||
fn update_network_type() -> Weight;
|
||||
fn update_network_gatekeeper() -> Weight;
|
||||
fn update_network_topic_name() -> Weight;
|
||||
@ -66,316 +65,260 @@ pub trait WeightInfo {
|
||||
/// Weight for ghost_networks using the Substrate node and recommended hardware.
|
||||
pub struct SubstrateWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// The range of component `i` is `[1, 20]`.
|
||||
/// The range of component `j` is `[1, 150]`.
|
||||
/// The range of component `k` is `[1, 20]`.
|
||||
fn register_network(_i: u32, _j: u32, k: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `109`
|
||||
// Estimated: `3574`
|
||||
// Minimum execution time: 46_023_000 picoseconds.
|
||||
Weight::from_parts(97_871_287, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3574))
|
||||
// Standard Error: 94_524
|
||||
.saturating_add(Weight::from_parts(940_486, 0).saturating_mul(k.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `n` is `[1, 20]`.
|
||||
fn update_network_name(n: u32, ) -> Weight {
|
||||
/// The range of component `m` is `[1, 150]`.
|
||||
fn register_network(_n: u32, _m: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 49_906_000 picoseconds.
|
||||
Weight::from_parts(55_537_587, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Standard Error: 87_704
|
||||
.saturating_add(Weight::from_parts(92_366, 0).saturating_mul(n.into()))
|
||||
// Measured: `76`
|
||||
// Estimated: `2551`
|
||||
// Minimum execution time: 32_086 nanoseconds.
|
||||
Weight::from_parts(33_092_855, 2551)
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `n` is `[1, 20]`.
|
||||
fn update_network_name(_n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_496 nanoseconds.
|
||||
Weight::from_parts(35_728_230, 2616)
|
||||
// Standard Error: 2_591
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `n` is `[1, 150]`.
|
||||
fn update_network_endpoint(n: u32, ) -> Weight {
|
||||
fn update_network_endpoint(_n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 50_556_000 picoseconds.
|
||||
Weight::from_parts(57_726_674, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Standard Error: 12_261
|
||||
.saturating_add(Weight::from_parts(274, 0).saturating_mul(n.into()))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_666 nanoseconds.
|
||||
Weight::from_parts(35_959_961, 2616)
|
||||
// Standard Error: 381
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_network_finality_delay() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 49_406_000 picoseconds.
|
||||
Weight::from_parts(51_256_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 33_860 nanoseconds.
|
||||
Weight::from_parts(34_995_000, 2616)
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
fn update_network_rate_limit_delay() -> Weight {
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_network_release_delay() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 49_572_000 picoseconds.
|
||||
Weight::from_parts(52_584_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 33_860 nanoseconds.
|
||||
Weight::from_parts(34_995_000, 2616)
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
fn update_network_block_distance() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 48_880_000 picoseconds.
|
||||
Weight::from_parts(50_596_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_network_type() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 48_282_000 picoseconds.
|
||||
Weight::from_parts(49_137_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_976 nanoseconds.
|
||||
Weight::from_parts(36_182_000, 2616)
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_network_gatekeeper() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 50_853_000 picoseconds.
|
||||
Weight::from_parts(51_982_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_768 nanoseconds.
|
||||
Weight::from_parts(35_580_000, 2616)
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_network_topic_name() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 50_343_000 picoseconds.
|
||||
Weight::from_parts(52_380_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_768 nanoseconds.
|
||||
Weight::from_parts(35_580_000, 2616)
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
}
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_incoming_network_fee() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 49_393_000 picoseconds.
|
||||
Weight::from_parts(80_966_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_768 nanoseconds.
|
||||
Weight::from_parts(35_580_000, 2616)
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
}
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_outgoing_network_fee() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 49_579_000 picoseconds.
|
||||
Weight::from_parts(51_126_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_768 nanoseconds.
|
||||
Weight::from_parts(35_580_000, 2616)
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
}
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn remove_network() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 44_634_000 picoseconds.
|
||||
Weight::from_parts(45_815_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 33_336 nanoseconds.
|
||||
Weight::from_parts(34_609_000, 2616)
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
}
|
||||
|
||||
impl WeightInfo for () {
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// The range of component `i` is `[1, 20]`.
|
||||
/// The range of component `j` is `[1, 150]`.
|
||||
/// The range of component `k` is `[1, 20]`.
|
||||
fn register_network(_i: u32, _j: u32, k: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `109`
|
||||
// Estimated: `3574`
|
||||
// Minimum execution time: 46_023_000 picoseconds.
|
||||
Weight::from_parts(97_871_287, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3574))
|
||||
// Standard Error: 94_524
|
||||
.saturating_add(Weight::from_parts(940_486, 0).saturating_mul(k.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `n` is `[1, 20]`.
|
||||
fn update_network_name(n: u32, ) -> Weight {
|
||||
/// The range of component `m` is `[1, 150]`.
|
||||
fn register_network(_n: u32, _m: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 49_906_000 picoseconds.
|
||||
Weight::from_parts(55_537_587, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Standard Error: 87_704
|
||||
.saturating_add(Weight::from_parts(92_366, 0).saturating_mul(n.into()))
|
||||
// Measured: `76`
|
||||
// Estimated: `2551`
|
||||
// Minimum execution time: 32_086 nanoseconds.
|
||||
Weight::from_parts(33_092_855, 2551)
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `n` is `[1, 20]`.
|
||||
fn update_network_name(_n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_496 nanoseconds.
|
||||
Weight::from_parts(35_728_230, 2616)
|
||||
// Standard Error: 2_591
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `n` is `[1, 150]`.
|
||||
fn update_network_endpoint(n: u32, ) -> Weight {
|
||||
fn update_network_endpoint(_n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 50_556_000 picoseconds.
|
||||
Weight::from_parts(57_726_674, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Standard Error: 12_261
|
||||
.saturating_add(Weight::from_parts(274, 0).saturating_mul(n.into()))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_666 nanoseconds.
|
||||
Weight::from_parts(35_959_961, 2616)
|
||||
// Standard Error: 381
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_network_finality_delay() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 49_406_000 picoseconds.
|
||||
Weight::from_parts(51_256_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 33_860 nanoseconds.
|
||||
Weight::from_parts(34_995_000, 2616)
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
fn update_network_rate_limit_delay() -> Weight {
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_network_release_delay() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 49_572_000 picoseconds.
|
||||
Weight::from_parts(52_584_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 33_860 nanoseconds.
|
||||
Weight::from_parts(34_995_000, 2616)
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
fn update_network_block_distance() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 48_880_000 picoseconds.
|
||||
Weight::from_parts(50_596_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_network_type() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 48_282_000 picoseconds.
|
||||
Weight::from_parts(49_137_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_976 nanoseconds.
|
||||
Weight::from_parts(36_182_000, 2616)
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_network_gatekeeper() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 50_853_000 picoseconds.
|
||||
Weight::from_parts(51_982_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_768 nanoseconds.
|
||||
Weight::from_parts(35_580_000, 2616)
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_network_topic_name() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 50_343_000 picoseconds.
|
||||
Weight::from_parts(52_380_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_768 nanoseconds.
|
||||
Weight::from_parts(35_580_000, 2616)
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
}
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_incoming_network_fee() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 49_393_000 picoseconds.
|
||||
Weight::from_parts(80_966_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_768 nanoseconds.
|
||||
Weight::from_parts(35_580_000, 2616)
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
}
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn update_outgoing_network_fee() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 49_579_000 picoseconds.
|
||||
Weight::from_parts(51_126_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 34_768 nanoseconds.
|
||||
Weight::from_parts(35_580_000, 2616)
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
}
|
||||
/// Storage: GhostNetworks Networks (r:1 w:1)
|
||||
/// Proof Skipped: GhostNetworks Networks (max_values: None, max_size: None, mode: Measured)
|
||||
fn remove_network() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `302`
|
||||
// Estimated: `3767`
|
||||
// Minimum execution time: 44_634_000 picoseconds.
|
||||
Weight::from_parts(45_815_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3767))
|
||||
// Measured: `141`
|
||||
// Estimated: `2616`
|
||||
// Minimum execution time: 33_336 nanoseconds.
|
||||
Weight::from_parts(34_609_000, 2616)
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
|
9
pallets/slow-clap/Cargo.toml
Normal file → Executable file
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ghost-slow-clap"
|
||||
version = "0.3.40"
|
||||
version = "0.3.14"
|
||||
description = "Applause protocol for the EVM bridge"
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
@ -27,13 +27,11 @@ sp-staking = { workspace = true }
|
||||
sp-io = { workspace = true }
|
||||
sp-std = { workspace = true }
|
||||
|
||||
pallet-balances = { workspace = true }
|
||||
ghost-networks = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
pallet-balances = { workspace = true }
|
||||
pallet-session = { workspace = true }
|
||||
pallet-staking = { workspace = true }
|
||||
pallet-staking-reward-curve = { workspace = true }
|
||||
pallet-session = { workspace = true, default-features = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
@ -51,7 +49,6 @@ std = [
|
||||
"sp-io/std",
|
||||
"sp-std/std",
|
||||
"pallet-session/std",
|
||||
"pallet-staking/std",
|
||||
"pallet-balances/std",
|
||||
"ghost-networks/std",
|
||||
]
|
||||
|
@ -3,8 +3,13 @@
|
||||
use super::*;
|
||||
use frame_benchmarking::v1::*;
|
||||
|
||||
use frame_support::traits::fungible::Inspect;
|
||||
use frame_system::RawOrigin;
|
||||
use frame_support::traits::fungible::{Inspect, Mutate};
|
||||
|
||||
use crate::Pallet as SlowClap;
|
||||
|
||||
const MAX_CLAPS: u32 = 100;
|
||||
const MAX_COMPANIONS: u32 = 20;
|
||||
|
||||
pub fn create_account<T: Config>() -> T::AccountId {
|
||||
let account_bytes = Vec::from([1u8; 32]);
|
||||
@ -12,89 +17,184 @@ pub fn create_account<T: Config>() -> T::AccountId {
|
||||
.expect("32 bytes always construct an AccountId32")
|
||||
}
|
||||
|
||||
benchmarks! {
|
||||
slow_clap {
|
||||
pub fn create_companions<T: Config>(
|
||||
total: usize,
|
||||
network_id: NetworkIdOf<T>,
|
||||
user_account: T::AccountId,
|
||||
fee: H256,
|
||||
receiver: H160,
|
||||
) -> Result<CompanionId, &'static str> {
|
||||
T::NetworkDataHandler::register(network_id.into(), NetworkData {
|
||||
chain_name: "Ethereum".into(),
|
||||
default_endpoint:
|
||||
"https://base-mainnet.core.chainstack.com/2fc1de7f08c0465f6a28e3c355e0cb14/".into(),
|
||||
finality_delay: Some(0),
|
||||
release_delay: Some(0),
|
||||
network_type: Default::default(),
|
||||
gatekeeper: b"0x1234567891234567891234567891234567891234".to_vec(),
|
||||
topic_name: b"0x12345678912345678912345678912345678912345678912345678912345678".to_vec(),
|
||||
incoming_fee: 0,
|
||||
outgoing_fee: 0,
|
||||
}).map_err(|_| BenchmarkError::Weightless)?;
|
||||
|
||||
let mut last_companion_id = 0;
|
||||
for _ in 0..total {
|
||||
let minimum_balance = <<T as pallet::Config>::Currency>::minimum_balance();
|
||||
let receiver = create_account::<T>();
|
||||
let amount = minimum_balance + minimum_balance;
|
||||
let network_id = NetworkIdOf::<T>::default();
|
||||
let session_index = T::ValidatorSet::session_index();
|
||||
|
||||
let authorities = vec![T::AuthorityId::generate_pair(None)];
|
||||
let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities.clone())
|
||||
.map_err(|()| "more than the maximum number of keys provided")?;
|
||||
Authorities::<T>::set(&session_index, bounded_authorities);
|
||||
|
||||
let clap = Clap {
|
||||
session_index: 0,
|
||||
authority_index: 0,
|
||||
transaction_hash: H256::repeat_byte(1u8),
|
||||
block_number: 69,
|
||||
removed: false,
|
||||
network_id,
|
||||
receiver: receiver.clone(),
|
||||
amount,
|
||||
let balance = minimum_balance + minimum_balance;
|
||||
let companion = Companion::<NetworkIdOf::<T>, BalanceOf::<T>> {
|
||||
network_id: network_id.into(), receiver,
|
||||
fee, amount: balance,
|
||||
};
|
||||
|
||||
let authority_id = authorities
|
||||
.get(0usize)
|
||||
.expect("first authority should exist");
|
||||
let encoded_clap = clap.encode();
|
||||
let signature = authority_id.sign(&encoded_clap)
|
||||
.ok_or("couldn't make signature")?;
|
||||
let _ = <<T as pallet::Config>::Currency>::mint_into(&user_account, balance);
|
||||
let companion_id = SlowClap::<T>::current_companion_id();
|
||||
let _ = SlowClap::<T>::propose_companion(
|
||||
RawOrigin::Signed(user_account.clone()).into(),
|
||||
network_id,
|
||||
companion,
|
||||
)?;
|
||||
last_companion_id = companion_id;
|
||||
}
|
||||
Ok(last_companion_id)
|
||||
}
|
||||
|
||||
}: _(RawOrigin::None, clap, signature)
|
||||
verify {
|
||||
assert_eq!(<<T as pallet::Config>::Currency>::total_balance(&receiver), amount);
|
||||
pub fn create_claps<T: Config>(i: u32, j: u32) -> Result<
|
||||
(
|
||||
Vec<crate::Clap<T::AccountId, NetworkIdOf<T>, BalanceOf<T>>>,
|
||||
<T::AuthorityId as RuntimeAppPublic>::Signature,
|
||||
),
|
||||
&'static str,
|
||||
> {
|
||||
let minimum_balance = <<T as pallet::Config>::Currency>::minimum_balance();
|
||||
let amount = minimum_balance + minimum_balance;
|
||||
let total_amount = amount.saturating_mul(j.into());
|
||||
let network_id = NetworkIdOf::<T>::default();
|
||||
|
||||
let mut claps = Vec::new();
|
||||
let mut companions = BTreeMap::new();
|
||||
|
||||
let authorities = vec![T::AuthorityId::generate_pair(None)];
|
||||
let bounded_authorities =
|
||||
WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities.clone())
|
||||
.map_err(|()| "more than the maximum number of keys provided")?;
|
||||
Authorities::<T>::put(bounded_authorities);
|
||||
|
||||
for index in 0..j {
|
||||
companions.insert(
|
||||
index.into(),
|
||||
amount,
|
||||
);
|
||||
}
|
||||
|
||||
self_applause {
|
||||
let session_index = T::ValidatorSet::session_index();
|
||||
let authorities = vec![T::AuthorityId::generate_pair(None)];
|
||||
let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities.clone())
|
||||
.map_err(|()| "more than the maximum number of keys provided")?;
|
||||
Authorities::<T>::set(&session_index, bounded_authorities);
|
||||
|
||||
let minimum_balance = <<T as pallet::Config>::Currency>::minimum_balance();
|
||||
let receiver = create_account::<T>();
|
||||
let receiver_clone = receiver.clone();
|
||||
let amount = minimum_balance + minimum_balance;
|
||||
let network_id = NetworkIdOf::<T>::default();
|
||||
let transaction_hash = H256::repeat_byte(1u8);
|
||||
|
||||
let unique_transaction_hash = <Pallet<T>>::generate_unique_hash(
|
||||
&receiver,
|
||||
&amount,
|
||||
&network_id,
|
||||
);
|
||||
let storage_key = (session_index, &transaction_hash, &unique_transaction_hash);
|
||||
|
||||
<Pallet::<T>>::trigger_nullification_for_benchmark();
|
||||
let clap = Clap {
|
||||
session_index,
|
||||
for _ in 0..i {
|
||||
claps.push(Clap {
|
||||
session_index: 1,
|
||||
authority_index: 0,
|
||||
transaction_hash,
|
||||
block_number: 69,
|
||||
removed: false,
|
||||
network_id,
|
||||
receiver: receiver.clone(),
|
||||
amount,
|
||||
};
|
||||
transaction_hash: H256::repeat_byte(1u8),
|
||||
block_number: 69,
|
||||
removed: true,
|
||||
receiver: create_account::<T>(),
|
||||
amount: total_amount,
|
||||
companions: companions.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
let authority_id = authorities
|
||||
.get(0usize)
|
||||
.expect("first authority should exist");
|
||||
let encoded_clap = clap.encode();
|
||||
let signature = authority_id.sign(&encoded_clap).unwrap();
|
||||
<Pallet<T>>::slow_clap(RawOrigin::None.into(), clap, signature)?;
|
||||
<Pallet::<T>>::trigger_nullification_for_benchmark();
|
||||
let authority_id = authorities
|
||||
.get(0usize)
|
||||
.expect("first authority should exist");
|
||||
let encoded_claps = claps.encode();
|
||||
let signature = authority_id.sign(&encoded_claps)
|
||||
.ok_or("couldn't make signature")?;
|
||||
|
||||
assert_eq!(<<T as pallet::Config>::Currency>::total_balance(&receiver), Default::default());
|
||||
assert_eq!(ApplausesForTransaction::<T>::get(&storage_key), false);
|
||||
}: _(RawOrigin::Signed(receiver_clone), network_id, session_index, transaction_hash, receiver_clone.clone(), amount)
|
||||
Ok((claps, signature))
|
||||
}
|
||||
|
||||
benchmarks! {
|
||||
slow_clap {
|
||||
let k in 1 .. MAX_CLAPS;
|
||||
let j in 1 .. MAX_COMPANIONS;
|
||||
|
||||
let receiver = H160::repeat_byte(69u8);
|
||||
let fee = H256::repeat_byte(0u8);
|
||||
let user_account: T::AccountId = whitelisted_caller();
|
||||
let network_id = <<T as pallet::Config>::NetworkDataHandler as NetworkDataBasicHandler>::NetworkId::default();
|
||||
|
||||
let (claps, signature) = create_claps::<T>(k, j)?;
|
||||
let _ = create_companions::<T>(j as usize, network_id, user_account, fee, receiver)?;
|
||||
}: _(RawOrigin::None, claps, signature)
|
||||
verify {
|
||||
assert_eq!(<<T as pallet::Config>::Currency>::total_balance(&receiver), amount);
|
||||
assert_eq!(ApplausesForTransaction::<T>::get(&storage_key), true);
|
||||
let minimum_balance = <<T as pallet::Config>::Currency>::minimum_balance();
|
||||
let total_amount = (minimum_balance + minimum_balance).saturating_mul(j.into());
|
||||
}
|
||||
|
||||
propose_companion {
|
||||
let receiver = H160::repeat_byte(69u8);
|
||||
let fee = H256::repeat_byte(0u8);
|
||||
let user_account: T::AccountId = whitelisted_caller();
|
||||
let network_id = <<T as pallet::Config>::NetworkDataHandler as NetworkDataBasicHandler>::NetworkId::default();
|
||||
// T::NetworkDataHandler::register(network_id.into(), NetworkData {
|
||||
// chain_name: "Ethereum".into(),
|
||||
// // https://nd-422-757-666.p2pify.com/0a9d79d93fb2f4a4b1e04695da2b77a7/
|
||||
// default_endpoint:
|
||||
// "https://base-mainnet.core.chainstack.com/2fc1de7f08c0465f6a28e3c355e0cb14/".into(),
|
||||
// finality_delay: Some(50),
|
||||
// release_delay: Some(100),
|
||||
// network_type: Default::default(),
|
||||
// gatekeeper: b"0x1234567891234567891234567891234567891234".to_vec(),
|
||||
// topic_name: b"0x12345678912345678912345678912345678912345678912345678912345678".to_vec(),
|
||||
// incoming_fee: 0,
|
||||
// outgoing_fee: 0,
|
||||
// }).map_err(|_| BenchmarkError::Weightless)?;
|
||||
let companion_id = create_companions::<T>(1, network_id, user_account.clone(), fee, receiver)?;
|
||||
let companion_id = SlowClap::<T>::current_companion_id();
|
||||
let minimum_balance = <<T as pallet::Config>::Currency>::minimum_balance();
|
||||
let balance = minimum_balance + minimum_balance;
|
||||
let companion = Companion::<NetworkIdOf::<T>, BalanceOf::<T>> {
|
||||
network_id: network_id.into(), receiver,
|
||||
fee, amount: balance,
|
||||
};
|
||||
let _ = <<T as pallet::Config>::Currency>::mint_into(&user_account, balance);
|
||||
assert_eq!(SlowClap::<T>::current_companion_id(), companion_id);
|
||||
}: _(RawOrigin::Signed(user_account), network_id.into(), companion)
|
||||
verify {
|
||||
assert_eq!(SlowClap::<T>::current_companion_id(), companion_id + 1);
|
||||
}
|
||||
|
||||
release_companion {
|
||||
let receiver = H160::repeat_byte(69u8);
|
||||
let fee = H256::repeat_byte(0u8);
|
||||
let user_account: T::AccountId = whitelisted_caller();
|
||||
let network_id = <<T as pallet::Config>::NetworkDataHandler as NetworkDataBasicHandler>::NetworkId::default();
|
||||
let companion_id = create_companions::<T>(1, network_id, user_account.clone(), fee, receiver)?;
|
||||
assert_eq!(SlowClap::<T>::release_blocks(companion_id), BlockNumberFor::<T>::default());
|
||||
}: _(RawOrigin::Signed(user_account), network_id.into(), companion_id)
|
||||
verify {
|
||||
assert_ne!(SlowClap::<T>::release_blocks(companion_id), BlockNumberFor::<T>::default());
|
||||
}
|
||||
|
||||
kill_companion {
|
||||
let receiver = H160::repeat_byte(69u8);
|
||||
let fee = H256::repeat_byte(0u8);
|
||||
let user_account: T::AccountId = whitelisted_caller();
|
||||
let network_id = <<T as pallet::Config>::NetworkDataHandler as NetworkDataBasicHandler>::NetworkId::default();
|
||||
let companion_id = create_companions::<T>(1, network_id, user_account.clone(), fee, receiver)?;
|
||||
SlowClap::<T>::release_companion(
|
||||
RawOrigin::Signed(user_account.clone()).into(),
|
||||
network_id,
|
||||
companion_id,
|
||||
)?;
|
||||
let block_shift =
|
||||
<<T as pallet::Config>::NetworkDataHandler as NetworkDataInspectHandler<NetworkData>>::get(&network_id)
|
||||
.unwrap()
|
||||
.release_delay
|
||||
.unwrap();
|
||||
frame_system::Pallet::<T>::set_block_number((block_shift + 1).saturated_into());
|
||||
}: _(RawOrigin::Signed(user_account), network_id.into(), companion_id)
|
||||
verify {
|
||||
assert_eq!(SlowClap::<T>::companions(network_id, companion_id), None);
|
||||
assert_eq!(SlowClap::<T>::companion_details(companion_id), None);
|
||||
assert_eq!(SlowClap::<T>::current_companion_id(), companion_id + 1);
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(
|
||||
|
@ -1,57 +0,0 @@
|
||||
use crate::{Deserialize, Deserializer, Vec, H256};
|
||||
|
||||
pub fn de_string_to_bytes<'de, D>(de: D) -> Result<Option<Vec<u8>>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s: &str = Deserialize::deserialize(de)?;
|
||||
Ok(Some(s.as_bytes().to_vec()))
|
||||
}
|
||||
|
||||
pub fn de_string_to_u64<'de, D>(de: D) -> Result<Option<u64>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s: &str = Deserialize::deserialize(de)?;
|
||||
let s = if s.starts_with("0x") { &s[2..] } else { &s };
|
||||
Ok(u64::from_str_radix(s, 16).ok())
|
||||
}
|
||||
|
||||
pub fn de_string_to_u64_pure<'de, D>(de: D) -> Result<u64, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s: &str = Deserialize::deserialize(de)?;
|
||||
let s = if s.starts_with("0x") { &s[2..] } else { &s };
|
||||
Ok(u64::from_str_radix(s, 16).unwrap_or_default())
|
||||
}
|
||||
|
||||
pub fn de_string_to_h256<'de, D>(de: D) -> Result<Option<H256>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s: &str = Deserialize::deserialize(de)?;
|
||||
let start_index = if s.starts_with("0x") { 2 } else { 0 };
|
||||
let h256: Vec<_> = (start_index..s.len())
|
||||
.step_by(2)
|
||||
.map(|i| u8::from_str_radix(&s[i..i + 2], 16).expect("valid u8 symbol; qed"))
|
||||
.collect();
|
||||
Ok(Some(H256::from_slice(&h256)))
|
||||
}
|
||||
|
||||
pub fn de_string_to_vec_of_bytes<'de, D>(de: D) -> Result<Vec<Vec<u8>>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let strings: Vec<&str> = Deserialize::deserialize(de)?;
|
||||
Ok(strings
|
||||
.iter()
|
||||
.map(|s| {
|
||||
let start_index = if s.starts_with("0x") { 2 } else { 0 };
|
||||
(start_index..s.len())
|
||||
.step_by(2)
|
||||
.map(|i| u8::from_str_radix(&s[i..i + 2], 16).expect("valid u8 symbol; qed"))
|
||||
.collect::<Vec<u8>>()
|
||||
})
|
||||
.collect::<Vec<Vec<u8>>>())
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
use crate::{
|
||||
deserialisations::{
|
||||
de_string_to_bytes, de_string_to_h256, de_string_to_u64, de_string_to_u64_pure,
|
||||
de_string_to_vec_of_bytes,
|
||||
},
|
||||
Decode, Deserialize, Encode, RuntimeDebug, Vec, H256,
|
||||
};
|
||||
|
||||
const NUMBER_OF_TOPICS: usize = 3;
|
||||
|
||||
#[derive(RuntimeDebug, Clone, PartialEq, Deserialize, Encode, Decode)]
|
||||
pub struct EvmResponse {
|
||||
#[serde(default)]
|
||||
id: Option<u32>,
|
||||
#[serde(default, deserialize_with = "de_string_to_bytes")]
|
||||
jsonrpc: Option<Vec<u8>>,
|
||||
#[serde(default, deserialize_with = "de_string_to_bytes")]
|
||||
pub error: Option<Vec<u8>>,
|
||||
#[serde(default)]
|
||||
pub result: Option<EvmResponseType>,
|
||||
}
|
||||
|
||||
#[derive(RuntimeDebug, Clone, PartialEq, Deserialize, Encode, Decode)]
|
||||
#[serde(untagged)]
|
||||
pub enum EvmResponseType {
|
||||
#[serde(deserialize_with = "de_string_to_u64_pure")]
|
||||
BlockNumber(u64),
|
||||
TransactionLogs(Vec<Log>),
|
||||
}
|
||||
|
||||
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Ord, PartialOrd, Deserialize, Encode, Decode)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Log {
|
||||
#[serde(default, deserialize_with = "de_string_to_h256")]
|
||||
pub transaction_hash: Option<H256>,
|
||||
#[serde(default, deserialize_with = "de_string_to_u64")]
|
||||
pub block_number: Option<u64>,
|
||||
#[serde(default, deserialize_with = "de_string_to_vec_of_bytes")]
|
||||
pub topics: Vec<Vec<u8>>,
|
||||
pub removed: bool,
|
||||
}
|
||||
|
||||
impl Log {
|
||||
pub fn is_sufficient(&self) -> bool {
|
||||
self.transaction_hash.is_some()
|
||||
&& self.block_number.is_some()
|
||||
&& self.topics.len() == NUMBER_OF_TOPICS
|
||||
}
|
||||
}
|
1573
pallets/slow-clap/src/lib.rs
Normal file → Executable file
@ -4,22 +4,20 @@ use frame_support::{
|
||||
derive_impl, parameter_types,
|
||||
traits::{ConstU32, ConstU64},
|
||||
weights::Weight,
|
||||
PalletId,
|
||||
};
|
||||
use frame_system::EnsureRoot;
|
||||
use pallet_session::historical as pallet_session_historical;
|
||||
use sp_runtime::{
|
||||
curve::PiecewiseLinear,
|
||||
testing::{TestXt, UintAuthorityId},
|
||||
traits::ConvertInto,
|
||||
Permill,
|
||||
BuildStorage, Permill,
|
||||
};
|
||||
use sp_staking::{
|
||||
offence::{OffenceError, ReportOffence},
|
||||
SessionIndex,
|
||||
};
|
||||
|
||||
use sp_runtime::BuildStorage;
|
||||
|
||||
use crate as slow_clap;
|
||||
use crate::Config;
|
||||
|
||||
@ -38,8 +36,8 @@ frame_support::construct_runtime!(
|
||||
|
||||
parameter_types! {
|
||||
pub static Validators: Option<Vec<u64>> = Some(vec![
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]);
|
||||
}
|
||||
@ -55,10 +53,13 @@ impl pallet_session::SessionManager<u64> for TestSessionManager {
|
||||
|
||||
impl pallet_session::historical::SessionManager<u64, u64> for TestSessionManager {
|
||||
fn new_session(_new_index: SessionIndex) -> Option<Vec<(u64, u64)>> {
|
||||
Validators::mutate(|l| {
|
||||
l.take()
|
||||
.map(|validators| validators.iter().map(|v| (*v, *v)).collect())
|
||||
})
|
||||
Validators::mutate(|l| l
|
||||
.take()
|
||||
.map(|validators| validators
|
||||
.iter()
|
||||
.map(|v| (*v, *v))
|
||||
.collect())
|
||||
)
|
||||
}
|
||||
fn end_session(_: SessionIndex) {}
|
||||
fn start_session(_: SessionIndex) {}
|
||||
@ -83,21 +84,24 @@ impl ReportOffence<u64, IdentificationTuple, Offence> for OffenceHandler {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alice_account_id() -> <Runtime as frame_system::Config>::AccountId { 69 }
|
||||
pub fn eve_account_id() -> <Runtime as frame_system::Config>::AccountId { 1337 }
|
||||
|
||||
pub fn new_test_ext() -> sp_io::TestExternalities {
|
||||
let t = frame_system::GenesisConfig::<Runtime>::default()
|
||||
let mut t = frame_system::GenesisConfig::<Runtime>::default()
|
||||
.build_storage()
|
||||
.unwrap();
|
||||
|
||||
pallet_balances::GenesisConfig::<Runtime> {
|
||||
balances: vec![ (alice_account_id(), 100) ],
|
||||
}
|
||||
.assimilate_storage(&mut t)
|
||||
.unwrap();
|
||||
|
||||
let mut result = sp_io::TestExternalities::new(t);
|
||||
|
||||
result.execute_with(|| {
|
||||
for i in 1..=3 {
|
||||
System::inc_providers(&i);
|
||||
assert_eq!(
|
||||
Session::set_keys(RuntimeOrigin::signed(i), i.into(), vec![],),
|
||||
Ok(())
|
||||
);
|
||||
}
|
||||
System::set_block_number(1);
|
||||
});
|
||||
|
||||
result
|
||||
@ -148,7 +152,7 @@ impl frame_support::traits::EstimateNextSessionRotation<u64> for TestNextSession
|
||||
}
|
||||
|
||||
fn estimate_current_session_progress(now: u64) -> (Option<Permill>, Weight) {
|
||||
let (estimate, weight) =
|
||||
let (estimate, weight) =
|
||||
pallet_session::PeriodicSessions::<Period, Offset>::estimate_current_session_progress(
|
||||
now,
|
||||
);
|
||||
@ -163,7 +167,6 @@ impl frame_support::traits::EstimateNextSessionRotation<u64> for TestNextSession
|
||||
|
||||
impl ghost_networks::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Currency = Balances;
|
||||
type NetworkId = u32;
|
||||
type RegisterOrigin = EnsureRoot<Self::AccountId>;
|
||||
type UpdateOrigin = EnsureRoot<Self::AccountId>;
|
||||
@ -171,21 +174,9 @@ impl ghost_networks::Config for Runtime {
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
pallet_staking_reward_curve::build! {
|
||||
const REWARD_CURVE: PiecewiseLinear<'static> = curve!(
|
||||
min_inflation: 0_006_000,
|
||||
max_inflation: 1_000_000,
|
||||
ideal_stake: 0_690_000,
|
||||
falloff: 0_050_000,
|
||||
max_piece_count: 100,
|
||||
test_precision: 0_005_000,
|
||||
);
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub static ExistentialDeposit: u64 = 2;
|
||||
pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
|
||||
pub const HistoryDepth: u32 = 10;
|
||||
pub const TreasuryPalletId: PalletId = PalletId(*b"mck/test");
|
||||
}
|
||||
|
||||
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
|
||||
@ -208,16 +199,23 @@ impl Config for Runtime {
|
||||
type ReportUnresponsiveness = OffenceHandler;
|
||||
|
||||
type MaxAuthorities = ConstU32<5>;
|
||||
type ApplauseThreshold = ConstU32<50>;
|
||||
type OffenceThreshold = ConstU32<75>;
|
||||
type MaxNumberOfClaps = ConstU32<100>;
|
||||
type ApplauseThreshold = ConstU32<0>;
|
||||
type MaxAuthorityInfoInSession = ConstU32<5_000>;
|
||||
type OffenceThreshold = ConstU32<40>;
|
||||
type UnsignedPriority = ConstU64<{ 1 << 20 }>;
|
||||
type HistoryDepth = HistoryDepth;
|
||||
type TreasuryPalletId = TreasuryPalletId;
|
||||
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
pub type Extrinsic = TestXt<RuntimeCall, ()>;
|
||||
|
||||
// impl frame_system::offchain::SigningTypes for Runtime {
|
||||
// type Public = <Signature as Verify>::Signer;
|
||||
// type Signature = Signature;
|
||||
// }
|
||||
|
||||
impl<LocalCall> frame_system::offchain::SendTransactionTypes<LocalCall> for Runtime
|
||||
where
|
||||
RuntimeCall: From<LocalCall>,
|
||||
@ -226,36 +224,30 @@ where
|
||||
type Extrinsic = Extrinsic;
|
||||
}
|
||||
|
||||
pub fn advance_session() {
|
||||
let now = System::block_number().max(1);
|
||||
System::set_block_number(now + 1);
|
||||
Session::rotate_session();
|
||||
let session_index = Session::current_index();
|
||||
// impl<LocalCall> frame_system::offchain::CreateSignedTransaction<LocalCall> for Runtime
|
||||
// where
|
||||
// RuntimeCall: From<LocalCall>,
|
||||
// {
|
||||
// fn create_transaction<C: frame_system::offchain::AppCrypto<Self::Public, Self::Signature>>(
|
||||
// call: Self::OverarchingCall,
|
||||
// _public: Self::Public,
|
||||
// _account: Self::AccountId,
|
||||
// nonce: Self::Nonce,
|
||||
// ) -> Option<(RuntimeCall, <Extrinsic as ExtrinsicT>::SignaturePayload)> {
|
||||
// Some((call, (nonce.into(), ())))
|
||||
// }
|
||||
// }
|
||||
|
||||
let authorities = Session::validators()
|
||||
.into_iter()
|
||||
.map(UintAuthorityId)
|
||||
.collect();
|
||||
|
||||
SlowClap::set_test_authorities(session_index, authorities);
|
||||
assert_eq!(session_index, (now / Period::get()) as u32);
|
||||
}
|
||||
|
||||
pub fn advance_session_with_authority(authority: u64) {
|
||||
let now = System::block_number().max(1);
|
||||
System::set_block_number(now + 1);
|
||||
Session::rotate_session();
|
||||
|
||||
let session_index = Session::current_index();
|
||||
|
||||
SlowClap::set_test_authorities(
|
||||
session_index,
|
||||
vec![
|
||||
UintAuthorityId::from(authority),
|
||||
UintAuthorityId::from(69),
|
||||
UintAuthorityId::from(420),
|
||||
UintAuthorityId::from(1337),
|
||||
],
|
||||
);
|
||||
assert_eq!(session_index, (now / Period::get()) as u32);
|
||||
}
|
||||
// pub fn advance_session() {
|
||||
// let now = System::block_number().max(1);
|
||||
// System::set_block_number(now + 1);
|
||||
// Session::rotate_session();
|
||||
//
|
||||
// let authorities = Session::validators()
|
||||
// .into_iter()
|
||||
// .map(UintAuthorityId)
|
||||
// .collect();
|
||||
//
|
||||
// SlowClap::set_authorities(authorities);
|
||||
// assert_eq!(Session::current_index(), (now / Period::get()) as u32);
|
||||
// }
|
||||
|
@ -1,176 +1,18 @@
|
||||
// This file is part of Ghost Network.
|
||||
|
||||
// Ghost Network 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.
|
||||
|
||||
// Ghost Network 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 Ghost Network. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Autogenerated weights for `ghost_slow_clap`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
|
||||
//! DATE: 2025-06-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
|
||||
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/ghost
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=casper-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=ghost_slow_clap
|
||||
// --extrinsic=*
|
||||
// --wasm-execution=compiled
|
||||
// --heap-pages=4096
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/casper/src/weights/ghost_slow_clap.rs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use frame_support::{
|
||||
traits::Get,
|
||||
weights::{Weight, constants::RocksDbWeight}
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
use frame_support::weights::Weight;
|
||||
|
||||
pub trait WeightInfo {
|
||||
fn slow_clap() -> Weight;
|
||||
fn self_applause()-> Weight;
|
||||
}
|
||||
|
||||
/// Weight functions for `ghost_slow_clap`.
|
||||
pub struct SubstrateWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
/// Storage: `GhostSlowClaps::Authorities` (r:1 w:0)
|
||||
/// Proof: `GhostSlowClaps::Authorities` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostSlowClaps::ReceivedClaps` (r:1 w:1)
|
||||
/// Proof: `GhostSlowClaps::ReceivedClaps` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostSlowClaps::ClapsInSession` (r:1 w:1)
|
||||
/// Proof: `GhostSlowClaps::ClapsInSession` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostSlowClaps::ApplausesForTransaction` (r:1 w:1)
|
||||
/// Proof: `GhostSlowClaps::ApplausesForTransaction` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::NullifyNeeded` (r:1 w:0)
|
||||
/// Proof: `GhostNetworks::NullifyNeeded` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:0)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::GatekeeperAmount` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::GatekeeperAmount` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::BridgedImbalance` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::BridgedImbalance` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::AccumulatedCommission` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::AccumulatedCommission` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `System::Account` (r:1 w:1)
|
||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
||||
fn slow_clap() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `355`
|
||||
// Estimated: `3820`
|
||||
// Minimum execution time: 213_817_000 picoseconds.
|
||||
Weight::from_parts(216_977_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3820))
|
||||
.saturating_add(T::DbWeight::get().reads(10))
|
||||
.saturating_add(T::DbWeight::get().writes(7))
|
||||
}
|
||||
/// Storage: `GhostSlowClaps::ReceivedClaps` (r:1 w:0)
|
||||
/// Proof: `GhostSlowClaps::ReceivedClaps` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostSlowClaps::Authorities` (r:1 w:0)
|
||||
/// Proof: `GhostSlowClaps::Authorities` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostSlowClaps::ApplausesForTransaction` (r:1 w:1)
|
||||
/// Proof: `GhostSlowClaps::ApplausesForTransaction` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::NullifyNeeded` (r:1 w:0)
|
||||
/// Proof: `GhostNetworks::NullifyNeeded` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:0)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::GatekeeperAmount` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::GatekeeperAmount` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::BridgedImbalance` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::BridgedImbalance` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::AccumulatedCommission` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::AccumulatedCommission` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `System::Account` (r:1 w:1)
|
||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
||||
fn self_applause() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `655`
|
||||
// Estimated: `4120`
|
||||
// Minimum execution time: 210_676_000 picoseconds.
|
||||
Weight::from_parts(212_905_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4120))
|
||||
.saturating_add(T::DbWeight::get().reads(9))
|
||||
.saturating_add(T::DbWeight::get().writes(5))
|
||||
}
|
||||
fn slow_clap(claps_len: u32, companions_len: u32) -> Weight;
|
||||
fn propose_companion() -> Weight;
|
||||
fn release_companion() -> Weight;
|
||||
fn kill_companion() -> Weight;
|
||||
}
|
||||
|
||||
impl WeightInfo for () {
|
||||
/// Storage: `GhostSlowClaps::Authorities` (r:1 w:0)
|
||||
/// Proof: `GhostSlowClaps::Authorities` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostSlowClaps::ReceivedClaps` (r:1 w:1)
|
||||
/// Proof: `GhostSlowClaps::ReceivedClaps` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostSlowClaps::ClapsInSession` (r:1 w:1)
|
||||
/// Proof: `GhostSlowClaps::ClapsInSession` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostSlowClaps::ApplausesForTransaction` (r:1 w:1)
|
||||
/// Proof: `GhostSlowClaps::ApplausesForTransaction` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::NullifyNeeded` (r:1 w:0)
|
||||
/// Proof: `GhostNetworks::NullifyNeeded` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:0)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::GatekeeperAmount` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::GatekeeperAmount` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::BridgedImbalance` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::BridgedImbalance` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::AccumulatedCommission` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::AccumulatedCommission` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `System::Account` (r:1 w:1)
|
||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
||||
fn slow_clap() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `355`
|
||||
// Estimated: `3820`
|
||||
// Minimum execution time: 213_817_000 picoseconds.
|
||||
Weight::from_parts(216_977_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3820))
|
||||
.saturating_add(RocksDbWeight::get().reads(10))
|
||||
.saturating_add(RocksDbWeight::get().writes(7))
|
||||
}
|
||||
/// Storage: `GhostSlowClaps::ReceivedClaps` (r:1 w:0)
|
||||
/// Proof: `GhostSlowClaps::ReceivedClaps` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostSlowClaps::Authorities` (r:1 w:0)
|
||||
/// Proof: `GhostSlowClaps::Authorities` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostSlowClaps::ApplausesForTransaction` (r:1 w:1)
|
||||
/// Proof: `GhostSlowClaps::ApplausesForTransaction` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::NullifyNeeded` (r:1 w:0)
|
||||
/// Proof: `GhostNetworks::NullifyNeeded` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::Networks` (r:1 w:0)
|
||||
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::GatekeeperAmount` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::GatekeeperAmount` (`max_values`: None, `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::BridgedImbalance` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::BridgedImbalance` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `GhostNetworks::AccumulatedCommission` (r:1 w:1)
|
||||
/// Proof: `GhostNetworks::AccumulatedCommission` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `System::Account` (r:1 w:1)
|
||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
||||
fn self_applause() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `655`
|
||||
// Estimated: `4120`
|
||||
// Minimum execution time: 210_676_000 picoseconds.
|
||||
Weight::from_parts(212_905_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4120))
|
||||
.saturating_add(RocksDbWeight::get().reads(9))
|
||||
.saturating_add(RocksDbWeight::get().writes(5))
|
||||
}
|
||||
fn slow_clap(
|
||||
_claps_len: u32,
|
||||
_companions_len: u32,
|
||||
) -> Weight { Weight::zero() }
|
||||
fn propose_companion() -> Weight { Weight::zero() }
|
||||
fn release_companion() -> Weight { Weight::zero() }
|
||||
fn kill_companion() -> Weight { Weight::zero() }
|
||||
}
|
||||
|
@ -1,45 +0,0 @@
|
||||
[package]
|
||||
name = "ghost-sudo"
|
||||
version = "0.0.2"
|
||||
description = "Port of the sudo pallet because of dependencies issue"
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
docify = "0.2.8"
|
||||
codec = { workspace = true, features = ["derive"] }
|
||||
frame-benchmarking = { workspace = true, optional = true }
|
||||
scale-info = { workspace = true, features = ["derive"] }
|
||||
frame-support = { workspace = true }
|
||||
frame-system = { workspace = true }
|
||||
|
||||
sp-io = { workspace = true }
|
||||
sp-runtime = { workspace = true }
|
||||
sp-std = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
"frame-benchmarking?/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
"scale-info/std",
|
||||
"sp-io/std",
|
||||
"sp-runtime/std",
|
||||
"sp-std/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"frame-benchmarking/runtime-benchmarks",
|
||||
"frame-support/runtime-benchmarks",
|
||||
"frame-system/runtime-benchmarks",
|
||||
"sp-runtime/runtime-benchmarks",
|
||||
]
|
||||
try-runtime = [
|
||||
"frame-support/try-runtime",
|
||||
"frame-system/try-runtime",
|
||||
"sp-runtime/try-runtime",
|
||||
]
|
@ -1,77 +0,0 @@
|
||||
use super::*;
|
||||
use crate::Pallet;
|
||||
use frame_benchmarking::v2::*;
|
||||
use frame_system::RawOrigin;
|
||||
|
||||
fn assert_last_event<T: Config>(generic_event: crate::Event<T>) {
|
||||
let re: <T as Config>::RuntimeEvent = generic_event.into();
|
||||
frame_system::Pallet::<T>::assert_last_event(re.into());
|
||||
}
|
||||
|
||||
#[benchmarks(where <T as Config>::RuntimeCall: From<frame_system::Call<T>>)]
|
||||
mod benchmarks {
|
||||
use super::*;
|
||||
|
||||
#[benchmark]
|
||||
fn set_key() {
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
Key::<T>::put(&caller);
|
||||
|
||||
let new_sudoer: T::AccountId = account("sudoer", 0, 0);
|
||||
let new_sudoer_lookup = T::Lookup::unlookup(new_sudoer.clone());
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(caller.clone()), new_sudoer_lookup);
|
||||
|
||||
assert_last_event::<T>(Event::KeyChanged {
|
||||
old: Some(caller),
|
||||
new: new_sudoer,
|
||||
});
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn sudo() {
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
Key::<T>::put(&caller);
|
||||
|
||||
let call = frame_system::Call::remark { remark: vec![] }.into();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(caller), Box::new(call));
|
||||
|
||||
assert_last_event::<T>(Event::Sudid {
|
||||
sudo_result: Ok(()),
|
||||
})
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn sudo_as() {
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
Key::<T>::put(caller.clone());
|
||||
|
||||
let call = frame_system::Call::remark { remark: vec![] }.into();
|
||||
|
||||
let who: T::AccountId = account("as", 0, 0);
|
||||
let who_lookup = T::Lookup::unlookup(who);
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(caller), who_lookup, Box::new(call));
|
||||
|
||||
assert_last_event::<T>(Event::SudoAsDone {
|
||||
sudo_result: Ok(()),
|
||||
})
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn remove_key() {
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
Key::<T>::put(&caller);
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(caller.clone()));
|
||||
|
||||
assert_last_event::<T>(Event::KeyRemoved {});
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(Pallet, crate::mock::new_bench_ext(), crate::mock::Test);
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
use crate::{Config, Key};
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::{dispatch::DispatchInfo, ensure};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{
|
||||
traits::{DispatchInfoOf, Dispatchable, SignedExtension},
|
||||
transaction_validity::{
|
||||
InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError,
|
||||
UnknownTransaction, ValidTransaction,
|
||||
},
|
||||
};
|
||||
use sp_std::{fmt, marker::PhantomData};
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||
#[scale_info(skip_type_params(T))]
|
||||
pub struct CheckOnlySudoAccount<T: Config + Send + Sync>(PhantomData<T>);
|
||||
|
||||
impl<T: Config + Send + Sync> Default for CheckOnlySudoAccount<T> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config + Send + Sync> fmt::Debug for CheckOnlySudoAccount<T> {
|
||||
#[cfg(feature = "std")]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "CheckOnlySudoAccount")
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config + Send + Sync> CheckOnlySudoAccount<T> {
|
||||
/// Creates new `SignedExtension` to check sudo key.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config + Send + Sync> SignedExtension for CheckOnlySudoAccount<T>
|
||||
where
|
||||
<T as Config>::RuntimeCall: Dispatchable<Info = DispatchInfo>,
|
||||
{
|
||||
const IDENTIFIER: &'static str = "CheckOnlySudoAccount";
|
||||
type AccountId = T::AccountId;
|
||||
type Call = <T as Config>::RuntimeCall;
|
||||
type AdditionalSigned = ();
|
||||
type Pre = ();
|
||||
|
||||
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
who: &Self::AccountId,
|
||||
_call: &Self::Call,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
) -> TransactionValidity {
|
||||
let sudo_key: T::AccountId = Key::<T>::get().ok_or(UnknownTransaction::CannotLookup)?;
|
||||
ensure!(*who == sudo_key, InvalidTransaction::BadSigner);
|
||||
|
||||
Ok(ValidTransaction {
|
||||
priority: info.weight.ref_time() as TransactionPriority,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
fn pre_dispatch(
|
||||
self,
|
||||
who: &Self::AccountId,
|
||||
call: &Self::Call,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> Result<Self::Pre, TransactionValidityError> {
|
||||
self.validate(who, call, info, len).map(|_| ())
|
||||
}
|
||||
}
|
@ -1,212 +0,0 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use sp_runtime::{traits::StaticLookup, DispatchResult};
|
||||
use sp_std::prelude::*;
|
||||
|
||||
use frame_support::{dispatch::GetDispatchInfo, traits::UnfilteredDispatchable};
|
||||
|
||||
mod extension;
|
||||
#[cfg(test)]
|
||||
mod mock;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benchmarking;
|
||||
pub mod weights;
|
||||
pub use weights::WeightInfo;
|
||||
|
||||
pub use extension::CheckOnlySudoAccount;
|
||||
pub use pallet::*;
|
||||
|
||||
type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::{DispatchResult, *};
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::{pallet_prelude::*, RawOrigin};
|
||||
|
||||
pub mod config_preludes {
|
||||
use super::*;
|
||||
use frame_support::derive_impl;
|
||||
|
||||
pub struct TestDefaultConfig;
|
||||
|
||||
#[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
|
||||
impl frame_system::DefaultConfig for TestDefaultConfig {}
|
||||
|
||||
#[frame_support::register_default_impl(TestDefaultConfig)]
|
||||
impl DefaultConfig for TestDefaultConfig {
|
||||
type WeightInfo = ();
|
||||
#[inject_runtime_type]
|
||||
type RuntimeEvent = ();
|
||||
#[inject_runtime_type]
|
||||
type RuntimeCall = ();
|
||||
}
|
||||
}
|
||||
#[pallet::config(with_default)]
|
||||
pub trait Config: frame_system::Config {
|
||||
#[pallet::no_default_bounds]
|
||||
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
|
||||
#[pallet::no_default_bounds]
|
||||
type RuntimeCall: Parameter
|
||||
+ UnfilteredDispatchable<RuntimeOrigin = Self::RuntimeOrigin>
|
||||
+ GetDispatchInfo;
|
||||
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
#[pallet::call_index(0)]
|
||||
#[pallet::weight({
|
||||
let dispatch_info = call.get_dispatch_info();
|
||||
(
|
||||
T::WeightInfo::sudo().saturating_add(dispatch_info.weight),
|
||||
dispatch_info.class
|
||||
)
|
||||
})]
|
||||
pub fn sudo(
|
||||
origin: OriginFor<T>,
|
||||
call: Box<<T as Config>::RuntimeCall>,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
Self::ensure_sudo(origin)?;
|
||||
|
||||
let res = call.dispatch_bypass_filter(RawOrigin::Root.into());
|
||||
Self::deposit_event(Event::Sudid {
|
||||
sudo_result: res.map(|_| ()).map_err(|e| e.error),
|
||||
});
|
||||
|
||||
Ok(Pays::No.into())
|
||||
}
|
||||
|
||||
#[pallet::call_index(1)]
|
||||
#[pallet::weight((*weight, call.get_dispatch_info().class))]
|
||||
pub fn sudo_unchecked_weight(
|
||||
origin: OriginFor<T>,
|
||||
call: Box<<T as Config>::RuntimeCall>,
|
||||
weight: Weight,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
Self::ensure_sudo(origin)?;
|
||||
let _ = weight;
|
||||
|
||||
let res = call.dispatch_bypass_filter(RawOrigin::Root.into());
|
||||
Self::deposit_event(Event::Sudid {
|
||||
sudo_result: res.map(|_| ()).map_err(|e| e.error),
|
||||
});
|
||||
|
||||
Ok(Pays::No.into())
|
||||
}
|
||||
|
||||
#[pallet::call_index(2)]
|
||||
#[pallet::weight(T::WeightInfo::set_key())]
|
||||
pub fn set_key(
|
||||
origin: OriginFor<T>,
|
||||
new: AccountIdLookupOf<T>,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
Self::ensure_sudo(origin)?;
|
||||
|
||||
let new = T::Lookup::lookup(new)?;
|
||||
Self::deposit_event(Event::KeyChanged {
|
||||
old: Key::<T>::get(),
|
||||
new: new.clone(),
|
||||
});
|
||||
Key::<T>::put(new);
|
||||
|
||||
Ok(Pays::No.into())
|
||||
}
|
||||
|
||||
#[pallet::call_index(3)]
|
||||
#[pallet::weight({
|
||||
let dispatch_info = call.get_dispatch_info();
|
||||
(
|
||||
T::WeightInfo::sudo_as().saturating_add(dispatch_info.weight),
|
||||
dispatch_info.class,
|
||||
)
|
||||
})]
|
||||
pub fn sudo_as(
|
||||
origin: OriginFor<T>,
|
||||
who: AccountIdLookupOf<T>,
|
||||
call: Box<<T as Config>::RuntimeCall>,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
Self::ensure_sudo(origin)?;
|
||||
|
||||
let who = T::Lookup::lookup(who)?;
|
||||
let res = call.dispatch_bypass_filter(RawOrigin::Signed(who).into());
|
||||
Self::deposit_event(Event::SudoAsDone {
|
||||
sudo_result: res.map(|_| ()).map_err(|e| e.error),
|
||||
});
|
||||
|
||||
Ok(Pays::No.into())
|
||||
}
|
||||
|
||||
#[pallet::call_index(4)]
|
||||
#[pallet::weight(T::WeightInfo::remove_key())]
|
||||
pub fn remove_key(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
|
||||
Self::ensure_sudo(origin)?;
|
||||
|
||||
Self::deposit_event(Event::KeyRemoved {});
|
||||
Key::<T>::kill();
|
||||
|
||||
Ok(Pays::No.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config> {
|
||||
Sudid {
|
||||
sudo_result: DispatchResult,
|
||||
},
|
||||
KeyChanged {
|
||||
old: Option<T::AccountId>,
|
||||
new: T::AccountId,
|
||||
},
|
||||
KeyRemoved,
|
||||
SudoAsDone {
|
||||
sudo_result: DispatchResult,
|
||||
},
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
RequireSudo,
|
||||
}
|
||||
|
||||
#[pallet::storage]
|
||||
pub(super) type Key<T: Config> = StorageValue<_, T::AccountId, OptionQuery>;
|
||||
|
||||
#[pallet::genesis_config]
|
||||
#[derive(frame_support::DefaultNoBound)]
|
||||
pub struct GenesisConfig<T: Config> {
|
||||
pub key: Option<T::AccountId>,
|
||||
}
|
||||
|
||||
#[pallet::genesis_build]
|
||||
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
|
||||
fn build(&self) {
|
||||
Key::<T>::set(self.key.clone());
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
pub(crate) fn ensure_sudo(origin: OriginFor<T>) -> DispatchResult {
|
||||
let sender = ensure_signed_or_root(origin)?;
|
||||
|
||||
if let Some(sender) = sender {
|
||||
if Key::<T>::get().map_or(false, |k| k == sender) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::<T>::RequireSudo.into())
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
use super::*;
|
||||
use crate as sudo;
|
||||
use frame_support::derive_impl;
|
||||
use sp_io;
|
||||
use sp_runtime::BuildStorage;
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod logger {
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config {
|
||||
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
#[pallet::call_index(0)]
|
||||
#[pallet::weight(*weight)]
|
||||
pub fn privileged_i32_log(
|
||||
origin: OriginFor<T>,
|
||||
i: i32,
|
||||
weight: Weight,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
ensure_root(origin)?;
|
||||
<I32Log<T>>::try_append(i).map_err(|_| "could not append")?;
|
||||
Self::deposit_event(Event::AppendI32 { value: i, weight });
|
||||
Ok(().into())
|
||||
}
|
||||
|
||||
#[pallet::call_index(1)]
|
||||
#[pallet::weight(*weight)]
|
||||
pub fn non_privileged_log(
|
||||
origin: OriginFor<T>,
|
||||
i: i32,
|
||||
weight: Weight,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let sender = ensure_signed(origin)?;
|
||||
<I32Log<T>>::try_append(i).map_err(|_| "could not append")?;
|
||||
<AccountLog<T>>::try_append(sender.clone()).map_err(|_| "could not append")?;
|
||||
Self::deposit_event(Event::AppendI32AndAccount {
|
||||
sender,
|
||||
value: i,
|
||||
weight,
|
||||
});
|
||||
Ok(().into())
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config> {
|
||||
AppendI32 {
|
||||
value: i32,
|
||||
weight: Weight,
|
||||
},
|
||||
AppendI32AndAccount {
|
||||
sender: T::AccountId,
|
||||
value: i32,
|
||||
weight: Weight,
|
||||
},
|
||||
}
|
||||
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn account_log)]
|
||||
pub(super) type AccountLog<T: Config> =
|
||||
StorageValue<_, BoundedVec<T::AccountId, ConstU32<1_000>>, ValueQuery>;
|
||||
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn i32_log)]
|
||||
pub(super) type I32Log<T> = StorageValue<_, BoundedVec<i32, ConstU32<1_000>>, ValueQuery>;
|
||||
}
|
||||
|
||||
type Block = frame_system::mocking::MockBlock<Test>;
|
||||
|
||||
frame_support::construct_runtime!(
|
||||
pub enum Test
|
||||
{
|
||||
System: frame_system,
|
||||
Sudo: sudo,
|
||||
Logger: logger,
|
||||
}
|
||||
);
|
||||
|
||||
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
|
||||
impl frame_system::Config for Test {
|
||||
type Block = Block;
|
||||
}
|
||||
|
||||
impl logger::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
pub type SudoCall = sudo::Call<Test>;
|
||||
pub type LoggerCall = logger::Call<Test>;
|
||||
|
||||
pub fn new_test_ext(root_key: u64) -> sp_io::TestExternalities {
|
||||
let mut t = frame_system::GenesisConfig::<Test>::default()
|
||||
.build_storage()
|
||||
.unwrap();
|
||||
sudo::GenesisConfig::<Test> {
|
||||
key: Some(root_key),
|
||||
}
|
||||
.assimilate_storage(&mut t)
|
||||
.unwrap();
|
||||
let mut ext: sp_io::TestExternalities = t.into();
|
||||
ext.execute_with(|| System::set_block_number(1));
|
||||
ext
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub fn new_bench_ext() -> sp_io::TestExternalities {
|
||||
frame_system::GenesisConfig::<Test>::default()
|
||||
.build_storage()
|
||||
.unwrap()
|
||||
.into()
|
||||
}
|
@ -1,217 +0,0 @@
|
||||
use super::*;
|
||||
use frame_support::{assert_noop, assert_ok, weights::Weight};
|
||||
use mock::{
|
||||
new_test_ext, Logger, LoggerCall, RuntimeCall, RuntimeEvent as TestEvent, RuntimeOrigin, Sudo,
|
||||
SudoCall, System, Test,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_setup_works() {
|
||||
new_test_ext(1).execute_with(|| {
|
||||
assert_eq!(Key::<Test>::get(), Some(1u64));
|
||||
assert!(Logger::i32_log().is_empty());
|
||||
assert!(Logger::account_log().is_empty());
|
||||
});
|
||||
}
|
||||
|
||||
#[docify::export]
|
||||
#[test]
|
||||
fn sudo_basics() {
|
||||
new_test_ext(1).execute_with(|| {
|
||||
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
|
||||
i: 42,
|
||||
weight: Weight::from_parts(1_000, 0),
|
||||
}));
|
||||
assert_ok!(Sudo::sudo(RuntimeOrigin::signed(1), call));
|
||||
assert_eq!(Logger::i32_log(), vec![42i32]);
|
||||
|
||||
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
|
||||
i: 42,
|
||||
weight: Weight::from_parts(1_000, 0),
|
||||
}));
|
||||
assert_noop!(
|
||||
Sudo::sudo(RuntimeOrigin::signed(2), call),
|
||||
Error::<Test>::RequireSudo
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sudo_emits_events_correctly() {
|
||||
new_test_ext(1).execute_with(|| {
|
||||
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
|
||||
i: 42,
|
||||
weight: Weight::from_parts(1, 0),
|
||||
}));
|
||||
assert_ok!(Sudo::sudo(RuntimeOrigin::signed(1), call));
|
||||
System::assert_has_event(TestEvent::Sudo(Event::Sudid {
|
||||
sudo_result: Ok(()),
|
||||
}));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sudo_unchecked_weight_basics() {
|
||||
new_test_ext(1).execute_with(|| {
|
||||
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
|
||||
i: 42,
|
||||
weight: Weight::from_parts(1_000, 0),
|
||||
}));
|
||||
assert_ok!(Sudo::sudo_unchecked_weight(
|
||||
RuntimeOrigin::signed(1),
|
||||
call,
|
||||
Weight::from_parts(1_000, 0)
|
||||
));
|
||||
assert_eq!(Logger::i32_log(), vec![42i32]);
|
||||
|
||||
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
|
||||
i: 42,
|
||||
weight: Weight::from_parts(1_000, 0),
|
||||
}));
|
||||
assert_noop!(
|
||||
Sudo::sudo_unchecked_weight(
|
||||
RuntimeOrigin::signed(2),
|
||||
call,
|
||||
Weight::from_parts(1_000, 0)
|
||||
),
|
||||
Error::<Test>::RequireSudo,
|
||||
);
|
||||
assert_eq!(Logger::i32_log(), vec![42i32]);
|
||||
|
||||
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
|
||||
i: 42,
|
||||
weight: Weight::from_parts(1, 0),
|
||||
}));
|
||||
let sudo_unchecked_weight_call = SudoCall::sudo_unchecked_weight {
|
||||
call,
|
||||
weight: Weight::from_parts(1_000, 0),
|
||||
};
|
||||
let info = sudo_unchecked_weight_call.get_dispatch_info();
|
||||
assert_eq!(info.weight, Weight::from_parts(1_000, 0));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sudo_unchecked_weight_emits_events_correctly() {
|
||||
new_test_ext(1).execute_with(|| {
|
||||
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
|
||||
i: 42,
|
||||
weight: Weight::from_parts(1, 0),
|
||||
}));
|
||||
assert_ok!(Sudo::sudo_unchecked_weight(
|
||||
RuntimeOrigin::signed(1),
|
||||
call,
|
||||
Weight::from_parts(1_000, 0)
|
||||
));
|
||||
System::assert_has_event(TestEvent::Sudo(Event::Sudid {
|
||||
sudo_result: Ok(()),
|
||||
}));
|
||||
})
|
||||
}
|
||||
|
||||
#[docify::export]
|
||||
#[test]
|
||||
fn set_key_basics() {
|
||||
new_test_ext(1).execute_with(|| {
|
||||
assert_ok!(Sudo::set_key(RuntimeOrigin::signed(1), 2));
|
||||
assert_eq!(Key::<Test>::get(), Some(2u64));
|
||||
});
|
||||
|
||||
new_test_ext(1).execute_with(|| {
|
||||
assert_noop!(
|
||||
Sudo::set_key(RuntimeOrigin::signed(2), 3),
|
||||
Error::<Test>::RequireSudo
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_key_emits_events_correctly() {
|
||||
new_test_ext(1).execute_with(|| {
|
||||
assert_ok!(Sudo::set_key(RuntimeOrigin::signed(1), 2));
|
||||
System::assert_has_event(TestEvent::Sudo(Event::KeyChanged {
|
||||
old: Some(1),
|
||||
new: 2,
|
||||
}));
|
||||
assert_ok!(Sudo::set_key(RuntimeOrigin::signed(2), 4));
|
||||
System::assert_has_event(TestEvent::Sudo(Event::KeyChanged {
|
||||
old: Some(2),
|
||||
new: 4,
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_key_works() {
|
||||
new_test_ext(1).execute_with(|| {
|
||||
assert_ok!(Sudo::remove_key(RuntimeOrigin::signed(1)));
|
||||
assert!(Key::<Test>::get().is_none());
|
||||
System::assert_has_event(TestEvent::Sudo(Event::KeyRemoved {}));
|
||||
|
||||
assert_noop!(
|
||||
Sudo::remove_key(RuntimeOrigin::signed(1)),
|
||||
Error::<Test>::RequireSudo
|
||||
);
|
||||
assert_noop!(
|
||||
Sudo::set_key(RuntimeOrigin::signed(1), 1),
|
||||
Error::<Test>::RequireSudo
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn using_root_origin_works() {
|
||||
new_test_ext(1).execute_with(|| {
|
||||
assert_ok!(Sudo::remove_key(RuntimeOrigin::root()));
|
||||
assert!(Key::<Test>::get().is_none());
|
||||
System::assert_has_event(TestEvent::Sudo(Event::KeyRemoved {}));
|
||||
|
||||
assert_ok!(Sudo::set_key(RuntimeOrigin::root(), 1));
|
||||
assert_eq!(Some(1), Key::<Test>::get());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sudo_as_basics() {
|
||||
new_test_ext(1).execute_with(|| {
|
||||
let call = Box::new(RuntimeCall::Logger(LoggerCall::privileged_i32_log {
|
||||
i: 42,
|
||||
weight: Weight::from_parts(1_000, 0),
|
||||
}));
|
||||
assert_ok!(Sudo::sudo_as(RuntimeOrigin::signed(1), 2, call));
|
||||
assert!(Logger::i32_log().is_empty());
|
||||
assert!(Logger::account_log().is_empty());
|
||||
|
||||
let call = Box::new(RuntimeCall::Logger(LoggerCall::non_privileged_log {
|
||||
i: 42,
|
||||
weight: Weight::from_parts(1, 0),
|
||||
}));
|
||||
assert_noop!(
|
||||
Sudo::sudo_as(RuntimeOrigin::signed(3), 2, call),
|
||||
Error::<Test>::RequireSudo
|
||||
);
|
||||
|
||||
let call = Box::new(RuntimeCall::Logger(LoggerCall::non_privileged_log {
|
||||
i: 42,
|
||||
weight: Weight::from_parts(1, 0),
|
||||
}));
|
||||
assert_ok!(Sudo::sudo_as(RuntimeOrigin::signed(1), 2, call));
|
||||
assert_eq!(Logger::i32_log(), vec![42i32]);
|
||||
assert_eq!(Logger::account_log(), vec![2]);
|
||||
});
|
||||
}
|
||||
|
||||
#[docify::export]
|
||||
#[test]
|
||||
fn sudo_as_emits_events_correctly() {
|
||||
new_test_ext(1).execute_with(|| {
|
||||
let call = Box::new(RuntimeCall::Logger(LoggerCall::non_privileged_log {
|
||||
i: 42,
|
||||
weight: Weight::from_parts(1, 0),
|
||||
}));
|
||||
assert_ok!(Sudo::sudo_as(RuntimeOrigin::signed(1), 2, call));
|
||||
System::assert_has_event(TestEvent::Sudo(Event::SudoAsDone {
|
||||
sudo_result: Ok(()),
|
||||
}));
|
||||
});
|
||||
}
|
@ -1,156 +0,0 @@
|
||||
// This file is part of Ghost Network.
|
||||
|
||||
// Ghost Network 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.
|
||||
|
||||
// Ghost Network 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 Ghost Network. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Autogenerated weights for `ghost_sudo`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
|
||||
//! DATE: 2025-07-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
|
||||
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/ghost
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=casper-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=ghost-sudo
|
||||
// --extrinsic=*
|
||||
// --wasm-execution=compiled
|
||||
// --heap-pages=4096
|
||||
// --header=./file_header.txt
|
||||
// --output=./runtime/casper/src/weights/ghost_sudo.rs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use frame_support::{
|
||||
traits::Get,
|
||||
weights::{Weight, constants::RocksDbWeight},
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// Weight functions needed for `pallet_sudo`.
|
||||
pub trait WeightInfo {
|
||||
fn set_key() -> Weight;
|
||||
fn sudo() -> Weight;
|
||||
fn sudo_as() -> Weight;
|
||||
fn remove_key() -> Weight;
|
||||
}
|
||||
|
||||
/// Weight functions for `ghost_sudo`.
|
||||
pub struct SubstrateWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
/// Storage: `GhostSudo::Key` (r:1 w:1)
|
||||
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
fn set_key() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `165`
|
||||
// Estimated: `1517`
|
||||
// Minimum execution time: 40_014_000 picoseconds.
|
||||
Weight::from_parts(40_856_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 1517))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostSudo::Key` (r:1 w:0)
|
||||
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
fn sudo() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `165`
|
||||
// Estimated: `1517`
|
||||
// Minimum execution time: 44_086_000 picoseconds.
|
||||
Weight::from_parts(45_920_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 1517))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
}
|
||||
/// Storage: `GhostSudo::Key` (r:1 w:0)
|
||||
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
fn sudo_as() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `165`
|
||||
// Estimated: `1517`
|
||||
// Minimum execution time: 44_106_000 picoseconds.
|
||||
Weight::from_parts(44_650_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 1517))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
}
|
||||
/// Storage: `GhostSudo::Key` (r:1 w:1)
|
||||
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
fn remove_key() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `165`
|
||||
// Estimated: `1517`
|
||||
// Minimum execution time: 36_416_000 picoseconds.
|
||||
Weight::from_parts(37_373_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 1517))
|
||||
.saturating_add(T::DbWeight::get().reads(1))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests.
|
||||
impl WeightInfo for () {
|
||||
/// Storage: `GhostSudo::Key` (r:1 w:1)
|
||||
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
fn set_key() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `165`
|
||||
// Estimated: `1517`
|
||||
// Minimum execution time: 40_014_000 picoseconds.
|
||||
Weight::from_parts(40_856_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 1517))
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
/// Storage: `GhostSudo::Key` (r:1 w:0)
|
||||
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
fn sudo() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `165`
|
||||
// Estimated: `1517`
|
||||
// Minimum execution time: 44_086_000 picoseconds.
|
||||
Weight::from_parts(45_920_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 1517))
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
}
|
||||
/// Storage: `GhostSudo::Key` (r:1 w:0)
|
||||
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
fn sudo_as() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `165`
|
||||
// Estimated: `1517`
|
||||
// Minimum execution time: 44_106_000 picoseconds.
|
||||
Weight::from_parts(44_650_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 1517))
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
}
|
||||
/// Storage: `GhostSudo::Key` (r:1 w:1)
|
||||
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
|
||||
fn remove_key() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `165`
|
||||
// Estimated: `1517`
|
||||
// Minimum execution time: 36_416_000 picoseconds.
|
||||
Weight::from_parts(37_373_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 1517))
|
||||
.saturating_add(RocksDbWeight::get().reads(1))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
}
|
6
pallets/traits/Cargo.toml
Normal file → Executable file
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ghost-traits"
|
||||
version = "0.3.23"
|
||||
version = "0.3.19"
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
@ -14,6 +14,6 @@ sp-runtime = { workspace = true }
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"frame-support/std",
|
||||
"sp-runtime/std",
|
||||
"frame-support/std",
|
||||
"sp-runtime/std",
|
||||
]
|
||||
|
0
pallets/traits/src/lib.rs
Normal file → Executable file
26
pallets/traits/src/networks.rs
Normal file → Executable file
@ -1,7 +1,10 @@
|
||||
use frame_support::{pallet_prelude::*, storage::PrefixIterator};
|
||||
use frame_support::{
|
||||
pallet_prelude::*,
|
||||
storage::PrefixIterator,
|
||||
};
|
||||
use sp_runtime::{
|
||||
traits::{AtLeast32BitUnsigned, Member},
|
||||
DispatchResult,
|
||||
traits::{AtLeast32BitUnsigned, Member},
|
||||
};
|
||||
|
||||
pub trait NetworkDataBasicHandler {
|
||||
@ -18,26 +21,9 @@ pub trait NetworkDataBasicHandler {
|
||||
pub trait NetworkDataInspectHandler<Network>: NetworkDataBasicHandler {
|
||||
fn get(n: &Self::NetworkId) -> Option<Network>;
|
||||
fn iter() -> PrefixIterator<(Self::NetworkId, Network)>;
|
||||
fn is_nullification_period() -> bool;
|
||||
}
|
||||
|
||||
pub trait NetworkDataMutateHandler<Network, Balance>: NetworkDataInspectHandler<Network> {
|
||||
pub trait NetworkDataMutateHandler<Network>: NetworkDataInspectHandler<Network> {
|
||||
fn register(chain_id: Self::NetworkId, network: Network) -> DispatchResult;
|
||||
fn remove(chain_id: Self::NetworkId) -> DispatchResult;
|
||||
|
||||
fn increase_gatekeeper_amount(
|
||||
chain_id: &Self::NetworkId,
|
||||
amount: &Balance,
|
||||
) -> Result<Balance, ()>;
|
||||
fn decrease_gatekeeper_amount(
|
||||
chain_id: &Self::NetworkId,
|
||||
amount: &Balance,
|
||||
) -> Result<Balance, ()>;
|
||||
|
||||
fn accumulate_outgoing_imbalance(amount: &Balance) -> Result<Balance, ()>;
|
||||
fn accumulate_incoming_imbalance(amount: &Balance) -> Result<Balance, ()>;
|
||||
|
||||
fn accumulate_commission(commission: &Balance) -> Result<Balance, ()>;
|
||||
fn nullify_commission();
|
||||
fn trigger_nullification();
|
||||
}
|
||||
|
0
rpc/Cargo.toml
Normal file → Executable file
56
rpc/src/lib.rs
Normal file → Executable file
@ -1,15 +1,17 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use babe_primitives::BabeApi;
|
||||
use block_builder_api::BlockBuilder;
|
||||
use consensus_common::SelectChain;
|
||||
use grandpa::FinalityProofProvider;
|
||||
use jsonrpsee::RpcModule;
|
||||
use primitives::{AccountId, Balance, Block, BlockNumber, Hash, Nonce};
|
||||
use primitives::{
|
||||
AccountId, Balance, Block, BlockNumber, Hash, Nonce,
|
||||
};
|
||||
use sc_client_api::AuxStore;
|
||||
use grandpa::FinalityProofProvider;
|
||||
pub use sc_rpc::{DenyUnsafe, SubscriptionTaskExecutor};
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use block_builder_api::BlockBuilder;
|
||||
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
|
||||
use consensus_common::SelectChain;
|
||||
use babe_primitives::BabeApi;
|
||||
use sp_keystore::KeystorePtr;
|
||||
use tx_pool_api::TransactionPool;
|
||||
|
||||
@ -59,16 +61,7 @@ pub struct FullDeps<C, P, SC, B> {
|
||||
}
|
||||
|
||||
pub fn create_full_rpc<C, P, SC, B>(
|
||||
FullDeps {
|
||||
client,
|
||||
pool,
|
||||
select_chain,
|
||||
chain_spec,
|
||||
deny_unsafe,
|
||||
babe,
|
||||
grandpa,
|
||||
backend,
|
||||
}: FullDeps<C, P, SC, B>,
|
||||
FullDeps { client, pool, select_chain, chain_spec, deny_unsafe, babe, grandpa, backend } : FullDeps<C, P, SC, B>,
|
||||
) -> Result<RpcExtension, Box<dyn std::error::Error + Send + Sync>>
|
||||
where
|
||||
C: ProvideRuntimeApi<Block>
|
||||
@ -87,19 +80,20 @@ where
|
||||
B: sc_client_api::Backend<Block> + Send + Sync + 'static,
|
||||
B::State: sc_client_api::StateBackend<sp_runtime::traits::HashingFor<Block>>,
|
||||
{
|
||||
use babe_rpc::{Babe, BabeApiServer};
|
||||
use frame_rpc_system::{System, SystemApiServer};
|
||||
use pallet_transaction_payment_rpc::{
|
||||
TransactionPayment, TransactionPaymentApiServer,
|
||||
};
|
||||
use babe_rpc::{Babe, BabeApiServer};
|
||||
use grandpa_rpc::{Grandpa, GrandpaApiServer};
|
||||
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer};
|
||||
use sc_rpc_spec_v2::chain_spec::{ChainSpec, ChainSpecApiServer};
|
||||
use sc_sync_state_rpc::{SyncState, SyncStateApiServer};
|
||||
use substrate_state_trie_migration_rpc::{StateMigration, StateMigrationApiServer};
|
||||
use substrate_state_trie_migration_rpc::{
|
||||
StateMigration, StateMigrationApiServer,
|
||||
};
|
||||
|
||||
let mut io = RpcModule::new(());
|
||||
let BabeDeps {
|
||||
babe_worker_handle,
|
||||
keystore,
|
||||
} = babe;
|
||||
let BabeDeps { babe_worker_handle, keystore } = babe;
|
||||
let GrandpaDeps {
|
||||
shared_voter_state,
|
||||
shared_authority_set,
|
||||
@ -109,13 +103,10 @@ where
|
||||
} = grandpa;
|
||||
|
||||
let chain_name = chain_spec.name().to_string();
|
||||
let genesis_hash = client
|
||||
.hash(0)
|
||||
.ok()
|
||||
.flatten()
|
||||
.expect("Genesis block exists; qed;");
|
||||
let genesis_hash = client.hash(0).ok().flatten().expect("Genesis block exists; qed;");
|
||||
let properties = chain_spec.properties();
|
||||
|
||||
|
||||
io.merge(ChainSpec::new(chain_name, genesis_hash, properties).into_rpc())?;
|
||||
io.merge(StateMigration::new(client.clone(), backend.clone(), deny_unsafe).into_rpc())?;
|
||||
io.merge(System::new(client.clone(), pool.clone(), deny_unsafe).into_rpc())?;
|
||||
@ -128,8 +119,7 @@ where
|
||||
keystore,
|
||||
select_chain,
|
||||
deny_unsafe,
|
||||
)
|
||||
.into_rpc(),
|
||||
).into_rpc()
|
||||
)?;
|
||||
|
||||
io.merge(
|
||||
@ -139,8 +129,7 @@ where
|
||||
shared_voter_state,
|
||||
justification_stream,
|
||||
finality_provider,
|
||||
)
|
||||
.into_rpc(),
|
||||
).into_rpc(),
|
||||
)?;
|
||||
|
||||
io.merge(
|
||||
@ -148,9 +137,8 @@ where
|
||||
chain_spec,
|
||||
client.clone(),
|
||||
shared_authority_set,
|
||||
babe_worker_handle,
|
||||
)?
|
||||
.into_rpc(),
|
||||
babe_worker_handle
|
||||
)?.into_rpc(),
|
||||
)?;
|
||||
|
||||
Ok(io)
|
||||
|