HIPsHanzo Proposals
Back to HIPs
HIP-0079FinalStandards TrackInfrastructure

Q-Chain — Quasar Finality Block Standard

Hanzo AI
Created: 2026-05-10
Requires: HIP-0077, HIP-0078, HIP-0084

HIP-0079: Q-Chain — Quasar Finality Block Standard

Abstract

Q-Chain is the compact finality-block log for the Quasar consensus engine. Each Q-Block carries the minimum information needed for finality: roots of the validator / DKG / identity state held in Z-Chain (HIP-0078) plus a single Pulsar-M-65 threshold signature (HIP-0084) that proves the current epoch's committee finalised the block. Q-Chain does not carry raw ML-DSA validator pubkeys, raw ML-DSA per-validator signatures, raw DKG transcript messages, or raw attestation blobs — those live in Z-Chain.

The result: a finality lane whose per-block size is bounded and small (a few hundred bytes plus one ~3.3 KB Pulsar-M-65 signature), independent of validator-set size. Adding validators makes Z-Chain heavier, not Q-Chain.

Specification

Q-Block structure

QBlock {
    version                      uint16
    network_id                   uint32
    chain_id                     uint32
    height                       uint64
    round_or_view                uint32
    parent_qblock_hash           [32]byte

    // State roots — Z-Chain anchors. Each MUST equal the latest
    // accepted EpochCommitment field for the current epoch.
    lux_state_root               [32]byte    // Lux primary state at this height
    zchain_state_root            [32]byte    // anchors EpochCommitment.zchain_state_root
    validator_set_root           [32]byte    // anchors EpochCommitment.validator_registry_root
    committee_root               [32]byte    // anchors EpochCommitment.committee_root
    dkg_transcript_root          [32]byte    // anchors EpochCommitment.dkg_transcript_root
    group_public_key_hash        [32]byte    // anchors EpochCommitment.group_public_key_hash

    // Payload anchors — block-specific data lives elsewhere.
    payload_root                 [32]byte    // application transactions
    da_root                      [32]byte    // data-availability commitment

    // Cert envelope.
    proof_system_id              ProofSystemID  // = 0x10 STARK_FRI_SHA3_PQ canonical (0x80/0x81 refused)
    hash_suite_id                HashSuiteID    // = 0x01 SHA3_NIST canonical
    sig_scheme_id                SigSchemeID    // = 0x52 Pulsar-M-65 default; 0x53 for high-value roots

    // Signature.
    signer_bitmap_or_weight_commitment  []byte  // who attested (committee bitmap or weight Merkle root)
    pulsar_m_threshold_signature        []byte  // single threshold sig over the canonical transcript
}

What Q-Chain MUST NOT carry

Hard exclusions:

  • Full validator ML-DSA-65 public keys (live in Z-Chain identity_root).
  • Per-validator ML-DSA-65 identity signatures (live in Z-Chain validator-registration proofs).
  • Full DKG ceremony messages (live in Z-Chain dkg_transcript_root).
  • Per-validator attestation blobs (live in Z-Chain).
  • Z-Chain proof bytes for non-epoch-boundary blocks (the cert references zchain_state_root by hash; the proof itself only ships at epoch boundaries).

A Q-Block that carries any of these violates the spec and MUST be rejected. The wire format does not have fields to hold them; this is an enforcement-by-construction guarantee.

Canonical transcript binding

The transcript Pulsar-M signs over for a Q-Block is computed as:

TranscriptHash = TupleHash256(
    [ "Q-Chain/v1",
      version,           // 2 bytes BE
      network_id,        // 4
      chain_id,          // 4
      height,            // 8
      round_or_view,     // 4
      parent_qblock_hash,
      lux_state_root,
      zchain_state_root,
      validator_set_root,
      committee_root,
      dkg_transcript_root,
      group_public_key_hash,
      payload_root,
      da_root,
      [proof_system_id],          // 1
      [hash_suite_id],             // 1
      [sig_scheme_id],             // 1
      signer_bitmap_or_weight_commitment ],
    customization = "PULSAR-M-Q-BLOCK-V1")

TupleHash256 per NIST SP 800-185 is used for unambiguous length-prefixed tuple hashing. Customisation tags pin the protocol version; bumping "v1" → "v2" is the only way to reuse the same transcript bytes for a breaking change. Hash family is HashSuiteID = 0x01 SHA3_NIST only — HashSuite-mismatched Q-Blocks are not produceable on Lux primary network.

Acceptance rule

A full node accepts a Q-Block at height H iff every of the following holds:

  1. parent_qblock_hash matches the chain tip.
  2. zchain_state_root matches the latest accepted Z-Chain epoch root.
  3. validator_set_root matches the latest accepted Z-Chain validator_registry_root (per EpochCommitment).
  4. committee_root matches the latest accepted Z-Chain committee_root.
  5. dkg_transcript_root matches the latest accepted Z-Chain dkg_transcript_root.
  6. group_public_key_hash matches the latest accepted Z-Chain group_public_key_hash.
  7. proof_system_id is NOT in the forbidden set (IsForbiddenInPQMode() == false); strict-PQ networks require 0x10 STARK_FRI_SHA3_PQ.
  8. hash_suite_id == 0x01 SHA3_NIST.
  9. sig_scheme_id ∈ {0x52 Pulsar-M-65, 0x53 Pulsar-M-87} for mainnet; testnet may also accept 0x51 Pulsar-M-44.
  10. signer_bitmap_or_weight_commitment satisfies the configured threshold (43-of-64 default per HIP-0084).
  11. pulsar_m_threshold_signature verifies under unmodified FIPS 204 ML-DSA.Verify against the canonical transcript hash and the group public key derived from group_public_key_hash.

If any check fails, the block is rejected and a slashing-evidence record is produced per HIP-0084 §"Identifiable abort".

Production defaults

parametervalue
version0x0001
proof_system_id0x10 (STARK_FRI_SHA3_PQ)
hash_suite_id0x01 (SHA3_NIST)
sig_scheme_id0x52 (Pulsar-M-65)
committee size64
BFT fault boundf = 21
threshold43-of-64
epoch lengthnetwork-configurable; start 1 hour
DKG cadenceonce per epoch (HIP-0084)
online signingpreprocessing-enabled
abort handlingidentifiable abort required

High-value roots (governance, bridges, slashing, archival) MAY upgrade sig_scheme_id to 0x53 Pulsar-M-87 for the duration of the operation. Block consumers MUST accept either.

What changes for Quasar mode

PQModeQuasar (consensus/config/pq_mode.go) maps to:

  • proof_system_id = 0x10 STARK_FRI_SHA3_PQ
  • hash_suite_id = 0x01 SHA3_NIST
  • sig_scheme_id = 0x52 Pulsar-M-65 (default) or 0x53 Pulsar-M-87 (high-value)

The legacy "Pulsar.R + Groth16/BN254 Z-Chain rollup" wire shape from the prior HIP-0077 is retired with the migration to Z-Chain v1 (HIP-0078 Phase 3 flag day).

Security considerations

  • No silent downgrade. A Q-Block that carries proof_system_id = 0x80 or 0x81 is refused before signature verification. The forbidden markers exist on the wire so a misconfigured operator's block is named, not silently accepted.
  • Single threshold sig per block. Multi-sig fallback paths (per-validator BLS + ML-DSA, classical/PQ hybrid) are NOT in this HIP. A future variant MAY add hybrid-cert support but it lives in a follow-up HIP, not here.
  • Root tampering. All root fields are bound into the transcript; flipping any one breaks signature verification.
  • Signer-bitmap forgery. Bitmap is bound into the transcript and validated against committee_root; an attacker who flips a bit must produce a valid Pulsar-M sig over the modified transcript, which reduces to forging Pulsar-M.
  • Replay across networks. network_id and chain_id are bound into the transcript; a Q-Block valid on Lux mainnet is not valid on a tenant network.

Adoption order

  1. Wire format frozen (this HIP).
  2. consensus/pkg/wire/qblock.go reference encoder/decoder.
  3. Test vectors at ~/work/lux/consensus/qblock-vectors/ covering acceptance, refusal-on-forbidden-proof-system, transcript binding.
  4. Quasar driver (consensus/protocol/quasar/) consumes Q-Blocks from WitnessSet.Run outputs.
  5. Q-Chain VM at chains/quasarvm (planned location) implements acceptance rule.
  6. Phase 2 of HIP-0078 ships, gating the proof_system_id = 0x10 requirement on Lux primary network.

References

  • HIP-0077 — Mesh Identity, Gossip & Payments (parent).
  • HIP-0078 — Z-Chain PQ Identity Rollup (root source).
  • HIP-0084 — Pulsar-M DKG (signing primitive).
  • FIPS 204 — ML-DSA verification target.
  • FIPS 202 + NIST SP 800-185 — TupleHash256 transcript family.