Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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
35 changes: 35 additions & 0 deletions .cargo/audit.toml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,20 @@ ignore = [
# From https://rustsec.org/advisories/RUSTSEC-2026-0096
# CRITICAL severity but only affects aarch64 architecture.
# Our primary deployment targets x86-64. Pinned by polkadot-sdk; no update path available.
"RUSTSEC-2026-0006", # wasmtime v35.0.0 — segfault with f64.copysign on x86-64.
# https://rustsec.org/advisories/RUSTSEC-2026-0006 ->
# https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-vc8c-j3xm-xj73
# The vulnerability only triggers when signals-based-traps is DISABLED in the wasmtime Config.
# Substrate's sc-executor-wasmtime uses wasmtime::Config::new() which has signals_based_traps
# enabled by default, and never disables it. Therefore this code path is never exercised.
"RUSTSEC-2026-0114", # wasmtime v35.0.0 — panic when allocating oversized table (MEDIUM, DoS only).
# https://rustsec.org/advisories/RUSTSEC-2026-0114 ->
# https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-p8xm-42r7-89xg
# Arithmetic overflow panic when a Wasm module declares a table with an extremely large size,
# leveraging the memory64 proposal's 64-bit range. Requires the on-demand allocator and
# memory64 to be enabled. Substrate runtime Wasm blobs are compiled for wasm32 and are
# governance-controlled (not attacker-supplied). PVF validation only runs Wasm from registered
# parachains. This is a DoS (panic), not a sandbox escape. Unaffected in practice.

# ===== lru (unsound — IterMut not exercised) =====

Expand All @@ -166,6 +180,27 @@ ignore = [
# Only triggers when a custom logger implementation calls rand::rng() during ThreadRng
# reseeding. This project uses Substrate's standard sc-tracing logging infrastructure
# which does not call rand::rng(). The trigger conditions are not met.

"RUSTSEC-2026-0186", # memmap2 v0.5.10 — unchecked pointer offset in advise/flush range functions.
# https://rustsec.org/advisories/RUSTSEC-2026-0186
# Unsoundness: out-of-bounds offset/len passed to advise_range/flush_range/flush_async_range/
# unchecked_advise_range reach pointer arithmetic handed to syscalls (pointer is not
# dereferenced). Fixed in memmap2 0.9.11. The 0.5.10 copy comes from parity-db v0.4.13
# (polkadot-sdk transitive via sc-client-db -> parity-db), which requires memmap2 ^0.5 and
# has no 0.4.x release on the patched line; parity-db 0.4.13 is pinned by polkadot-sdk
# stable2512. (The other memmap2 copy, 0.9.x, was updated to 0.9.11.)
# Verified against the parity-db 0.4.13 source: the ONLY affected function it calls is
# MmapMut::flush_range, once, in Index::flush() (src/index.rs:605):
# map.flush_range(META_SIZE, map.len() - META_SIZE)
# The advise_range/unchecked_advise_range/flush_async_range functions are never used
# (parity-db does madvise via a raw libc::madvise call, not the memmap2 wrapper). The
# flush_range range is in-bounds by construction: the index file is always created at
# file_size = total_entries(index_bits) * 8 + META_SIZE (META_SIZE is a 16 KiB constant),
# so [META_SIZE, map.len()) is exactly the map minus its header. Both arguments are pure
# functions of the local index geometry, never of transaction/proof/block/network data, so a
# remote attacker has no path to the out-of-bounds trigger. (The only theoretical trigger is a
# locally truncated index file making map.len() < META_SIZE underflow the len — this needs
# local DB write access, which is outside the remote threat model.)
]
informational_warnings = ["unmaintained", "yanked"]

Expand Down
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[target.x86_64-unknown-linux-gnu]
linker = "/usr/bin/cc"
rustflags = ["-C", "link-arg=-fuse-ld=lld"]
rustflags = ["-C", "link-arg=-fuse-ld=lld", "-C", "link-arg=-lstdc++"]
118 changes: 118 additions & 0 deletions .claude/commands/runtime/describe_cfg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
description: >
Describe pallet configuration types from the vflow-runtime crate.
Provide a pallet name and optionally specific type names to describe.
If no types are given, all types from the pallet Config impl are listed
and you are asked which ones to describe.
argument-hint: <pallet> [type1 type2 ...]
---

# Describe Runtime Configuration Types

You are analyzing pallet configuration types for the `vflow-runtime` crate.

## Input

- **Pallet**: `$0`
- **Types to describe**: `$ARGUMENTS`

If `$0` is empty or missing, ask the user for the pallet crate name (e.g. `pallet_collator_selection`, `pallet_session`, `pallet_aura`).

## Step 1: Find the Config implementation

Search the `vflow-runtime` crate source (under `runtime/vflow/src/`) for
`impl $0::Config for Runtime` (or the appropriate pattern — some pallets use
generic instances like `pallet_bags_list::Config<VoterBagsListInstance>`).

Read the full `impl` block to extract all associated type assignments.

## Step 2: Determine which types to describe

Parse the arguments after the pallet name. If specific type names were provided
(e.g. `XcmConfig Filter Sort`), describe only those types.

If NO type names were provided beyond the pallet name, list ALL associated types
found in the `impl` block and ask the user which ones they want described.
Present them as a numbered list so the user can pick.

## Step 3: For each selected type, provide

For each type, research thoroughly using:
- The pallet source code in the local cargo registry (`~/.cargo/registry/src/`)
to find the trait definition, doc comments, and trait bounds
- The polkadot-fellows/runtimes repository (https://github.com/polkadot-fellows/runtimes)
for all the system parachains on Polkadot and Kusama, such as Asset Hub and Collectives
- The Moonbeam repository (https://github.com/moonbeam-foundation/moonbeam) for the Moonbeam
parachain runtime

Produce the following for each type:

### 3a. Description

What this type is and what trait bound it has. Include the doc comment from
the pallet's `Config` trait if available.

### 3b. Purpose and application examples

How this type is used within the pallet. What behavior does it control?
What happens with different values? Reference specific pallet code paths
where this type is used (e.g. hooks, extrinsics, internal functions).

### 3c. Possible values

List the concrete types that can satisfy the trait bound. For each, explain
the behavioral difference:
- SDK-provided implementations (e.g. `()`, `ConstU32<N>`, `ConstBool<B>`,
`Disabled`, `HoldConsideration`, etc.)
- Common patterns from production runtimes

### 3d. System parachains configurations

Look up how this type is configured in the system parachains for the Polkadot and Kusama relay chain
runtimes from https://github.com/polkadot-fellows/runtimes.

To determine the correct source version, check the currently deployed spec
version on each chain. For example:
- Asset Hub: https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpolkadot-asset-hub-rpc.polkadot.io
- Collectives: https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpolkadot-collectives-rpc.polkadot.io
- Moonbeam: https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fmoonbeam.api.onfinality.io%2Fpublic-ws

Then find the corresponding tag/release in the polkadot-fellows/runtimes repo
and look at the exact configuration. Present a comparison table:

| Parameter | Asset Hub | Collectives | Moonbeam | VFlow |
|-----------|----------|--------|--------|----------|
| `TypeName` | value | value | value | value |

### 3e. VFlow current value

Show the exact value configured in the vflow-runtime `impl` block, including
the constant/parameter definition if it references a `parameter_types!` value
or a `const`.

## Output format

For each type, use this structure:

```
#### `TypeName`

**Trait bound**: `TraitName<...>`

**Description**: ...

**Purpose**: ...

**Possible values**:
- `Value1` -- explanation
- `Value2` -- explanation

**Asset Hub/Collectives/Moonbeam comparison** (spec version XXXX):

| Parameter | Asset Hub | Collectives | Moonbeam | VFlow |
|-----------|----------|--------|--------|----------|
| `TypeName` | ... | ... | ... | ... |

**VFlow value**: `type TypeName = ...;` (defined as `CONST_NAME = value`)
```

218 changes: 218 additions & 0 deletions .claude/skills/fix-benchmarks/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
---
name: Fix Benchmarks
description: >
This skill should be used when the user asks to "fix benchmarks",
"fix cargo make test-bench", "fix benchmark compilation errors",
"fix benchmark panics", "fix bench", or mentions broken benchmarks,
benchmark failures, or pallet benchmark issues. Provides a systematic
workflow for diagnosing and fixing benchmark compilation errors and
runtime panics.
---

# Fix Benchmarks

Systematic workflow for diagnosing and fixing `cargo make test-bench`
failures. Covers two failure classes: compilation errors and runtime
panics.

## Important

- This skill fixes **existing** broken benchmarks only. It does NOT
write benchmarks for new pallets or regenerate weight files.
- Benchmark fixes should never change production behavior. Use
`#[cfg(feature = "runtime-benchmarks")]` guards when adjusting
constants or configuration for benchmark compatibility.

## Workflow Overview

1. Build with benchmarks enabled and capture errors
2. Classify each error as a compilation failure or runtime panic
3. Apply the appropriate fix strategy
4. Verify the fix by re-running `cargo make test-bench`

## Step 1: Build with Benchmarks

```bash
cargo build --release --features runtime-benchmarks 2>&1
```

If this fails, you have **compilation errors** — go to Step 2a.

If the build succeeds, run the benchmarks:

```bash
./target/release/vflow-node benchmark pallet --pallet "*" --extrinsic "*" -s 2 -r 1 2>&1
```

If a benchmark panics, go to Step 2b.

## Step 2a: Fix Compilation Errors

Compilation errors typically come from pallet API changes in upstream
dependencies (polkadot-sdk, Frontier, cumulus) that break benchmark
code.

### Diagnosis

1. Read the compiler error to identify the affected crate and file
2. Common locations:
- Pallet benchmarks: `pallets/<name>/src/benchmarking.rs`
- Runtime benchmark list: `runtime/vflow/src/benchmark.rs`
- Runtime benchmark dispatch: `runtime/vflow/src/lib.rs` (the
`impl_runtime_apis!` block, `BenchmarkingApi` section)
- XCM benchmark config: also in `runtime/vflow/src/lib.rs`

### Common Compilation Fix Patterns

**Missing or changed trait implementations:**
The upstream pallet added or changed a `Config` associated type that
the `BenchmarkHelper` or similar benchmark trait requires. Check what
the upstream benchmark expects and implement it in the runtime config.

**Changed benchmark function signatures:**
The upstream `#[benchmarks]` module changed its function signatures or
setup requirements. Read the new upstream benchmark code to understand
what changed.

**New pallet added to runtime but missing from benchmark list:**
Add the pallet to `runtime/vflow/src/benchmark.rs` inside the
`define_benchmarks!` macro, and ensure the `runtime-benchmarks` feature
is propagated in `runtime/vflow/Cargo.toml`.

### Where to Look for Upstream Reference

When fixing compilation errors, compare against the upstream benchmark
code from the dependency that changed. The key upstream sources are:

- **Polkadot SDK pallets** (stable2512): `frame/` and `pallets/`
directories in polkadot-sdk
- **Frontier pallets** (Moonbeam fork, `moonbeam-polkadot-stable2512`):
Moonbeam's frontier fork
- **Cumulus pallets**: `cumulus/pallets/` in polkadot-sdk

## Step 2b: Fix Runtime Panics

Runtime panics occur when benchmarks execute but hit assertion failures
or impossible states due to configuration mismatches between what the
upstream benchmark code expects and our runtime configuration.

### Diagnosis

1. Read the panic message and backtrace to identify:
- Which pallet and extrinsic panicked
- The assertion or condition that failed
2. Locate the upstream benchmark code for that pallet to understand
what preconditions it expects

### Common Runtime Panic Fix Patterns

**Insufficient balances or existential deposit issues:**
Benchmarks may expect accounts to have minimum balances. Check:
- `runtime/common/src/constants.rs` — `EXISTENTIAL_DEPOSIT` is
conditionally set under `runtime-benchmarks`. The value must balance
two competing constraints:
- **Non-zero**: Upstream benchmarks like `pallet_collator_selection`
derive `CandidacyBond` from `Currency::minimum_balance()` (= ED)
and assert it's > 0.
- **Low enough**: With `insecure_zero_ed` always enabled on
pallet-balances, the upstream benchmark code takes the zero-ED
code path (`cfg!(feature = "insecure_zero_ed")`), which assumes
accounts are NOT reaped. If ED is too high (e.g. 100), accounts
with balance below ED get reaped, breaking assertions. ED must be
smaller than the benchmark's hardcoded minimum balance (100) to
avoid this. Currently set to `1`.
- `runtime/vflow/src/genesis_config_presets.rs` — The dev genesis
endows accounts and adds extra accounts under `runtime-benchmarks`.
Add more endowed accounts or increase `ENDOWMENT` if benchmarks need
more funded accounts.

**Transaction fee / minimum balance mismatches:**
- `runtime/vflow/src/configs/monetary.rs` contains
`OnChargeTransactionRuntimeBenchmarks`, a benchmark-only wrapper
around the transaction payment handler. Adjust `minimum_balance()`
if benchmarks fail due to fee-related assertions.

**Missing or invalid genesis state:**
Some benchmarks expect specific storage entries to exist at genesis.
Fix by adjusting `development_config_genesis()` in
`runtime/vflow/src/genesis_config_presets.rs`, guarded behind
`#[cfg(feature = "runtime-benchmarks")]`.

**Configuration constant too low or too high:**
Some benchmarks parametrize over runtime constants (e.g., max items,
max weight). If a constant is set too low for the benchmark to run,
add a benchmark-specific override using conditional compilation:

```rust
#[cfg(not(feature = "runtime-benchmarks"))]
pub const SOME_LIMIT: u32 = 10;

#[cfg(feature = "runtime-benchmarks")]
pub const SOME_LIMIT: u32 = 100;
```

Follow the established pattern in `runtime/common/src/constants.rs`.

**XCM benchmark configuration:**
XCM benchmarks have dedicated configuration in `runtime/vflow/src/lib.rs`
inside the `impl_runtime_apis!` block. Key types:
- `ExistentialDepositAsset` — minimum asset for XCM transfers. Must use
a meaningful non-zero amount (e.g. `CENTS`), not `ExistentialDeposit::get()`
which is near-zero under benchmarks.
- `XcmConfig` / `DeliveryHelper` — XCM routing for benchmarks

**AccountId32 vs AccountKey20 incompatibility (EVM chains):**
VFlow uses 20-byte EVM accounts (`AccountKey20`), but some upstream
pallet_xcm extrinsics (e.g. `add_authorized_alias`,
`remove_authorized_alias`) hardcode `AccountId32` pattern matching.
These benchmarks will always fail on EVM chains. The fix is to use
`frame_support::traits::Disabled` for `AuthorizedAliasConsideration`
in `pallet_xcm::Config` (in `runtime/vflow/src/configs/xcm.rs`). This
makes the benchmark fail gracefully at ticket creation with
`BenchmarkError::Override(Weight::MAX)` — the same approach Moonbeam
uses. The resulting weight file records `Weight::MAX`, effectively
disabling those extrinsics at runtime.

**Checking how Moonbeam handles a benchmark issue:**
When an upstream benchmark is incompatible with EVM/20-byte-account
chains, check Moonbeam's runtime for reference
(https://github.com/moonbeam-foundation/moonbeam). They face the same
`AccountKey20` constraints. Common patterns: using `Disabled` for
unsupported features, letting benchmarks fail gracefully via
`BenchmarkError::Override(Weight::MAX)`, or configuring benchmark
traits to return `None` to skip.

## Step 3: Verify the Fix

After applying fixes, run the full benchmark test:

```bash
cargo make test-bench
```

This builds with `--features runtime-benchmarks` and runs all pallet
benchmarks with minimal steps/repeats (`-s 2 -r 1`).

If only specific pallets were affected, you can verify faster by
targeting them:

```bash
cargo build --release --features runtime-benchmarks && \
./target/release/vflow-node benchmark pallet \
--pallet "pallet_name" --extrinsic "*" -s 2 -r 1
```

## Key File Reference

| Purpose | Path |
|---------|------|
| Benchmark task definition | `Makefile.toml` (`test-bench`, `build-bench`) |
| Benchmark list (which pallets) | `runtime/vflow/src/benchmark.rs` |
| Benchmark dispatch & XCM config | `runtime/vflow/src/lib.rs` (`BenchmarkingApi`) |
| Conditional constants | `runtime/common/src/constants.rs` |
| Monetary / fee config | `runtime/vflow/src/configs/monetary.rs` |
| XCM pallet config | `runtime/vflow/src/configs/xcm.rs` (`AuthorizedAliasConsideration`, `ExecuteXcmOrigin`) |
| Dev genesis presets | `runtime/vflow/src/genesis_config_presets.rs` |
| Per-chain configs | `runtime/vflow/src/configs/mainnet.rs`, `volta.rs` |
| Pallet benchmarks | `pallets/<name>/src/benchmarking.rs` |
| Runtime feature propagation | `runtime/vflow/Cargo.toml` (`runtime-benchmarks` feature) |
Loading
Loading