Subalfred

An All-In-One Substrate Development Toolbox.

License Checks Docs Release GitHub tag (latest by date) GitHub code lines GitHub last commit

Subalfred

Philosophy

  • Blazing fast
  • Lightweight
  • Zero panic
  • Ergonomics
  • Pursue excellence

Documentation

# Get more information by using the `--help` flag.
subalfred --help
# Each subcommand also has its own `--help`.
subalfred check --help
subalfred check runtime --help

Contribution

  • If you have any questions or would like to request a new feature, start a discussion.
  • If you come across any bugs, report an issue.
  • Lastly, pull requests are always welcome!

Installation

There are multiple ways to install the subalfred CLI tool. Choose any one of the methods below that best suit your needs.

Pre-built Binaries

  1. Download it from the GitHub Releases page.
  2. Uncompress the downloaded file.
  3. Rename it to whatever you like. (optional)
  4. Give the execution privilege to it.

The compressing algorithm is zstd. For some systems, you might need to install zstd first. For Windows users, you would like to rename the extracted content name to subalfred.exe.

Use subalfred-aarch64-apple-darwin.zst as an example.

  • One line command:
    curl -L https://github.com/hack-ink/subalfred/releases/latest/download/subalfred-aarch64-apple-darwin.zst | zstd -o subalfred -d && chmod u+x subalfred
    
  • Multi-lines command:
    curl -LO https://github.com/hack-ink/subalfred/releases/latest/download/subalfred-aarch64-apple-darwin.zst
    zstd -o subalfred -d subalfred-aarch64-apple-darwin.zst
    chmod u+x subalfred
    

Available pre-built binaries list.

  • subalfred-aarch64-apple-darwin.zst
  • subalfred-x86_64-apple-darwin.zst
  • subalfred-x86_64-pc-windows-msvc.zst
  • subalfred-x86_64-unknown-linux-gnu.zst

Build from Source

To build subalfred from source, you will first need to install Rust. Once you have installed Rust, the following command can be used to build and install subalfred:

  • Build from crates.io:
    cargo install subalfred
    
  • Build from the latest main branch code:
    cargo install subalfred --git https://github.com/hack-ink/subalfred
    

This will automatically download subalfred from crates.io/github.com, build it, and install it in Cargo's global binary directory (~/.cargo/bin/ by default).

The version published to crates.io will ever so slightly be behind the version hosted on github.com. If you need the latest version you can build the git version of subalfred yourself. Cargo makes this super easy!

To uninstall, run the command cargo uninstall subalfred.

Command subalfred

Your Substrate Alfred.

Usage: subalfred [OPTIONS] <COMMAND>

Commands:
  check
          Substrate development checkers
  convert
          Data style converters
  get
          Substrate-link node getter
  hash
          Hash the hex with the specific hasher(hash algorithm)
  key
          Calculate the public key/SS58 address of the SS58 address/public key
  rpc
          Send a RPC request to the node's HTTP RPC endpoint.
  state
          A set of tools to process Substrate-like chain state
  storage-key
          Calculate the storage key of the storage item
  track-updates
          Track the updates
  workspace
          Workspace manager
  help
          Print this message or the help of the given subcommand(s)

Options:
  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

  -V, --version
          Print version information

Command check

Substrate development checkers

Usage: subalfred check [OPTIONS] <COMMAND>

Commands:
  runtime
          Compare the local node's runtime version with the live's one
  features
          Check if the crates' features are enabled correctly
  help
          Print this message or the help of the given subcommand(s)

Options:
  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Command check runtime

Compare the local node's runtime version with the live's one

Usage: subalfred check runtime [OPTIONS] --executable <PATH> --chain <CHAIN> --live <URI> --property <PROPERTY>

Options:
      --executable <PATH>
          Node executable's path

      --chain <CHAIN>
          Pass this name to `--chain` to launch the local chain

      --live <URI>
          Live chain's HTTP RPC endpoint

      --property <PROPERTY>
          Target property

          [possible values: storage, version]

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

We assume node-template's live chain is Polkadot here.

ENV preparation

git clone https://github.com/substrate-developer-hub/substrate-node-template.git /tmp/subalfred-example/substrate-node-template
cd /tmp/subalfred-example/substrate-node-template
cargo build

Command check runtime --property storage

subalfred check runtime --chain dev --executable target/debug/node-template --live https://rpc.polkadot.io --property storage
- Pallet: "Auctions"
+ Pallet: "Aura"
- Pallet: "Authorship"
- Pallet: "Babe"
- Pallet: "Bounties"
- Pallet: "ChildBounties"
- Pallet: "Claims"
- Pallet: "Configuration"
- Pallet: "Council"
- Pallet: "Crowdloan"
- Pallet: "Democracy"
- Pallet: "Dmp"
- Pallet: "ElectionProviderMultiPhase"
- Pallet: "Hrmp"
- Pallet: "Identity"
- Pallet: "ImOnline"
- Pallet: "Indices"
- Pallet: "Initializer"
- Pallet: "Multisig"
- Pallet: "NominationPools"
- Pallet: "Offences"
- Pallet: "ParaInclusion"
- Pallet: "ParaInherent"
- Pallet: "ParaScheduler"
- Pallet: "ParaSessionInfo"
- Pallet: "Paras"
- Pallet: "ParasDisputes"
- Pallet: "ParasShared"
- Pallet: "PhragmenElection"
- Pallet: "Preimage"
- Pallet: "Proxy"
+ Pallet: "RandomnessCollectiveFlip"
- Pallet: "Registrar"
- Pallet: "Scheduler"
- Pallet: "Session"
- Pallet: "Slots"
- Pallet: "Staking"
+ Pallet: "Sudo"
- Pallet: "TechnicalCommittee"
- Pallet: "TechnicalMembership"
+ Pallet: "TemplateModule"
- Pallet: "Tips"
- Pallet: "Treasury"
- Pallet: "Ump"
- Pallet: "Vesting"
- Pallet: "VoterList"
- Pallet: "XcmPallet"

Pallet Balances
+ Entry: StorageEntryMetadata { name: "Locks", modifier: Default, ty: Map { hashers: [Blake2_128Concat], key: UntrackedSymbol { id: 0, marker: PhantomData }, value: UntrackedSymbol { id: 94, marker: PhantomData } }, default: [0], docs: [" Any liquidity locks on some account balances.", " NOTE: Should only be accessed when setting, changing and freeing a lock."] }
- Entry: StorageEntryMetadata { name: "Locks", modifier: Default, ty: Map { hashers: [Blake2_128Concat], key: UntrackedSymbol { id: 0, marker: PhantomData }, value: UntrackedSymbol { id: 467, marker: PhantomData } }, default: [0], docs: [" Any liquidity locks on some account balances.", " NOTE: Should only be accessed when setting, changing and freeing a lock."] }
+ Entry: StorageEntryMetadata { name: "Reserves", modifier: Default, ty: Map { hashers: [Blake2_128Concat], key: UntrackedSymbol { id: 0, marker: PhantomData }, value: UntrackedSymbol { id: 98, marker: PhantomData } }, default: [0], docs: [" Named reserves on some account balances."] }
- Entry: StorageEntryMetadata { name: "Reserves", modifier: Default, ty: Map { hashers: [Blake2_128Concat], key: UntrackedSymbol { id: 0, marker: PhantomData }, value: UntrackedSymbol { id: 471, marker: PhantomData } }, default: [0], docs: [" Named reserves on some account balances."] }

Pallet Grandpa
+ Entry: StorageEntryMetadata { name: "PendingChange", modifier: Optional, ty: Plain(UntrackedSymbol { id: 77, marker: PhantomData }), default: [0], docs: [" Pending change: (signaled at, scheduled change)."] }
- Entry: StorageEntryMetadata { name: "PendingChange", modifier: Optional, ty: Plain(UntrackedSymbol { id: 513, marker: PhantomData }), default: [0], docs: [" Pending change: (signaled at, scheduled change)."] }

Pallet System
+ Entry: StorageEntryMetadata { name: "BlockWeight", modifier: Default, ty: Plain(UntrackedSymbol { id: 7, 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], docs: [" The current weight for the block."] }
- Entry: StorageEntryMetadata { name: "BlockWeight", modifier: Default, ty: Plain(UntrackedSymbol { id: 7, 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], docs: [" The current weight for the block."] }
+ Entry: StorageEntryMetadata { name: "Events", modifier: Default, ty: Plain(UntrackedSymbol { id: 16, marker: PhantomData }), default: [0], docs: [" Events deposited for the current block.", "", " NOTE: The item is unbound and should therefore never be read on chain.", " It could otherwise inflate the PoV size of a block.", "", " Events have a large in-memory size. Box the events to not go out-of-memory", " just in case someone still reads them from within the runtime."] }
- Entry: StorageEntryMetadata { name: "Events", modifier: Default, ty: Plain(UntrackedSymbol { id: 16, marker: PhantomData }), default: [0], docs: [" Events deposited for the current block.", "", " NOTE: The item is unbound and should therefore never be read on chain.", " It could otherwise inflate the PoV size of a block.", "", " Events have a large in-memory size. Box the events to not go out-of-memory", " just in case someone still reads them from within the runtime."] }

Command check runtime --property version

subalfred check runtime --chain dev --executable target/debug/substrate-node-template --live https://rpc.polkadot.io --property version
RuntimeVersion {
-   spec_name: "polkadot",
+   spec_name: "node-template",
-   impl_name: "parity-polkadot",
+   impl_name: "node-template",
-   authoring_version: 0,
+   authoring_version: 1,
-   spec_version: 9291,
+   spec_version: 100,
-   impl_version: 0,
+   impl_version: 1,
-   transaction_version: 14,
+   transaction_version: 1,
-   state_version: 0,
+   state_version: 1,
}

Features

Check if the crates' features are enabled correctly

Usage: subalfred check features [OPTIONS] [PATH]

Arguments:
  [PATH]
          Root `Cargo.toml`'s path.

          If `Cargo.toml` wasn't given, Subalfred will search it under the given path.

          [default: ./Cargo.toml]

Options:
  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG` simultaneously, this will append `RUST_LOG`'s
          value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Episode 1

As we know Substrate has two runtime ENVs, native and WASM. If a runtime dependency is not pure no-std, we need to write:

[features]
std = ["pallet/std"]

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

Sometimes, we might forget to write add the pallet/std. Recently, I found someone have the same requirement. So, I decide to make this tool.

Episode 2

As time passed, more and more features were added to Substrate. We have std, runtime-benchmarks and try-runtime now. It's hard to check if all features are enabled correctly.

Example

git clone https://github.com/paritytech/polkadot /tmp/subalfred-example/polkadot
cd /tmp/subalfred-example/polkadot
git checkout 0fd106c04e5f57f6342f8e000d471d0f819f7b61
subalfred check features runtime/polkadot -lsubalfred
checking: runtime/polkadot/Cargo.toml
2022-11-02T17:50:17.766228Z TRACE subalfred_core::check::features: check::features::try-runtime takes 0.000155583 secs
2022-11-02T17:50:17.766669Z TRACE subalfred_core::check::features: check::features::std takes 0.000417541 secs
2022-11-02T17:50:17.766846Z TRACE subalfred_core::check::features: check::features::runtime-benchmarks takes 0.000169125 secs
incomplete `try-runtime` of `frame-support`
incomplete `try-runtime` of `runtime-parachains`
incomplete `std` of `frame-benchmarking`
incomplete `std` of `frame-system-benchmarking`
incomplete `std` of `pallet-election-provider-support-benchmarking`
incomplete `std` of `pallet-nomination-pools-benchmarking`
incomplete `std` of `pallet-offences-benchmarking`
incomplete `std` of `pallet-session-benchmarking`
incomplete `std` of `runtime-parachains`
incomplete `std` of `sp-io`
incomplete `runtime-benchmarks` of `primitives`
incomplete `runtime-benchmarks` of `sp-staking`
incomplete `runtime-benchmarks` of `xcm-executor`

CI

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

I've already add these to the Darwinia CI. And here is the result example.

Command convert

Data style converters

Usage: subalfred convert [OPTIONS] <COMMAND>

Commands:
  ascii2hex
          Convert ascii to hex
  bytes-style
          Convert bytes between several different styles
  bytes2hex
          Convert bytes to hex
  hex2bytes
          Convert hex to bytes
  help
          Print this message or the help of the given subcommand(s)

Options:
  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Command convert ascii2hex

Convert ascii to hex

Usage: subalfred convert ascii2hex [OPTIONS] <ASCII>

Arguments:
  <ASCII>
          Ascii data input

Options:
  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

subalfred convert ascii2hex AurevoirXavier
0x41757265766f6972586176696572

Command convert bytes-style

Convert bytes between several different styles

Usage: subalfred convert bytes-style [OPTIONS] --from <STYLE> --to <STYLE> <BYTES>

Arguments:
  <BYTES>
          Bytes data input

Options:
      --from <STYLE>
          Origin style

          [possible values: byte-string-literal, vec-string]

      --to <STYLE>
          Target style

          [possible values: byte-string-literal, vec-string]

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

From Vec String to Byte String Literal

subalfred convert bytes-style --from vec-string --to byte-string-literal "[65, 117, 114, 101, 118, 111, 105, 114, 88, 97, 118, 105, 101, 114]"
AurevoirXavier
subalfred convert bytes-style --from vec-string --to byte-string-literal "[1, 1, 1, 1]"
\x01\x01\x01\x01

From Byte String Literal to Vec String

subalfred convert bytes-style --from byte-string-literal --to vec-string "AurevoirXavier"
[65, 117, 114, 101, 118, 111, 105, 114, 88, 97, 118, 105, 101, 114]
subalfred convert bytes-style --from byte-string-literal --to vec-string "\x01\x01\x01\x01"
[1, 1, 1, 1]

Command convert bytes2hex

Convert bytes to hex

Usage: subalfred convert bytes2hex [OPTIONS] <BYTES>

Arguments:
  <BYTES>
          Bytes data input.

          e.g. `[0, 0, 0, 0]`

Options:
  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

subalfred convert bytes2hex "[65, 117, 114, 101, 118, 111, 105, 114, 88, 97, 118, 105, 101, 114]"
0x41757265766f6972586176696572

Command convert hex2bytes

Convert hex to bytes

Usage: subalfred convert hex2bytes [OPTIONS] <HEX>

Arguments:
  <HEX>
          Hex input.

          e.g. `0x00000000`

Options:
  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

subalfred convert hex2bytes 0x41757265766f6972586176696572
[65, 117, 114, 101, 118, 111, 105, 114, 88, 97, 118, 105, 101, 114]

Command get

Substrate-link node getter

Usage: subalfred get [OPTIONS] <COMMAND>

Commands:
  runtime-upgrade-block
          Get the runtime upgrade block
  help
          Print this message or the help of the given subcommand(s)

Options:
  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Command get runtime-upgrade-block

Get the runtime upgrade block.

Using the dichotomy algorithm to find it out. This operation will fail if the runtime version does not
existed.

Usage: subalfred get runtime-upgrade-block [OPTIONS] --uri <URI> <VERSION>

Arguments:
  <VERSION>
          At this runtime version

Options:
      --uri <URI>
          Node's WS RPC endpoint

          [default: ws://localhost:9944]

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Episode 1

The original question was from stackexchange.

Yep, I think that is an interesting question. So, I implemented this function. It uses dichotomy algorithm, the whole process takes:

$$\log_{2} BlockHeight\times Requests$$

Example

subalfred get runtime-upgrade-block 9100 --uri wss://rpc.polkadot.io -lsubalfred_core::node
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

Command hash

Hash the hex with the specific hasher(hash algorithm)

Usage: subalfred hash [OPTIONS] <HEX>

Arguments:
  <HEX>
          Hex data input

Options:
      --hasher <HASHER>
          Hash algorithm

          [default: blake2-128-concat]
          [possible values: blake2-128, blake2-128-concat, blake2-256, blake2-512, twox64, twox64-concat,
          twox128, twox256, keccak256, keccak512, sha2-256]

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

blake2-128-concat (Default)

subalfred hash 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
0xe58b08eb4646f23e89bde2676c8e1feeb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747

blake2-128

subalfred hash --hasher blake2-128 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
0xe58b08eb4646f23e89bde2676c8e1fee

blake2-256

subalfred hash --hasher blake2-256 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
0x83aa9248019a972a674ada58cfcb6b0dc85cc94c90691b1e93d3e71ded507d32

blake2-512

subalfred hash --hasher blake2-512 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
0x7068368532a7b4a4dedf9994bfe584e4479304e8db003cee3658db7ad938add4ab2ce8d62e559e4de141227124d3b5b1d8d84d3e5e56084ea7804f871b3fde9d

twox64

subalfred hash --hasher twox64 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
0x3ab053dc6b6a71e1

twox64-concat

subalfred hash --hasher twox64-concat 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
0x3ab053dc6b6a71e1b4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747

twox128

subalfred hash --hasher twox128 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
0x3ab053dc6b6a71e13f13e44949b8e388

twox256

subalfred hash --hasher twox256 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
0x3ab053dc6b6a71e13f13e44949b8e388638838f880a0e3dc18e197b7f8efd6dc

keccak256

subalfred hash --hasher keccak256 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
0x7774e3a14e4868bd5f3f6bd409685efd0e5179e783ed53d2a5da42c911efb05a

keccak512

subalfred hash --hasher keccak512 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
0xe7aeb316f9808098e7d71998d4642c784aecbdbbc03061fdcaec6992831bf6ae5abb5673af4f3dec4f4aeed543390ffeda9e0f8900f771f56043128177b1bcea

sha2-256

subalfred hash --hasher sha2-256 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
0x5d0ae9ab625ce7c50e5ced079f414f28161b1b645df49679ebd794fc43c239bc

Command key

Calculate the public key/SS58 address of the SS58 address/public key

Usage: subalfred key [OPTIONS] <PUBLIC KEY/SS58 ADDRESS>

Arguments:
  <PUBLIC KEY/SS58 ADDRESS>
          Public key/SS58 address

Options:
      --type <TYPE>
          Key type

          [possible values: pallet, parachain, sibling]

      --network <NETWORK>
          Network name

          [default: Substrate]

      --list-all
          List all the networks' addresses

      --show-prefix
          Show network(s) prefix(es)

      --json-output
          Enable JSON output

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

Calculate the public key

subalfred key 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
public-key 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
Substrate 5G9z8Ttoo7892VqBHiSWCbnd2aEdH8noJLqZ4HFMzMVNhvgP

Calculate the SS58 address

subalfred key 5G9z8Ttoo7892VqBHiSWCbnd2aEdH8noJLqZ4HFMzMVNhvgP
public-key 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
Substrate 5G9z8Ttoo7892VqBHiSWCbnd2aEdH8noJLqZ4HFMzMVNhvgP

Calculate the pallet address

subalfred key --type pallet "py/trsry"
public-key 0x6d6f646c70792f74727372790000000000000000000000000000000000000000 PalletId(py/trsry)
Substrate 5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z

Subalfred will detect if this is a pallet address automatically.

subalfred key 5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z
public-key 0x6d6f646c70792f74727372790000000000000000000000000000000000000000 PalletId(py/trsry)
Substrate 5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z

Calculate the sovereign address

Sovereign address on relaychain.

subalfred key --type parachain 2000
public-key 0x70617261d0070000000000000000000000000000000000000000000000000000 ParaId(2000)
Substrate 5Ec4AhPUwPeyTFyuhGuBbD224mY85LKLMSqSSo33JYWCazU4

Sovereign address on sibling chain.

subalfred key --type sibling 2000
public-key 0x7369626cd0070000000000000000000000000000000000000000000000000000 SiblId(2000)
Substrate 5Eg2fntJ27qsari4FGrGhrMqKFDRnkNSR6UshkZYBGXmSuC8

Note that, if you are on Moonbeam-link chain, remove last 24 zeros from the public-key.

public-key 0x7369626cd0070000000000000000000000000000000000000000000000000000 SiblId(2000)
public-key 0x7369626cd0070000000000000000000000000000 SiblId(2000)

Subalfred will detect if this is a sovereign address automatically.

subalfred key 5Eg2fntJ27qsari4FGrGhrMqKFDRnkNSR6UshkZYBGXmSuC8
public-key 0x7369626cd0070000000000000000000000000000000000000000000000000000 SiblId(2000)
Substrate 5Eg2fntJ27qsari4FGrGhrMqKFDRnkNSR6UshkZYBGXmSuC8

Option list-all

subalfred key --list-all 5G9z8Ttoo7892VqBHiSWCbnd2aEdH8noJLqZ4HFMzMVNhvgP
public-key 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
BareEd25519           NTG3mn5om1nwD45xx8aUTR3pefA8zEVwfES4dAcw1JMjNgm
BareSecp256k1         5MwePTSDBPzsBZEeCFKXaW43g4NvLKRKVHPgfxtfTD5rzTug
BareSr25519           AswXnhH3BGLd6FA9tNXietCXgNa2cyTZn8AqFt21J7PAnpZ
DICO                  6MpEyNrF2Jk8k9HHFa7mMWiJ8uort9iXNgvzpoKg5m2jonV1
Eggnet                oVRYSJ9KxJzim3FzSpeAMPBJpmQYP6wkEkHz5erKyhFmc3PUL
ICE                   npQjXEEdK3EkZyJp4gUC4jqKg4gdQeHYizXNk6bsFevGx1Dos
KICO                  6G2aiPJqe1sQb5spM3EjycSsVRfZpy61BkNsD7gNcuSFXSgN
SNOW                  ni2MJgjyWScn3yYvNiPtYaAJUhdUb8ZFQvKvLirhz2CDjzTtu
Turing                cU8jCBoMnvw9xNB3HoVoB4bPFwaLQTjVSBxarreqv8m5UubMC
acala                 24xsriZuVo8t2ctLJgHk7mH2M3fDXGe9GF7MNQfjAzTmhcR3
ajuna                 aUtUKdw182tzTyNnVgZijvnDTU9An54EGKajDGD3AM9JHr8Ci
altair                kAMF48Seoe2NLpgBpERuPiUhaBVqPuKM5kG22BGtNkgC5UF25
amplitude             6kxt1M1rZUF3NNu8shdrs7mzirP36tEc8T9XHXtswBQgvnbM
apex                  rzg96q3EEBeHKBq4PoA9jZo3RGoqMuGNUzGTXt9NHs3zsKZNg
ares                  4Tri4XZain8Kn2bU3TQKBPfDrh6GqfkdnpQW8p6xHWjUTQsr
astar                 a2aZkrtaLmFFKs1n1tdEFwu7cwkFMVYKYLhHzTDriVLJ5GZ
aventus               cLx3haNNmFzBd7wutbATTsiEfQe3EWY9xcEhQZSYEoCGNeAUs
bajun                 bUMvGXNsMQUm7wBohPESRRqQDjdY9gcv4yMpqduUb3fo9xRzt
basilisk              bXkghK7H4UNVqFBZUBLMEGUSfi8Q9YrKmPLfJZ9Lpnk1jXLSg
bifrost               fpEpkQHxddyQPGUgYmecADKm763JY84WUtpug6XKa5paJMM
calamari              dmy2WdnrD23rM4nVrA8PE3TWD8M1tB231YoceS7ck2cz4nvbM
centrifuge            4fS2aWePVMsn69QPrXAMwCC59fNrx31gAhWmNBPZDDvT24fC
cere                  6TbuENPeQbcruCgkA6znjQyinPx9wLM3ZdV8SUxyYcdE61cs
cess                  ce7TA31W7N2cdz3VgNjmYphyka6dox4TV41yzP1A2SGYF3pYk
cess-testnet          cXj4wVWrJmQe7zHbzQfU2f2xZD3UzSLAAypXb1FzkoYV32xMV
chainflip             cFMxm6p4BjhCvNfFusMC8jFLsDU2mSGtp3Zg47AXNsJy4tDoM
chainx                5TjJeSycZgsbLce76nCYxQKUKYXDPW3qgDwpHeXxv4gMGnqJ
clover                jHGBKnVSNs4aCrd4JVqVEP6Y1H4cqoUxbAgNoBKcDgskRNmg8
composable            64TGCQE2sS7xGy4tXyUhDov2CTNyibpxosGbykPmhCFGxk6n
contextfree           a7SDW4dbSQLxCPkokx6adk336WpRZGerMmMcyzFmRoJTTLqrd
cord                  3xvQmZrZoKkgzja9Wo1CHtL6dGNoZkc2r7dr4PtSyEm342uB
crust                 cTLRv7s2ZrcA97hoaZEkz3PFrmhC42GTGgS9owBhWRvKaexfe
dark                  2mUVffMjBqFy82iaeQSum58zsSfGuZ3napzGgCAqQydBg7vY
darwinia              2sG9veu8a88hH683YwKw8yQRWvoZxjgJmmYQHsp8sqDfxHHW
datahighway           4N53oY2BLVFbcyC18vXHoVPoDCwynV87bsrNX8Tepf8zBJfV
dentnet               dx9Knzz5LDj4UzmmAYS7eZNdZ3qbsmiG6nk83BqDTFqdoVwGm
dock-pos-mainnet      3GQnxd4k7HdbuKjuB4r2eaU86sNkBUCPXXkvkcPLjFbd5YU5
edgeware              mbu5jwhLvWhZSfwb5efz4UkQbELMikahRSxXMjpnRgJrcEc
efinity               efTEt1iEFLB9Pf5FDWrKUtSjUciocVawat9UPtoU6wqog1dGD
equilibrium           cg7CMCrLB3r7B7DaxVPN2NjJFVoVh3j3tpq4cgg23hNRzgFAa
fragnova              fRkmknCdFyMU718sBfEv2YYp9aAJArxWgdmSh4H1nXVpAy4qJ
geek                  XWGZATcKd9Zw3mpuxmVoefp8KNhn57zuozNL4ukSHKrciyPew
genshiro              cZip8fMgNTE8f7ThGXK4WD4H48kLsXzkakdcDJvrn4eNnfXNT
gm                    gMY6J6wTa8AssBmvDrD5q5GABvhNfSjuEJk3Tfgf56PJzfGj3
heiko                 hJKHS1bhv7u2tw11u6W3sNzAUk5t6aMays8BYRvjNHpkhAqHG
hydradx               7MgqZJGGsDVQJjKvJtv18XNYbmEoRz1jG6UJydkgiJyccwqp
integritee            2NKrdhC7efm4Vo6j2GvpFU5JHW66gpXhq4mkDTbdZZFEYdqE
integritee-incognito  hdUS5e5fKukxSvGgxzixRt1E4qFLZ7YUv5iYkZADBBzvKCfaw
interlay              wdBbAQmEBQZqDUnhj7sUehkhvTYeebSo8bPErUT1Wr572f6YH
joystream             j4VQthW8mfpdAs7GvZgtC3kVcYxKCn2My2HTzRqHgRRe1MgG8
jupiter               3fZRzbEMeT8WXZMkoCN8ABXpgowvQCiUHHyTDLxYafyaCmYh
kabocha               3mM6Famm2k1EgcmDhjF9Y5oFLJ6DTPLzUEXaq2br3Xa4VG9o
kapex                 tsY1kqQw6V4UHasRVx1veXwC2PBrAnDLLnSrn6r1n1wirN28x
karura                sPZLjV6jDPRiW5QVcXhMxkB45NdQuP6tN1693P8FHGo8zCJ
katalchain            UEvJmKVC3tX6GTYsV1brMgUU8oTCAs28bnZgJovPrtr1t9S
kilt                  4s1M6VjCFwdEQGDKfavQgzivSdfT4QGiYad2bYgA8w7RauZQ
kintsugi              a3eJSEw27oHiaTXS8Xs9jPnvwxNzPBgvabcZzcHKzCorveaqE
kulupu                2fgqQfpKoYPExyK7jsZtPAsaDxWyrNRGPtS94WXXx82hPqRq
kusama                GfbnnEgRU94n9ed4RFZ6Z9dBAWs5obykigJSwXKU9hsT2uU
laminar               2AkY7i7Jt61cBgHoDDAmVfYSzXoWaTGfTBfUz6K2dr4FyzaL
litentry              4AVjHYwNZuW9JrP5KrmF3grwvEfPg7s5Dzk7HmB3twx1cPDT
litmus                jcRKyQyPnevVkqtjNQ4Pnt7bbNE5JLfrXPGk1JZ62b3v3R4u2
manta                 dfaeJ6JCQRRsq52cAC45hsnV1mHs4fHjhUcAF4NTUPtvrnT4s
mathchain             4xo1MVGbeEVxZKcna7oS4tzM67ok7auEjXBADEKTbnhurwn7
mathchain-testnet     54afcUp12XNgiP2FUegTSoFmjbx3AmXkvTjHpuxm4eJQ9WvS
moonbeam              VducokCKmmc7iA5aB9JRrbBJqVkUjWy6Z8thUmU1JVEsBLJ47
moonriver             VkJ12HgyaNE6E9qTs7NjNkrL2rodZ2hPsD69t9DAa7xvPM3Ah
neatcoin              5rswgR9E6rNVxrFxiuieU1PAuV6PcEZvRzALkP7AmV4JPvtN
nftmart               nmv42mS6ERxtQ4qhU3ACUJJg3uZ44GhoiH1XTiWnj5YQky5bG
nodle                 4mDgqWBnsekWFCorm43PK6TVo9XA1DeCMe4tys2rg5WwJUjp
oak                   6AEvTPmSFizgS2UMSWMibiBSqwXGmnTUzopjbS35A3qmF5bR
origintrail-parachain gJqqV89qgkKGEyBzhPqLBsvyiUbWixnuBDM5v4EHwbJFq4Z7Z
p3d                   d1GLzqLHaqi2j6VG2PcGaskMqaxx9auwq3RRpouVrbYbciRnp
p3dt                  d7ejDNpwPSL1F6F9iMga73RP2x26y6eF97ctEBef8EGepiwZK
parallel              p8F2qgE7j8MSxfvGd36n7ihSdFTJtMa6JMNQXg4e5YnBXtbnX
peaq                  rtHktHYaRb2JoC5Ahq5rDQ82DukgYPY5Av518WQD2EKwfJtzL
pendulum              6fBDkMUTBBNKDKVfyAkqVDWa5NEk3hc5wWbPfrFaUKpCeWGr
phala                 44i52ZPyBcdR9nycRKtDfnbXGkX6cwEZ34Byg5XkS6MXL68i
picasso               5xfbwQgdV9FE7ufRdSbfquebYyEgfRCScviUN4kUELengQY6
pioneer_network       WWbXu4BNb1QQwVu5qFmKvQxQhpF87Q4xxxi8BJgiFhcvtJhmy
poli                  5ANKsUMQQpFQsSRiPBZUphXCP66LDxAH7QHRSbc4XVttRfvK
polkadex              esprg4jNEzFbX2MQjpsQRiBiAktY5JK28GnAgBZDSMsY8uq69
polkadexparachain     ezDEtcE23asa327JRnwhwsrjN7wgtp3KSLyd5ZJNhzbbLvKwY
polkadot              156HGo9setPcU2qhFMVWLkcmtCEGySLwNqa3DaEiYSWtte4Y
polkafoundry          g65543AY5Z5KCygDKTgj9YawKkVD5wLJZ4xB7JjyQKr9R3Dz3
polkasmith            fyggqVftGxTLgyvKdVcRdNuv8PS4GRc1Ezkihvzp8h86D2Yxp
polymesh              2GYCNheiGNtLLjhG7k3nsZose1wodduBe8DcbmxL6hekGSn8
pontem-network        gkPNMJ8Su8oAJxDZTG8YGYd4Vvp811i6RW8uXZCw28CUf7N6c
quartz_mainnet        yGGpnkEDQfqKtKjEpHFrHZY9tNxvsu6sAMmBynpuT6xmis9QJ
reserved46            5fJdAS4RLGd3ejT2uqxbiCrKcWooVsJt4745X1pZqmsKqDd7
reserved47            5m6HRRbpiZVmonrVpNqd677kFzx6Z3wQF3cD8hTsJdTp7q5Q
reynolds              yBDbj2W7WG9sZUsQ9Qijs1bhZWvU61d5JZDkj2Ri8sHRFbo
robonomics            4GHPYYUmxCNsTunYEPeGRb8NZiogjJVbQwJEuSpMMoYVtpSv
sapphire_mainnet      pxLUnGR64Nb1HxDGDbioZj3dSmLEcoubBGjRpDWdCivnZYW8r
shift                 3NCTDcc9VaWL4P9N5bj42UjYkMX3EepuiUK4NJ2eC7C7MwEw
social-network        xw7g97kFzsyQLLTZkP2wj4X6JHoURMuyE9ApmfbReCnc6q2BN
sora                  cnVaZkLyyeU5h6yUeTTfYYQKSrreWZTMCu2X24RBKL6VCh161
sora_kusama_para      oFFkmbGShjgXYrvYaD3EymDYUzWEdJvLKxjKSHo1DwqLN5eiM
stafi                 34qUSdywLht9bCvyN15ytmwGou6A56wM9eefXF6joYQeWpZG
subsocial             3s8kWaKAR2sxqgAgcG8Auz4fynEWWZyWfB5iSiF9WPAYmTxu
subspace              sufAN5qjKG8hG7zsijsHM5JG4TTmW3ais9idFa5sAj6jnm9Cg
subspace_testnet      stAMUCxcGVmaMn7om9t5zQnGgmBd6DqH4KcKHLqDenGpUYRFG
substrate             5G9z8Ttoo7892VqBHiSWCbnd2aEdH8noJLqZ4HFMzMVNhvgP
synesthesia           2ZuB9gGvRFWWouueqLgs1Gc9aUNgoBnkCwt1SptEVGSD7FJ6
tidefi                fhDnzqyYkYT2mDEa63mGi5E31kNTkNN7MsZK3RDhTJ2ykbHKr
tinker                i51xwp4GYJErWuJFis2AWYhJrHTwqATgANWNN48rFiu99FPRH
totem                 2U7WtgjX2xdnerWBvooqdNLivzEPk1AE21Ksq9Ew2Qqiq2f9
uniarts               5ZWxuSX1wykKVg3a1K5aLJaty2fWSggMsAVwuLBGNvGqZAkM
unique_mainnet        unicLcCWzL8dgqA3khnpJoEwWrp4u2twmKn8m29oFohekNWVg
vln                   4ZeNKX6z7513w5zvwzHLZHveWBEZtrP9ykxdkVkFkNKxjh7r
xxnetwork             6ZPZVMw3ntVb4G6D4dsp7KF9Rt6SzWyZka3G4AcH1UDiNL2o
zeitgeist             dE37RvKbC2wym613QKksdD6QEK5FncNYTBpLdZPpPrzi2jYtt
zero                  3Tz7Uc9YssP4DSYpz8c5QNzyPqfLHqTRuQsByyfwexnbeM1M
zero-alphaville       3ZmmjbgxGAFnNVxHtfV6nHGQ3KodM25x6MRKbfKF7pP5vUpv

Option --network

The network parameter is case insensitive.

subalfred key --network polkadot 5G9z8Ttoo7892VqBHiSWCbnd2aEdH8noJLqZ4HFMzMVNhvgP
public-key 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
polkadot 156HGo9setPcU2qhFMVWLkcmtCEGySLwNqa3DaEiYSWtte4Y

Option --show-prefix

subalfred key --show-prefix 5G9z8Ttoo7892VqBHiSWCbnd2aEdH8noJLqZ4HFMzMVNhvgP
public-key 0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747
Substrate 42 5G9z8Ttoo7892VqBHiSWCbnd2aEdH8noJLqZ4HFMzMVNhvgP

Option --show-prefix

If you don't have the jq command, then just ignore that. I only use it to beautify the output here.

subalfred key --json-output 5G9z8Ttoo7892VqBHiSWCbnd2aEdH8noJLqZ4HFMzMVNhvgP | jq
{
  "addresses": [
    {
      "address": "5G9z8Ttoo7892VqBHiSWCbnd2aEdH8noJLqZ4HFMzMVNhvgP",
      "network": "Substrate"
    }
  ],
  "public-key": "0xb4f7f03bebc56ebe96bc52ea5ed3159d45a0ce3a8d7f082983c33ef133274747",
  "sub-seed": ""
}

Option --type

See Calculate the pallet address and Calculate the sovereign address sections.

Command rpc

Send a RPC request to the node's HTTP RPC endpoint.

# Example:
Get the Polkadot's block zero's hash:
\```sh
# Normal output
subalfred rpc https://rpc.polkadot.io --method chain_getBlockHash --params '[[0,1,2]]'
# Beautiful output
subalfred rpc https://rpc.polkadot.io --method chain_getBlockHash --params '[[0,1,2]]' | jq
\```

Usage: subalfred rpc [OPTIONS] --method <METHOD> <URI>

Arguments:
  <URI>
          Node's HTTP RPC endpoint

          [default: http://localhost:9933]

Options:
      --method <METHOD>
          JSONRPC method name

      --params <[PARAMETER]>
          JSONRPC parameters

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

If you don't have the jq command, then just ignore that. I only use it to beautify the output here.

subalfred rpc https://rpc.polkadot.io --method chain_getBlockHash --params '[[0,1,2]]' | jq
{
  "id": 0,
  "jsonrpc": "2.0",
  "result": [
    "0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3",
    "0xc0096358534ec8d21d01d34b836eed476a1c343f8724fa2153dc0725ad797a90",
    "0x409d0bfe677594d7558101d574633d5808a6fc373cbd964ef236f00941f290ee"
  ]
}

Command state

A set of tools to process Substrate-like chain state

Usage: subalfred state [OPTIONS] <COMMAND>

Commands:
  diff
          Check the differences between the two states.
          Note:
          This is not a symmetric difference operation.
          `a.diff(b)` might equal `b.diff(a)`, but not always.
  export
          Export the chain state from the Substrate-like node through the WS RPC endpoint
  fork-off
          Fork-off the Substrate-like chain state
  insert
          Insert the key/value pair into the specific file.
  override
          Override the chain spec a with b.
  help
          Print this message or the help of the given subcommand(s)

Options:
  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Command state diff

Check the differences between the two states.
Note:
This is not a symmetric difference operation.
`a.diff(b)` might equal `b.diff(a)`, but not always.

Usage: subalfred state diff [OPTIONS] <PATH> <PATH>

Arguments:
  <PATH>
          Chain spec a's path

  <PATH>
          Chain spec b's path

Options:
  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

subalfred state diff chain-spec-a.json chain-spec-b.json
-0xbd2a529379475088d3e29a918cd47872878d434d6125b40443fe11fd292d13a4:0x03000000
-0x4d45a146e2a002ba470f48b9ed9a3e23878d434d6125b40443fe11fd292d13a4:0x02000200
-0xcebf674407db61a30e8759ec5084b7764e7b9012096b41c4eb3aaf947f6ea429:0x0000
subalfred state diff chain-spec-b.json chain-spec-a.json
+0xbd2a529379475088d3e29a918cd47872878d434d6125b40443fe11fd292d13a4:0x03000000
+0x4d45a146e2a002ba470f48b9ed9a3e23878d434d6125b40443fe11fd292d13a4:0x02000200
+0xcebf674407db61a30e8759ec5084b7764e7b9012096b41c4eb3aaf947f6ea429:0x0000

Command state export

Export the chain state from the Substrate-like node through the WS RPC endpoint.

The result will be stored at `<a>.export`.

Usage: subalfred state export [OPTIONS] <URI>

Arguments:
  <URI>
          Live chain's HTTP RPC endpoint

Options:
      --at <HASH/NUM>
          Export the data starting from this block.

          Accept block hash or block number.

      --timeout <SECS>
          Timeout for the fetching

          [default: 10]

      --all
          Export all the data.

          So, it conflicts with any other filter option.

          Note:
          The default behaviour (without this option) is fetching according to metadata's pallet
          storage records, which means if there is any old storage prefix that can not be found in
          the current runtime's pallet storage names will be ignored.

      --skip-pallets <[PALLET]>
          Skip these pallets, while fetching.

          It's useful when you want to skip the 'large' pallets.

      --renew-consensus-with <PATH>
          Renew the consensus relate things of the chain.

          We need the dev chain specification to renew the consensus relates genesis. Otherwise, the
          fork-off chain won't produce block.

          It will:
          - Skip `["System", "Babe", "Authorship", "Session", "Grandpa", "Beefy"]` pallets, but keep
            the `System::Account` data. (in order to make the new chain runnable)
          - Change the id and impl name to `*-export`.
          - Clear the bootnodes.
          - Set the `Staking::ForceEra` to `ForceNone`. (in order to prevent the validator set from
            changing mid-test)

          Usually use this as below to get a runnable fork-off chain, and you can do whatever you
          want on it. Test new features, runtime upgrade, etc.

          ```sh
          xxx-node --export-state > xxx-export.json
          xxx-node --build-spec xxx-dev > xxx-dev.json
          subalfred state fork-off xxx-export.json --renew-consensus-with xxx.dev.json --simple-governance
          --disable-default-bootnodes
          xxx-node --chain xxx.json.fork-off --alice --tmp
          ```

          Note:
          `--alice` only works for which dev chain's genesis validator is `//Alice`, otherwise the
          new chain won't produce block. If your dev chain's genesis validator is `//Bob`, then
          running with `--bob`. But if your dev chain's genesis validator isn't any one of the
          well-known keys, then you should start the node with `--validator` and insert the key
          manually.

      --simple-governance
          Use `//Alice` to control the governance.

          It's useful when you want to test the runtime upgrade.

          It will:
          - Replace sudo key with `//Alice`, if the sudo pallet existed.
          - Replace phragmen election and council members with `//Alice`, if the collective pallet
            existed.
          - Replace technical membership and tech.comm members with `//Alice`, if the membership
            pallet existed.

      --disable-default-bootnodes
          Disable adding the default bootnodes to the specification.

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

ENV preparation

git clone https://github.com/substrate-developer-hub/substrate-node-template.git /tmp/subalfred-example/substrate-node-template
cd /tmp/subalfred-example/substrate-node-template
cargo build
target/debug/node-template build-spec --dev --raw > chain-spec.json
target/debug/node-template --chain chain-spec.json --alice --tmp

Open PolkadotApps account page. Check Dave's balances is 0. Then transfer 10 UNIT from Alice to Dave.

Start example

# Open a new terminal.
cd /tmp/subalfred-example/substrate-node-template
subalfred state export ws://127.0.0.1:9944 -lsubalfred_core::state,subalfred_core::substrate_client

The exported state is locate at /tmp/subalfred-example/substrate-node-template/default-chain-spec.json.export.

Command state fork-off

Fork-off the Substrate-like chain state.

The result will be stored at `<a>.fork-off`.

Usage: subalfred state fork-off [OPTIONS] <PATH>

Arguments:
  <PATH>
          Target chain spec file's path

Options:
      --renew-consensus-with <PATH>
          Renew the consensus relate things of the chain.

          We need the dev chain specification to renew the consensus relates genesis. Otherwise, the
          fork-off chain won't produce block.

          It will:
          - Skip `["System", "Babe", "Authorship", "Session", "Grandpa", "Beefy"]` pallets, but keep
            the `System::Account` data. (in order to make the new chain runnable)
          - Change the id and impl name to `*-export`.
          - Clear the bootnodes.
          - Set the `Staking::ForceEra` to `ForceNone`. (in order to prevent the validator set from
            changing mid-test)

          Usually use this as below to get a runnable fork-off chain, and you can do whatever you
          want on it. Test new features, runtime upgrade, etc.

          ```sh
          xxx-node --export-state > xxx-export.json
          xxx-node --build-spec xxx-dev > xxx-dev.json
          subalfred state fork-off xxx-export.json --renew-consensus-with xxx.dev.json --simple-governance
          --disable-default-bootnodes
          xxx-node --chain xxx.json.fork-off --alice --tmp
          ```

          Note:
          `--alice` only works for which dev chain's genesis validator is `//Alice`, otherwise the
          new chain won't produce block. If your dev chain's genesis validator is `//Bob`, then
          running with `--bob`. But if your dev chain's genesis validator isn't any one of the
          well-known keys, then you should start the node with `--validator` and insert the key
          manually.

      --simple-governance
          Use `//Alice` to control the governance.

          It's useful when you want to test the runtime upgrade.

          It will:
          - Replace sudo key with `//Alice`, if the sudo pallet existed.
          - Replace phragmen election and council members with `//Alice`, if the collective pallet
            existed.
          - Replace technical membership and tech.comm members with `//Alice`, if the membership
            pallet existed.

      --disable-default-bootnodes
          Disable adding the default bootnodes to the specification.

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

ENV preparation

Finish the Command state export's example first.

Start example

cd /tmp/subalfred-example/substrate-node-template
subalfred state fork-off default-chain-spec.json.export --renew-consensus-with chain-spec.json
target/debug/node-template --chain default-chain-spec.json.export.fork-off --alice --tmp

Check block number from the console, it should be started from 0. It means this is a new chain.

Open PolkadotApps account page. Check Dave's balances, it should be 10. It means this is a new chain with the exported/fork-off(ed) data.

Command state override

Override the chain spec a with b.

The result will be stored at `<a>.override`.

Usage: subalfred state override [OPTIONS] <PATH> <PATH>

Arguments:
  <PATH>
          Chain spec a's path

  <PATH>
          Chain spec b's path

Options:
  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

subalfred state override a.json b.json
# You could use `diff` command to check the result, its output should be empty.
subalfred state diff a.json.override b.json

Command state insert

Insert the key/value pair into the specific file.

If the key already exists, it will be overwritten.

# Example
\```sh
# Calculate the WASM code key.
subalfred convert ascii2hex ':code'
# "0x3a636f6465"
# Override the WASM code.
subalfred state insert chain-spec.json --key 0x3a636f6465 --with-file runtime.compact.compressed.wasm
\```

Usage: subalfred state insert [OPTIONS] --key <HEX> <--value <HEX>|--with-file <PATH>> <PATH>

Arguments:
  <PATH>
          Target state file's path

Options:
      --key <HEX>
          Storage key

      --value <HEX>
          Storage value

      --with-file <PATH>
          Storage value file

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

# Update WASM code of a chain spec file.
subalfred state insert chain-spec.json --key 0x3a636f6465 --with-file runtime.compact.compressed.wasm

Command storage-key

Calculate the storage key of the storage item

Usage: subalfred storage-key [OPTIONS] --pallet <PALLET> --item <ITEM>

Options:
      --pallet <PALLET>
          Prefix of the storage

      --item <ITEM>
          Name of the storage item

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

subalfred storage-key --pallet System --item Account
0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9

Actually, it equals to twox128(pallet) + twox128(item).

subalfred convert ascii2hex System
0x53797374656d
subalfred hash --hasher twox128 0x53797374656d
0x26aa394eea5630e07c48ae0c9558cef7
subalfred convert ascii2hex Number
0x4e756d626572
subalfred hash --hasher twox128 0x4e756d626572
0x02a5c1b19ab7a04f536c519aca4983ac
0x26aa394eea5630e07c48ae0c9558cef7 + 0x02a5c1b19ab7a04f536c519aca4983ac
0x26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac

Command track-updates

Track the updates.

This command require a `GITHUB_TOKEN` environment variable to be set. It will list all the commits between the `from` and `to` GitHub ref.

The output is in markdown format.

Usage: subalfred track-updates [OPTIONS] --from <VERSION> --to <VERSION> <OWNER/REPOSITORY>

Arguments:
  <OWNER/REPOSITORY>
          Target repository.

          e.g. paritytech/substrate

Options:
      --from <VERSION>
          Release starting from

      --to <VERSION>
          Release updating to

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

We take paritytech/substrate as an example. If you want to track the updates of cumulus just replace the paritytech/substrate with paritytech/cumulus.

The GITHUB_TOKEN API key must have the privilege of the target repository.

This command will list all the commits/pull requests and their labels between polkadot-v0.9.33 and polkadot-v0.9.36. And some commits/pull requests which was under the important/specific labels.

pub enum WatchedLabels {
	/// [https://github.com/paritytech/substrate/labels/B3-apinoteworthy]
	B3Api,
	/// [https://github.com/paritytech/substrate/labels/B5-clientnoteworthy]
	B5Client,
	/// [https://github.com/paritytech/substrate/labels/B7-runtimenoteworthy]
	B7Runtime,
	/// [https://github.com/paritytech/substrate/labels/C7-high%20❗%EF%B8%8F]
	C7High,
	/// [https://github.com/paritytech/substrate/labels/C9-critical%20‼%EF%B8%8F]
	C9Critical,
	/// [https://github.com/paritytech/substrate/labels/E1-runtimemigration]
	E1Runtime,
	/// [https://github.com/paritytech/substrate/labels/E2-databasemigration]
	E2Database,
	/// [https://github.com/paritytech/substrate/labels/E4-newhostfunctions]
	E4NewHostFunctions,
	/// [https://github.com/paritytech/substrate/labels/E5-breaksapi]
	E5BreaksApi,
	/// [https://github.com/paritytech/substrate/labels/E6-transactionversion]
	E6TransactionVersion,
	/// [https://github.com/paritytech/substrate/labels/E7-breaksauthoring]
	E7BreaksAuthoring,
	/// [https://github.com/paritytech/substrate/labels/E8-breakseverything]
	E8BreaksEverything,
	/// [https://github.com/paritytech/substrate/labels/E10-client-update-first%20👀]
	E10ClientUpdateFirst,
	/// [https://github.com/paritytech/substrate/labels/I8-enhancement%20🎁]
	I8Enhancement,
}

Currently, its output is a markdown. You can copy and paste it to create a new issue manually.

There is an open StackExchange question. After paritytech finishes the refactoring of the labels. This command will provide a more professional update list in the future. You can easily focus on specific parts.

Also, there are some discussion about this command here.

Moreover, there will be a GitHub action later, which will check the Polkadot updates and create an issue for that.

export GITHUB_TOKEN=OMITTED
subalfred track-updates paritytech/substrate --from polkadot-v0.9.33 --to polkadot-v0.9.36
# or
GITHUB_TOKEN=OMITTED subalfred track-updates paritytech/substrate --from polkadot-v0.9.33 --to polkadot-v0.9.36

Track updates

repository: paritytech/substrate
commits   : 112
command   : subalfred track-updates paritytech/substrate --from polkadot-v0.9.33 --to polkadot-v0.9.36

https://github.com/paritytech/substrate/compare/polkadot-v0.9.33...polkadot-v0.9.36

All

Watched labels

Command workspace

Workspace manager

Usage: subalfred workspace [OPTIONS] <COMMAND>

Commands:
  update
          Update the workspace member versions
  update-deps
          Update the workspace dependency versions.
  help
          Print this message or the help of the given subcommand(s)

Options:
  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Command workspace update

Update the workspace member versions

Usage: subalfred workspace update [OPTIONS] <VERSION>

Arguments:
  <VERSION>
          Target version

Options:
      --manifest-path <PATH>
          Root `Cargo.toml`'s path.

          If `Cargo.toml` wasn't given, Subalfred will search it under the given path.

          [default: ./Cargo.toml]

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Example

git clone https://github.com/substrate-developer-hub/substrate-parachain-template.git /tmp/subalfred-example/substrate-parachain-template
cd /tmp/subalfred-example/substrate-parachain-template
subalfred workspace update 1.0.0

Command workspace update-deps

Update the Substrate-related repositories' dependency versions.

To use this command, you must make sure your dependencies were anchored at a branch.
This is a general rule of the Polkadot ecosystem.

We use the regex pattern matching here.
So, `git` field must be set before the `branch` field.

It might look like this:
\```toml
frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v.0.0.0" }
\```

Usage: subalfred workspace update-deps [OPTIONS] --targets <REPOSITORY,*> <VERSION>

Arguments:
  <VERSION>
          Target version.

          e.g. `0.0.0` will generate `release-v0.0.0` and `polkadot-v0.0.0`

Options:
      --manifest-path <PATH>
          Root `Cargo.toml`'s path.

          If `Cargo.toml` wasn't given, Subalfred will search it under the given path.

          [default: ./Cargo.toml]

      --targets <REPOSITORY,*>
          Targets.

          e.g. cumulus,polkadot,substrate

  -l, --log <TARGET=LEVEL,*>
          Set a custom log filter.

          This flag is also working with the `RUST_LOG` environment variable. If you use `RUST_LOG`
          simultaneously, this will append `RUST_LOG`'s value after the log.

          [default: info]

  -h, --help
          Print help information (use `-h` for a summary)

Episode 1

In parachain development. We have some dependency groups. cumulus,polkadot and substrate. And you can add your specific dependency group. For example frontier.

For example, when we want to update the version from polkadot-v0.9.30 to polkadot-v0.9.31. We need to handle those dependency versions. And here is a general rule. All those repositories have and must have a branch named polkadot-v0.9.31. For polkadot it's release-v0.9.31.

So, with this, you can update those versions with a one-line command.

Any ideas/improvements are welcome. We can draft an Episode 2 together!

Example

We take substrate-parachain-template as an example.

This command will update all the dependencies correctly that I described above.

And there is nothing I can show. Try the example commands below and check the file differences. You'll find all the dependencies were updated correctly.

git clone https://github.com/substrate-developer-hub/substrate-parachain-template.git /tmp/subalfred-example/substrate-parachain-template
cd /tmp/subalfred-example/substrate-parachain-template
subalfred workspace update-deps 0.9.31 --targets cumulus,polkadot,substrate