Grandpa docs
Look up any call, event, or storage item with code examples. Runtime v472 · Block #9,197,056
Developer documentation for the Grandpa pallet of the Subtensor blockchain, part of the Bittensor decentralized AI network. This page is designed for developers integrating with the chain: look up any call, event, or storage item, copy code examples in TypeScript, Python, or Rust, and filter by your role. For in-depth explanations, version history, and relationships between items, see the Reference section.
Grandpa
See [`Pallet::report_equivocation`].
Calls 3
Reports GRANDPA voter equivocation (double voting) with ownership proof.
Parameters
| Name | Type | Format | Description |
|---|---|---|---|
equivocation_proof | EquivocationProof | — | equivocation_proof (EquivocationProof) |
key_owner_proof | Void | — | key_owner_proof (Void) |
// ----------------------------------------------------------------------
// HEADS UP: 1 arg below has a complex type with no usable default.
// Look for `undefined as any` and replace it with real value
// before running — the snippet compiles, but will fail at runtime as-is.
// ----------------------------------------------------------------------
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Build report_equivocation call (typed, named args)
const equivocation_proof = undefined as any /* EquivocationProof — replace with real value */;
const tx = api.tx.Grandpa.report_equivocation({
equivocation_proof,
});Reports GRANDPA equivocation without requiring a signed transaction.
Parameters
| Name | Type | Format | Description |
|---|---|---|---|
equivocation_proof | EquivocationProof | — | equivocation_proof (EquivocationProof) |
key_owner_proof | Void | — | key_owner_proof (Void) |
// ----------------------------------------------------------------------
// HEADS UP: 1 arg below has a complex type with no usable default.
// Look for `undefined as any` and replace it with real value
// before running — the snippet compiles, but will fail at runtime as-is.
// ----------------------------------------------------------------------
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Build report_equivocation_unsigned call (typed, named args)
const equivocation_proof = undefined as any /* EquivocationProof — replace with real value */;
const tx = api.tx.Grandpa.report_equivocation_unsigned({
equivocation_proof,
});Signals that GRANDPA finality has stalled and schedules a forced authority set change.
Parameters
| Name | Type | Format | Description |
|---|---|---|---|
delay | u32 | Integer | delay: Block number |
best_finalized_block_number | u32 | Integer | best_finalized_block_number: Block number |
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Build note_stalled call (typed, named args)
const delay = 0;
const best_finalized_block_number = 0;
const tx = api.tx.Grandpa.note_stalled({
delay,
best_finalized_block_number,
});Events 3
Emitted when a new GRANDPA authority set becomes active.
When it fires
- Session change triggered authority set rotation
- New validators have been selected for GRANDPA
Fields
| Name | Type | Format | Description |
|---|---|---|---|
authority_set | Vec<(Public, u64)> | Array of (Public, u64) | New set of GRANDPA authorities (public keys with voting weights) |
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Subscribe to NewAuthorities events
client.finalizedBlock$.subscribe(async (block) => {
const events = await api.event.Grandpa.NewAuthorities.get(block.hash);
for (const evt of events) {
console.log("NewAuthorities:", evt.payload);
}
});Emitted when GRANDPA finality is paused by governance.
When it fires
- GRANDPA was previously live (not already paused)
- Governance or root triggered the pause
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Subscribe to Paused events
client.finalizedBlock$.subscribe(async (block) => {
const events = await api.event.Grandpa.Paused.get(block.hash);
for (const evt of events) {
console.log("Paused:", evt.payload);
}
});Emitted when GRANDPA finality resumes after being paused.
When it fires
- GRANDPA was previously paused
- Governance or root triggered the resume
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Subscribe to Resumed events
client.finalizedBlock$.subscribe(async (block) => {
const events = await api.event.Grandpa.Resumed.get(block.hash);
for (const evt of events) {
console.log("Resumed:", evt.payload);
}
});Storage 7
List of current GRANDPA authorities (public keys with voting weights).
WeakBoundedVec import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query Authorities storage (no keys - plain value)
const result = await api.query.Grandpa.Authorities.getValue();
console.log("Authorities:", result);Monotonically increasing counter for GRANDPA authority set changes.
u64 (Integer)import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query CurrentSetId storage (no keys - plain value)
const result = await api.query.Grandpa.CurrentSetId.getValue();
console.log("CurrentSetId:", result);Next block number where a forced authority change can be signaled.
u32 (Integer)import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query NextForced storage (no keys - plain value)
const result = await api.query.Grandpa.NextForced.getValue();
console.log("NextForced:", result);Scheduled authority set change waiting to be applied.
StoredPendingChange import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query PendingChange storage (no keys - plain value)
const result = await api.query.Grandpa.PendingChange.getValue();
console.log("PendingChange:", result);Maps GRANDPA set ID to the session index when that set was last responsible.
u32 (Integer)Keys
| Name | Type | Format | Description |
|---|---|---|---|
key1 | u64 | Integer | — |
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query SetIdSession storage
const key1 = 0n;
const result = await api.query.Grandpa.SetIdSession.getValue(key1);
console.log("SetIdSession:", result);Indicates GRANDPA has stalled with (delay, best_finalized_block).
(u32, u32) import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query Stalled storage (no keys - plain value)
const result = await api.query.Grandpa.Stalled.getValue();
console.log("Stalled:", result);Current state of the GRANDPA authority set (Live, Paused, or PendingPause/Resume).
StoredState import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query State storage (no keys - plain value)
const result = await api.query.Grandpa.State.getValue();
console.log("State:", result);Constants 3
Maximum number of GRANDPA authorities allowed.
u3232import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query MaxAuthorities constant
const value = await api.constants.Grandpa.MaxAuthorities();
console.log("MaxAuthorities:", value);Maximum nominators per validator for GRANDPA key ownership proofs.
u3220import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query MaxNominators constant
const value = await api.constants.Grandpa.MaxNominators();
console.log("MaxNominators:", value);Maximum entries kept in the SetIdSession mapping.
u64"0"import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query MaxSetIdSessionEntries constant
const value = await api.constants.Grandpa.MaxSetIdSessionEntries();
console.log("MaxSetIdSessionEntries:", value);
// Balance: divide by 10^9 for TAO
const tao = value / 1_000_000_000n;Errors 7
Cannot pause GRANDPA because it's already paused or pending.
Common Causes
- Already paused
- PendingPause scheduled
How to Fix
Check Grandpa.State,Wait for pending change
Cannot resume GRANDPA because it's not paused.
Common Causes
- Already Live
- PendingResume scheduled
How to Fix
Check Grandpa.State,Wait for pending change
An authority set change is already pending.
Common Causes
- Session change scheduled
- Previous forced change pending
How to Fix
Check Grandpa.PendingChange,Wait for current change
Cannot signal forced change; minimum delay not met.
Common Causes
- Recent forced change
- NextForced not reached
How to Fix
Check Grandpa.NextForced,Wait for delay
Key ownership proof in equivocation report is invalid.
Common Causes
- Wrong session
- Proof corrupted
- Session data pruned
How to Fix
Verify session matches,Check SetIdSession,Report promptly
Equivocation proof doesn't demonstrate double voting.
Common Causes
- Bad signatures
- Same block
- Wrong round
How to Fix
Verify signatures,Ensure different blocks,Check round
This equivocation was already reported.
Common Causes
- Another reporter was faster
- Resubmitting
How to Fix
No action needed - offender will be slashed