Commit-Reveal Weights (CRV3)

Consensus

Weight privacy protocol using timelock encryption (TLE) with drand randomness — validators encrypt weights for a future drand round, and the runtime automatically decrypts them at epoch.

Click items to navigate to their reference pages.

The Big Picture

Commit-reveal is the "anti-cheat" mechanism for weight submission. Without it, validators can watch the mempool or previous epoch's weights and simply copy the best-performing validator. CRV3 forces independence: weights are encrypted with timelock encryption targeting a future drand randomness round. Nobody — not even the validator — can reveal them early. The runtime auto-decrypts when the drand pulse arrives.

Why This Matters

Weight copying undermines subnet evaluation quality. If validators just copy each other, miners are not being independently evaluated and the "wisdom of the crowd" advantage is lost. CRV3 restores incentive to do actual evaluation work.

Example Scenario

Epoch N: Validator encrypts WeightsTlockPayload(uids, weights=[0.5, 0.3, 0.2], version_key) using TLE targeting drand round R (corresponding to the reveal epoch). They submit the ciphertext via commit_crv3_mechanism_weights. When drand round R arrives, the runtime reads the pulse signature from Drand.Pulses[R], decrypts the ciphertext, verifies the payload, and sets the weights automatically.

Common Questions

What if the drand pulse is delayed?
The commit stays in CRV3WeightCommits until the matching drand pulse arrives. If the pulse never arrives (unlikely with drand), the commitment expires after the reveal window.
Can someone decrypt my weights early?
No — TLE ciphertexts can only be decrypted with the drand signature for the target round, which does not exist until that round is produced by the drand beacon network.
Do I need to submit a reveal transaction?
No. CRV3 reveals are fully automatic. The runtime decrypts matured commits during block_step. You only submit the encrypted commit.

Use Cases

  • Implementing CRV3 in validator software
  • Understanding commit timing and drand round targeting
  • Debugging failed decryptions
  • Evaluating CRV3 effectiveness on a subnet

CRV3 (Commit-Reveal Version 3) is a weight privacy protocol that prevents validators from copying each other's weights. Validators encrypt their weight vector using Timelock Encryption (TLE) targeted at a future drand randomness round. The encrypted ciphertext is submitted on-chain. When the target drand round arrives, the runtime automatically decrypts and applies the weights — no manual reveal needed.

This forces validators to independently evaluate miners — encrypted weights cannot be read by anyone until the drand pulse arrives, at which point the commitment window for the next round has closed. Subnets can enable/disable CRV3 via the CommitRevealWeightsEnabled hyperparameter.

Triggers

  • Validator submits commit_crv3_mechanism_weights with TLE-encrypted weight payload
  • Runtime automatically decrypts matured commits during block_step using drand pulse signatures

Inputs (5)

ItemTypeRole
commit_crv3_mechanism_weights SubtensorModulecallSubmit TLE-encrypted weight payload targeting a future drand round
CommitRevealWeightsEnabled SubtensorModulestorageWhether CRV3 is active on this subnet
RevealPeriodEpochs SubtensorModulestorageNumber of epochs in the reveal window
CRV3WeightCommits SubtensorModulestorageStored encrypted weight commitments awaiting drand-based decryption
Pulses DrandstorageDrand randomness pulses used to decrypt matured TLE ciphertexts

Outputs (2)

ItemTypeRole
Weights SubtensorModulestorageUpdated weight vectors after successful decryption and verification
CRV3WeightCommits SubtensorModulestorageCommitment cleared after decryption

Source Files

pallets/subtensor/src/coinbase/reveal_commits.rs
reveal_crv3_commits_for_subnet()

Formulas

Timelock Encryption (TLE)

Weights are encrypted using TLE with a target drand round number. The ciphertext can only be decrypted when the drand beacon produces the signature for that round.

payload = WeightsTlockPayload(hotkey, uids, values, version_key)
ciphertext = TLE_encrypt(payload, target_drand_round)
// At reveal: runtime reads Drand.Pulses[round].signature
// decrypted_payload = TLE_decrypt(ciphertext, drand_signature)
// Weights are set via do_set_mechanism_weights(decrypted_payload)

Related Workflows

set-weights

Version History

v360 CRV3 commit-reveal protocol introduced with timelock encryption via drand
v374 Reveal period window extended, improved error messages