Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subalfred Book #111

Merged
merged 12 commits into from
Aug 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Pages

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
deploy:
name: Deploy pages
runs-on: ubuntu-latest
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
steps:
- name: Fetch latest code
uses: actions/checkout@v3
- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
with:
mdbook-version: "latest"
- name: Build pages
run: mdbook build doc
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: ${{ github.ref == 'refs/heads/main' }}
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: doc/book
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
# Package Manager
## Cargo
target
## mdBook
book
index.html

# Test data
test-data
79 changes: 19 additions & 60 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,66 +18,25 @@
</div>

## Philosophies
- **Lighting Fast**
- **Less Dependencies**
- **No `unsafe {}`/`.unwrap()`**
- **Easy to Use**
- **Strive for Excellence**

## Usage
```
subalfred 0.9.0-1bc3414-x86_64-unknown-linux-gnu
Xavier Lau <xavier@inv.cafe>
Your Substrate Alfred

USAGE:
subalfred [OPTIONS] <SUBCOMMAND>

OPTIONS:
-h, --help Print help information
--log <TARGET=LEVEL,*> Set a custom logging filter. Also, work with the `RUST_LOG` environment variable [default: info]
-V, --version Print version information

SUBCOMMANDS:
check Some checking tools are pretty useful for runtime development
export-state Export the chain state
hash Hash the hex with the specific hasher
help Print this message or the help of the given subcommand(s)
key Convert the public key/SS58 address from SS58 address/public key
storage-key Calculate the storage key for the storage prefix/item
workspace Workspace manager
- ***Lighting fast***
- ***Less dependencies***
- ***No `unsafe {}`, `.unwrap()`***
- ***Easy to use***
- ***Strive for excellence***

## Documentations
```sh
# Use the `--help` flag to get more information.
subalfred --help
# Each subcommand also provides its own `--help`.
subalfred check --help
subalfred check runtime --help
```

## Components
### CLI
- [check](src/bin/subalfred/command/check)
- [runtime](src/bin/subalfred/command/check/runtime)
- [std-feature](src/bin/subalfred/command/check/std-feature)
- [workspace](src/bin/subalfred/command/workspace)
- [update](src/bin/subalfred/command/update)
- [export-state](src/bin/subalfred/command/export-state.rs)
- [hash](src/bin/subalfred/command/hash.rs)
- [key](src/bin/subalfred/command/key.rs)
- [storage-key](src/bin/subalfred/command/storage-key.rs)

### Subalfred Core Libraries
- [cargo](src/subalfred/core/cargo)
- [check](src/subalfred/core/check)
- [error](src/subalfred/core/error)
- [http](src/subalfred/core/http)
- [jsonrpc](src/subalfred/core/jsonrpc)
- [key](src/subalfred/core/key)
- [node](src/subalfred/core/node)
- [ss58](src/subalfred/core/ss58)
- [substrate-client](src/subalfred/core/substrate-client)
- [system](src/subalfred/core/system)
- [`subalfred.hack.ink`](https://subalfred.hack.ink)
- [`hack-ink.github.io (backup)`](https://hack-ink.github.io)

### Substrate Minimal Libraries
- [subcryptor](substrate-minimal/subcryptor)
- [subgrandpa](substrate-minimal/subgrandpa)
- [subhasher](substrate-minimal/subhasher)
- [submetadatan](substrate-minimal/submetadatan)
- [subrpcer](substrate-minimal/subrpcer)
- [impl](substrate-minimal/subrpcer/impl)
- [substorager](substrate-minimal/substorager)
- [subversioner](substrate-minimal/subversioner)
## Contribution
- If you have a question or request a new feature, [start a discussion](https://github.com/hack-ink/subalfred/discussions/new).
- If you encounter any bugs, [report an issue](https://github.com/hack-ink/subalfred/issues/new).
- Otherwise, PRs are always welcome!
6 changes: 6 additions & 0 deletions doc/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[book]
authors = ["Xavier Lau"]
language = "en"
multilingual = false
src = "src"
title = "Subalfred Documentation"
20 changes: 20 additions & 0 deletions doc/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Summary
[Introduction](../../README.md)

# User Guide
- [Installation](user/installation.md)
- [Command Line Tool](user/cli/README.md)
- [check](user/cli/check.md)
- [convert](user/cli/convert.md)
- [get](user/cli/get.md)
- [hash](user/cli/hash.md)
- [key](user/cli/key.md)
- [state](user/cli/state.md)
- [storage-key](user/cli/storage-key.md)
- [workspace](user/cli/workspace.md)

# Reference Guide
- [todo]()
- [todo]()
- [todo]()
- [todo]()
14 changes: 14 additions & 0 deletions doc/src/user/cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Command Line Tool
The `subalfred` command-line tool is used to create and build books.
After you have [installed](../installation.md) `subalfred`, you can run the `subalfred help` command in your terminal to view the available commands.

This following sections provide in-depth information on the different commands available.

* [`subalfred check`](check.md)
* [`subalfred convert`](convert.md)
* [`subalfred get`](get.md)
* [`subalfred hash`](hash.md)
* [`subalfred key`](key.md)
* [`subalfred state`](state.md)
* [`subalfred storage-key`](storage-key.md)
* [`subalfred workspace`](workspace.md)
131 changes: 131 additions & 0 deletions doc/src/user/cli/check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# The Check Command
Currently, there are two subcommands available.

## Runtime
As the name says, the checks are on the runtime level.

There are three shared options:
- `--chain <NAME>`The chain name, which will supply to the executable.
- `--executable <PATH>` The executable path.
- `--live <URI>` The live chain's RPC HTTP endpoint.

And there are two properties to check, `storage` and `version`.

### Examples
For convenience, I use the [Pangolin Network](https://github.com/darwinia-network/darwinia-common) to demonstrate.
- `pangolin-dev` is the dev chain spec, which means its genesis is built from the latest code.
If you are on Polkadot, then use `polkadot-dev`.
- `./drml` is the path to my local pangolin node executable.
- `https://pangolin-rpc.darwinia.network` is the Pangoro live chain's RPC HTTP endpoint. Note, I use the Pangoro here. Just because I'm doing a demonstration. Compare with two different chains' runtime storage/version will get a lot of output.

#### Check Runtime Storage
```sh
subalfred check runtime --chain pangolin-dev --executable ./drml --live https://pangoro-rpc.darwinia.network --property storage
```
```diff
+ Pallet: "Bounties"
- Pallet: "BridgePangolinGrandpa"
- Pallet: "BridgePangolinMessages"
+ Pallet: "BridgePangolinParachainMessages"
+ Pallet: "BridgePangoroGrandpa"
+ Pallet: "BridgePangoroMessages"
+ Pallet: "BridgeRococoGrandpa"
+ Pallet: "BridgeRococoParachains"
+ Pallet: "Council"
+ Pallet: "DarwiniaEthereumRelay"
+ Pallet: "Democracy"
+ Pallet: "EcdsaRelayAuthority"
+ Pallet: "EthereumBacking"
+ Pallet: "HeaderMmr"
+ Pallet: "Identity"
+ Pallet: "Instance1DarwiniaRelayerGame"
+ Pallet: "KtonTreasury"
+ Pallet: "Multisig"
- Pallet: "PangolinFeeMarket"
+ Pallet: "PangolinParachainFeeMarket"
+ Pallet: "PangoroFeeMarket"
+ Pallet: "PhragmenElection"
+ Pallet: "Proxy"
+ Pallet: "Recovery"
+ Pallet: "Society"
- Pallet: "Substrate2SubstrateBacking"
+ Pallet: "Substrate2SubstrateIssuing"
+ Pallet: "TechnicalCommittee"
+ Pallet: "TechnicalMembership"
+ Pallet: "Tips"
+ Pallet: "ToPangolinParachainBacking"
+ Pallet: "Vesting"

Pallet ElectionProviderMultiPhase
+ Entry: StorageEntryMetadata { name: "SignedSubmissionsMap", modifier: Default, ty: Map { hashers: [Twox64Concat], key: UntrackedSymbol { id: 4, marker: PhantomData }, value: UntrackedSymbol { id: 227, marker: PhantomData } }, default: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], docs: [" Unchecked, signed solutions.", "", " Together with `SubmissionIndices`, this stores a bounded set of `SignedSubmissions` while", " allowing us to keep only a single one in memory at a time.", "", " Twox note: the key of the map is an auto-incrementing index which users cannot inspect or", " affect; we shouldn't need a cryptographically secure hasher."] }
- Entry: StorageEntryMetadata { name: "SignedSubmissionsMap", modifier: Default, ty: Map { hashers: [Twox64Concat], key: UntrackedSymbol { id: 4, marker: PhantomData }, value: UntrackedSymbol { id: 186, marker: PhantomData } }, default: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], docs: [" Unchecked, signed solutions.", "", " Together with `SubmissionIndices`, this stores a bounded set of `SignedSubmissions` while", " allowing us to keep only a single one in memory at a time.", "", " Twox note: the key of the map is an auto-incrementing index which users cannot inspect or", " affect; we shouldn't need a cryptographically secure hasher."] }

Pallet Scheduler
+ Entry: StorageEntryMetadata { name: "Agenda", modifier: Default, ty: Map { hashers: [Twox64Concat], key: UntrackedSymbol { id: 4, marker: PhantomData }, value: UntrackedSymbol { id: 609, marker: PhantomData } }, default: [0], docs: [" Items to be executed, indexed by the block number that they should be executed on."] }
- Entry: StorageEntryMetadata { name: "Agenda", modifier: Default, ty: Map { hashers: [Twox64Concat], key: UntrackedSymbol { id: 4, marker: PhantomData }, value: UntrackedSymbol { id: 378, marker: PhantomData } }, default: [0], docs: [" Items to be executed, indexed by the block number that they should be executed on."] }

Pallet Session
+ Entry: StorageEntryMetadata { name: "NextKeys", modifier: Optional, ty: Map { hashers: [Twox64Concat], key: UntrackedSymbol { id: 0, marker: PhantomData }, value: UntrackedSymbol { id: 347, marker: PhantomData } }, default: [0], docs: [" The next session keys for a validator."] }
- Entry: StorageEntryMetadata { name: "NextKeys", modifier: Optional, ty: Map { hashers: [Twox64Concat], key: UntrackedSymbol { id: 0, marker: PhantomData }, value: UntrackedSymbol { id: 282, marker: PhantomData } }, default: [0], docs: [" The next session keys for a validator."] }
+ Entry: StorageEntryMetadata { name: "QueuedKeys", modifier: Default, ty: Plain(UntrackedSymbol { id: 345, marker: PhantomData }), default: [0], docs: [" The queued keys for the next session. When the next session begins, these keys", " will be used to determine the validator's session keys."] }
- Entry: StorageEntryMetadata { name: "QueuedKeys", modifier: Default, ty: Plain(UntrackedSymbol { id: 280, marker: PhantomData }), default: [0], docs: [" The queued keys for the next session. When the next session begins, these keys", " will be used to determine the validator's session keys."] }

Pallet System
+ Entry: StorageEntryMetadata { name: "Events", modifier: Default, ty: Plain(UntrackedSymbol { id: 15, marker: PhantomData }), default: [0], docs: [" Events deposited for the current block.", "", " NOTE: This storage item is explicitly unbounded since it is never intended to be read", " from within the runtime."] }
- Entry: StorageEntryMetadata { name: "Events", modifier: Default, ty: Plain(UntrackedSymbol { id: 15, marker: PhantomData }), default: [0], docs: [" Events deposited for the current block.", "", " NOTE: This storage item is explicitly unbounded since it is never intended to be read", " from within the runtime."] }
```

#### Check Runtime Version
```sh
subalfred check runtime --chain pangolin-dev --executable ./drml --live https://pangoro-rpc.darwinia.network --property version
```
```diff
RuntimeVersion {
- spec_name: "Pangoro",
+ spec_name: "Pangolin",
- impl_name: "Pangoro",
+ impl_name: "Pangolin",
authoring_version: 0,
spec_version: 29020,
impl_version: 0,
transaction_version: 0,
}
```

## STD Feature
As we know Substrate have two runtime ENVs, native and WASM.

If a runtime dependency is not pure no-std, we need to write:
```toml
[features]
std = ["xxx/std"]

[dependencies]
xxx = { version = "0.1.0", default-features = false }
```

Sometimes, we might forget to write add the `xxx/std`.
Recently, I found someone have the same [requirement](https://github.com/paritytech/substrate/pull/11715).
So, I decide to make this public.

### Example
```sh
git clone https://github.com/paritytech/frontier /tmp/paritytech
subalfred check std-feature --manifest-path /tmp/paritytech/frontier/Cargo.toml
```
```
`fp-evm`'s std feature was disabled in `/tmp/paritytech/frontier/primitives/ethereum/Cargo.toml`
`ed25519-dalek`'s std feature was disabled in `/tmp/paritytech/frontier/frame/evm/precompile/ed25519/Cargo.toml`
`bn`'s std feature was disabled in `/tmp/paritytech/frontier/frame/evm/precompile/bn128/Cargo.toml`
`curve25519-dalek`'s std feature was disabled in `/tmp/paritytech/frontier/frame/evm/precompile/curve25519/Cargo.toml`
`frame-benchmarking`'s std feature was disabled in `/tmp/paritytech/frontier/template/runtime/Cargo.toml`
`frame-system-benchmarking`'s std feature was disabled in `/tmp/paritytech/frontier/template/runtime/Cargo.toml`
```

---

## CI
Moreover, we can add the checks into your project CI.

I've already add these to the [Darwinia CI](https://github.com/darwinia-network/darwinia/blob/v0.12.3/.github/workflows/ci.yml).
And here is a real world [example](https://github.com/darwinia-network/darwinia/pull/940#issuecomment-1226917895).
1 change: 1 addition & 0 deletions doc/src/user/cli/convert.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# convert
42 changes: 42 additions & 0 deletions doc/src/user/cli/get.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# The Get Command
Currently, there only one subcommand available.

## Runtime Upgrade Block
The origin question is from [stackexchange](https://substrate.stackexchange.com/questions/3861/how-do-you-tell-which-block-number-the-last-runtime-upgrade-happened-on-a-chain).

Yep, I think that is an interesting question.
So, I implemented this method.

It uses dichotomy algorithm, the whole process takes <img src="https://latex.codecogs.com/svg.image?log_2&space;BlockHeight" title="log_2 BlockHeight"/> times requests.

### Example
```sh
subalfred get runtime-upgrade-block 9100 --uri wss://polkadot.api.onfinality.io/public-ws -lsubalfred::core::node
```
```log
2022-08-27T13:58:07.684200Z TRACE subalfred::core::node: (0, 11788056) -> 9050
2022-08-27T13:58:09.469688Z TRACE subalfred::core::node: (5894028, 11788056) -> 9151
2022-08-27T13:58:10.874493Z TRACE subalfred::core::node: (5894028, 8841042) -> 9110
2022-08-27T13:58:11.852626Z TRACE subalfred::core::node: (5894028, 7367535) -> 9080
2022-08-27T13:58:12.916960Z TRACE subalfred::core::node: (6630782, 7367535) -> 9090
2022-08-27T13:58:13.126836Z TRACE subalfred::core::node: (6999158, 7367535) -> 9090
2022-08-27T13:58:14.591213Z TRACE subalfred::core::node: (7183346, 7367535) -> 9110
2022-08-27T13:58:14.800144Z TRACE subalfred::core::node: (7183346, 7275440) -> 9110
2022-08-27T13:58:15.921005Z TRACE subalfred::core::node: (7183346, 7229393) -> 9090
2022-08-27T13:58:18.036717Z TRACE subalfred::core::node: (7206370, 7229393) -> 9090
2022-08-27T13:58:18.993673Z TRACE subalfred::core::node: (7217881, 7229393) -> 9100
2022-08-27T13:58:19.208425Z TRACE subalfred::core::node: (7217881, 7223637) -> 9100
2022-08-27T13:58:19.415621Z TRACE subalfred::core::node: (7217881, 7220759) -> 9100
2022-08-27T13:58:19.624220Z TRACE subalfred::core::node: (7217881, 7219320) -> 9100
2022-08-27T13:58:19.828821Z TRACE subalfred::core::node: (7217881, 7218601) -> 9100
2022-08-27T13:58:20.035127Z TRACE subalfred::core::node: (7217881, 7218241) -> 9100
2022-08-27T13:58:20.240336Z TRACE subalfred::core::node: (7217881, 7218061) -> 9100
2022-08-27T13:58:20.444889Z TRACE subalfred::core::node: (7217881, 7217971) -> 9100
2022-08-27T13:58:21.594894Z TRACE subalfred::core::node: (7217881, 7217926) -> 9090
2022-08-27T13:58:24.625042Z TRACE subalfred::core::node: (7217904, 7217926) -> 9100
2022-08-27T13:58:24.824345Z TRACE subalfred::core::node: (7217904, 7217915) -> 9100
2022-08-27T13:58:25.030852Z TRACE subalfred::core::node: (7217904, 7217910) -> 9100
2022-08-27T13:58:26.058492Z TRACE subalfred::core::node: (7217904, 7217907) -> 9090
2022-08-27T13:58:26.275470Z TRACE subalfred::core::node: (7217906, 7217907) -> 9090
7217907 0x8f10de9e6dcf190dccc90f464a8aa4448c9b080746d8e905bb0e4841fef80fdd
```
1 change: 1 addition & 0 deletions doc/src/user/cli/hash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# hash
1 change: 1 addition & 0 deletions doc/src/user/cli/key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# key
1 change: 1 addition & 0 deletions doc/src/user/cli/state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# state
1 change: 1 addition & 0 deletions doc/src/user/cli/storage-key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# storage-key
1 change: 1 addition & 0 deletions doc/src/user/cli/workspace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# workspace
Loading