Owner: @Mehmet @Marcin Pawlowski @Thomas Lavaur
Reviewers: đ˘@Youngjoon Lee đ˘@David Rusu đ˘@Ălvaro Castro-Castilla
This document defines an implementation-friendly specification of the Proof of Quota (PoQ), which is introduced in Proof of Quota.
The PoQ ensures that there is a limited number of message encapsulations that a node can perform. This constrains the number of messages a node can introduce to the Blend network. The mechanism regulating these messages is similar to rate-limiting nullifiers.
The Proof of Quota (PoQ) verifies that a node's public key is within a limit for either a core node or a leader node. It consists of two parts:
PoQ_C
): Ensures that the core node is declared and hasnât already produced more keys than the core quota Q_C
.PoQ_L
): Ensures that the leader node would win the proof of stake for current Cryptarchia epoch and hasnât already produced more keys than the leadership quota Q_L
. That doesnât guarantee that the node is indeed winning because the PoQ doesnât check if the note is unspent enabling generation of the proof ahead of time preventing extreme delays.The final proof PoQ
is valid if either PoQ_C
or PoQ_L
holds.
A proof attesting that for the following public values derived from blockchain parameters:
class ProofOfQuotaPublic:
session: int # Session number (uint64)
core_quota: int # Allowed messages per session for core nodes
leader_quota: int # Allowed messages per session for potential leaders
core_root: zkhash # Merkle root of zk_id of the core nodes
K_part_one: int # First part of the signature public key (16 bytes)
K_part_two: int # Second part of the signature public key (16 bytes)
pol_epoch_nonce: int # PoL Epoch nonce
pol_t0: int # PoL constant t0
pol_t1: int # PoL constant t1
pol_ledger_aged: zkhash # Merkle root of the PoL eligible notes
# Outputs:
key_nullifier: zkhash # derived from session, private index and private sk
The prover knows a witness:
class ProofOfQuotaWitness:
index: int # This is the index of the generated key. Limiting this index limits the maximum number of key generated. (20 bits)
selector: bool # Indicates if it's a leader (=1) or a core node (=0)
# This part is filled randomly by potential leaders
core_sk: zkhash # sk corresponding to the zk_id of the core node
core_path: list[zkhash] # Merkle path proving zk_id membership (len = 20)
core_path_selectors: list[bool] # Indicates how to read the core_path (if Merkle nodes are left or right in the path)
# This part is filled randomly by core nodes
pol_sl: int # PoL slot
pol_sk_starting_slot: int # PoL starting slot of the slot secrets
pol_note_value: int # PoL note value
pol_note_tx_hash: zkhash # PoL note transaction
pol_note_output_number: int # PoL note transaction output number
pol_noteid_path: list[zkhash] # PoL Merkle path proving noteID membership in ledger aged (len = 32)
pol_noteid_path_selectors: list[bool] # Indicates how to read the note_path (if Merkle nodes are left or right in the path)
pol_slot_secret: int # PoL slot secret corresponding to sl
pol_slot_secret_path: list[zkhash] # PoL slot secret Merkle path to sk_secrets_root (len = 25)
Such that the following constraints hold: