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.