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_rootby 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:
parent_qblock_hashmatches the chain tip.zchain_state_rootmatches the latest accepted Z-Chain epoch root.validator_set_rootmatches the latest accepted Z-Chainvalidator_registry_root(per EpochCommitment).committee_rootmatches the latest accepted Z-Chaincommittee_root.dkg_transcript_rootmatches the latest accepted Z-Chaindkg_transcript_root.group_public_key_hashmatches the latest accepted Z-Chaingroup_public_key_hash.proof_system_idis NOT in the forbidden set (IsForbiddenInPQMode() == false); strict-PQ networks require0x10 STARK_FRI_SHA3_PQ.hash_suite_id == 0x01 SHA3_NIST.sig_scheme_id∈ {0x52 Pulsar-M-65,0x53 Pulsar-M-87} for mainnet; testnet may also accept0x51 Pulsar-M-44.signer_bitmap_or_weight_commitmentsatisfies the configured threshold (43-of-64 default per HIP-0084).pulsar_m_threshold_signatureverifies under unmodified FIPS 204 ML-DSA.Verify against the canonical transcript hash and the group public key derived fromgroup_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
| parameter | value |
|---|---|
version | 0x0001 |
proof_system_id | 0x10 (STARK_FRI_SHA3_PQ) |
hash_suite_id | 0x01 (SHA3_NIST) |
sig_scheme_id | 0x52 (Pulsar-M-65) |
| committee size | 64 |
| BFT fault bound | f = 21 |
| threshold | 43-of-64 |
| epoch length | network-configurable; start 1 hour |
| DKG cadence | once per epoch (HIP-0084) |
| online signing | preprocessing-enabled |
| abort handling | identifiable 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_PQhash_suite_id = 0x01 SHA3_NISTsig_scheme_id = 0x52 Pulsar-M-65(default) or0x53 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 = 0x80or0x81is 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_idandchain_idare bound into the transcript; a Q-Block valid on Lux mainnet is not valid on a tenant network.
Adoption order
- Wire format frozen (this HIP).
consensus/pkg/wire/qblock.goreference encoder/decoder.- Test vectors at
~/work/lux/consensus/qblock-vectors/covering acceptance, refusal-on-forbidden-proof-system, transcript binding. - Quasar driver (
consensus/protocol/quasar/) consumes Q-Blocks fromWitnessSet.Runoutputs. - Q-Chain VM at
chains/quasarvm(planned location) implements acceptance rule. - Phase 2 of HIP-0078 ships, gating the
proof_system_id = 0x10requirement 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.