Terminology in Polkadot


Terminology

PoV (Proof of Validity)

The PoV is the data package produced by parachain collators and sent to Relay Chain validators.

PVF (Parachain Validation Function)

The PVF is the specific logic or code stored on the Relay Chain that validators execute to check a parachain block

Candidate

Candidate Receipt

Compact representation of the result of a validation. This is what validators receive from collators, together with the PoV.

/// A candidate-receipt.
struct CandidateReceipt {
    /// The descriptor of the candidate.
    descriptor: CandidateDescriptor,
    /// The hash of the encoded commitments made as a result of candidate execution.
    commitments_hash: Hash,
}

Candidate Descriptor

This struct is pure description of the candidate, in a lightweight format.

/// A unique descriptor of the candidate receipt.
struct CandidateDescriptor {
    /// The ID of the para this is a candidate for.
    para_id: ParaId,
    /// The hash of the relay-chain block this is executed in the context of.
    relay_parent: Hash,
    /// The collator's sr25519 public key.
    collator: CollatorId,
    /// The blake2-256 hash of the persisted validation data. These are extra parameters
    /// derived from relay-chain state that influence the validity of the block which
    /// must also be kept available for approval checkers.
    persisted_validation_data_hash: Hash,
    /// The blake2-256 hash of the `pov-block`.
    pov_hash: Hash,
    /// The root of a block's erasure encoding Merkle tree.
    erasure_root: Hash,
    /// Signature on blake2-256 of components of this receipt:
    /// The parachain index, the relay parent, the validation data hash, and the `pov_hash`.
    signature: CollatorSignature,
    /// Hash of the para header that is being generated by this candidate.
    para_head: Hash,
    /// The blake2-256 hash of the validation code bytes.
    validation_code_hash: ValidationCodeHash,
}

PersistedValidationData

The validation data provides information about how to create the inputs for validation of a candidate. This information is derived from the chain state and will vary from para to para, although some of the fields may be the same for every para.

struct PersistedValidationData {
    /// The parent head-data.
    parent_head: HeadData,
    /// The relay-chain block number this is in the context of. This informs the collator.
    relay_parent_number: BlockNumber,
    /// The relay-chain block storage root this is in the context of.
    relay_parent_storage_root: Hash,
    /// The list of MQC heads for the inbound channels paired with the sender para ids. This
    /// vector is sorted ascending by the para id and doesn't contain multiple entries with the same
    /// sender.
    ///
    /// The HRMP MQC heads will be used by the validation function to authorize the input messages passed
    /// by the collator.
    hrmp_mqc_heads: Vec<(ParaId, Hash)>,
    /// The maximum legal size of a POV block, in bytes.
    pub max_pov_size: u32,
}

Candidate Commitments

The execution and validation of parachain candidates produces a number of values which either must be committed to blocks on the relay chain or committed to the state of the relay chain.

/// Commitments made in a `CandidateReceipt`. Many of these are outputs of validation.
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Default))]
struct CandidateCommitments {
    /// Messages directed to other paras routed via the relay chain.
    horizontal_messages: Vec<OutboundHrmpMessage>,
    /// Messages destined to be interpreted by the Relay chain itself.
    upward_messages: Vec<UpwardMessage>,
    /// New validation code.
    new_validation_code: Option<ValidationCode>,
    /// The head-data produced as a result of execution.
    head_data: HeadData,
    /// The number of messages processed from the DMQ.
    processed_downward_messages: u32,
    /// The mark which specifies the block number up to which all inbound HRMP messages are processed.
    hrmp_watermark: BlockNumber,
}

Backing

Backed Candidate

An CommittedCandidateReceipt along with all data necessary to prove its backing. This is submitted to the relay-chain to process and move along the candidate to the pending-availability stage.

struct BackedCandidate {
  candidate: CommittedCandidateReceipt,
  validity_votes: Vec<ValidityAttestation>,
  // the indices of validators who signed the candidate within the group. There is no need to include
  // bit for any validators who are not in the group, so this is more compact.
  // The number of bits is the number of validators in the group.
  //
  // the group should be apparent from context.
  validator_indices: BitVec,
}

struct BackedCandidates(Vec<BackedCandidate>); // sorted by para-id.

Availability

Proof-of-Validity

Often referred to as PoV, this is a type-safe wrapper around bytes (Vec) when referring to data that acts as a stateless-client proof of validity of a candidate, when used as input to the validation function of the para.

struct PoV(Vec<u8>);

Available Data

This is the data we want to keep available for each candidate included in the relay chain. This is the PoV of the block, as well as the PersistedValidationData

struct AvailableData {
    /// The Proof-of-Validation of the candidate.
    pov: Arc<PoV>,
    /// The persisted validation data used to check the candidate.
    validation_data: PersistedValidationData,
}

Erasure Chunk

The AvailableData is split up into an erasure-coding as part of the availability process. Each validator gets a chunk. This describes one of those chunks, along with its proof against a merkle root hash, which should be apparent from context, and is the erasure_root field of a CandidateDescriptor.

struct ErasureChunk {
    /// The erasure-encoded chunk of data belonging to the candidate block.
    chunk: Vec<u8>,
    /// The index of this erasure-encoded chunk of data.
    index: u32,
    /// Proof for this chunk's branch in the Merkle tree.
    proof: Vec<Vec<u8>>,
}

Validity & Availability

Erasure Coding

The cryptographic method used in Polkadot to ensure Data Availability (DA) without requiring every validator to store every piece of data from every parachain.

Steps: parachain block → relay chain inclusion

The protocol separates backing (candidate accepted with enough validator votes on-chain) from inclusion / enactment (candidate commitments applied: para head, UMP/HRMP, etc., after availability).

1. Off-chain: collator produces a candidate

  1. The collator builds a parachain block and the PoV (proof-of-validity bundle validators execute).
  2. Backing validators assigned to that para/core (scheduler / claim queue) fetch the collation via the collator protocol, then run candidate-validation (PVF / Wasm) to check the state transition.
  3. Validators gossip statements (Seconded, then Valid) via statement distribution. Enough valid votes ⇒ candidate is backable.
  4. The backing subsystem forms a BackedCandidate: receipt + validity attestations. The PoV is erasure-coded; validators store/gossip chunks (availability distribution / availability store).

Relay-chain parachain state is not updated yet.

2. Relay block author: parachains inherent

  1. The block author (BABE) fills the mandatory paras_inherent data: ParachainsInherentDatasigned availability bitfields, new backed_candidates, disputes, and parent header (process_inherent_data in paras_inherent).

3. On-chain: one enter call — bitfields/enact then new backing

Inside paras_inherent::enterprocess_inherent_data, roughly:

  1. Scheduling context — allowed relay parents / claim-queue view (shared::new_block, etc.).
  2. Disputes — weight limits, import statements; freeze can halt parachain progress.
  3. Free disputed coresfree_disputed for invalidated candidates.
  4. Bitfields — sanitize, then inclusion::update_pending_availability_and_get_freed_cores: each bit means a validator has the erasure chunk for that core’s pending work. Enough votes ⇒ available.
  5. For pending work that becomes available (respecting async backing order: predecessors enacted first), enact_candidate runs — this is runtime “inclusion”: UMP/HRMP/DMP, Paras::note_new_head, etc.
  6. Timeoutsfree_timedout when applicable.
  7. New BackedCandidatesback_candidatesinclusion::process_candidates: checks relay parents, persisted validation data, backing signatures, message limits → stored in PendingAvailability (backed but not yet enacted).

Typical timeline

4. Finality and extra checks (after enactment)

  1. GRANDPA finalizes relay blocks; the parachain block is only final in the usual sense once the relay block that enacted it is finalized.
  2. Approval voting — extra validity checks for finality gating; separate from enact_candidate.

Reference