EIP-225 Clique proof-of-authority consensus protocol

Final · Consensus & staking · EIP status Final · created 2017-03-06

Defines Clique, a proof-of-authority consensus mechanism in which only pre-approved signers can produce blocks. It reuses the existing block header structure as-is, making it easy to drop into any client.

Why it is needed

A testnet has no real value, so it cannot be secured by proof-of-work, since a proof-of-work network's security scales only with the computing power committed to it. In fact, in late February 2017, an attacker exploited low mining difficulty on the Ropsten testnet to inflate the block gas limit from the usual 4.7 million up to 9 billion, then sent huge transactions that paralyzed the network. Even before that, several very long chain reorganizations had already split the network along client and version lines. The Parity team responded with an emergency soft fork that rolled back blocks and capped the gas limit, but this was a stopgap: it required other clients to implement the fork rules separately, was incompatible with fast and light sync, and did not stop junk data from flowing in. Proof-of-stake (Casper) was still at the research stage and not usable right away, so a proof-of-authority approach that could be implemented immediately and would properly fix the testnet was proposed.

What changes

Today

After EIP-225

Who is affected

In depth

Design constraint: the signer list is managed entirely within the header

Proof-of-authority requires checking every block against a trusted signer list, and that list changes over time. Storing the list in an Ethereum contract seems like an option, but fast, light, and warp sync cannot access state during synchronization, so that approach cannot be used. Adding new voting fields to the header is also an option, but it would require changing core data structures across multiple implementations, burdening development, maintenance, and security alike. For this reason, the original text imposes two constraints: the protocol managing the signer list must be fully contained within the block header, and it must fit into the existing data model as-is. The resulting design reuses the header instead of the EVM, and existing fields instead of new ones.

Redefinition of header fields and constants

extraData fixes the leading EXTRA_VANITY (32 bytes) as free space for the signer and the trailing EXTRA_SEAL (65 bytes) as the signature slot. Checkpoint (epoch transition) blocks place the current signer list (N*20 bytes) in ascending byte order between them, and omit it otherwise. beneficiary (miner) becomes the field holding the address being proposed for a list change, and is set to zero otherwise. nonce is the proposal for that address: only NONCE_AUTH (0xffffffffffffffff) for addition and NONCE_DROP (0x0000000000000000) for removal are allowed, and both fields must be zero on checkpoint blocks. ommersHash has no meaning outside PoW, so it is always UNCLE_HASH (Keccak256(RLP([]))), and mixHash is left for fork protection but is zero otherwise. timestamp must be at least the parent timestamp plus BLOCK_PERIOD (proposed value 15 seconds). difficulty is the block score: an in-turn block, where BLOCK_NUMBER % SIGNER_COUNT == SIGNER_INDEX, gets DIFF_INTURN (2), otherwise DIFF_NOTURN (1). The epoch length EPOCH_LENGTH is proposed at 30000 blocks, similar to mainnet ethash. During transaction execution, the COINBASE opcode and fee attribution must use the actual signer account recovered from extraData, not beneficiary.

Block signing and signing frequency limits

Signers sign the block's sighash. The sighash is the hash, in the order defined by the yellow paper, of everything except the signature itself: every header field including nonce and mixDigest, and extraData with the 65-byte signature suffix excluded. The signature is produced with the standard secp256k1 curve, and the resulting 65 bytes (R, S, V, where V is 0 or 1) go at the end of extraData. Since the address can be recovered from the signature, a separate miner field is unnecessary. To limit the damage from a leaked key, each signer may sign at most 1 block out of every SIGNER_LIMIT (floor(SIGNER_COUNT / 2) + 1) consecutive blocks. The recommended strategy is for the in-turn signer to sign and propagate immediately at parent time + BLOCK_PERIOD, while out-of-turn signers delay by rand(SIGNER_COUNT * 500ms) to reduce small forks and network traffic.

Voting rules and epoch checkpoints

Epoch transition blocks (including genesis) are stateless checkpoints. They must not carry votes, all pending votes are discarded, and tallying restarts from scratch. This lets a client sync from a single checkpoint hash without replaying the voting history before it. On non-epoch blocks, a signer may cast one vote per block, and if the same signer votes on the same target again, only the latest vote is kept. Multiple proposals can be in progress simultaneously, and a proposal takes effect immediately once it reaches SIGNER_LIMIT approvals. Once a proposal passes, all pending votes for that target, for and against, are discarded. Nonsensical proposals, such as proposing to remove an address that is not a signer, are not penalized either, for implementation simplicity. Since a small reorg can make a voting block disappear, the suggested strategy is to configure a proposal on the signer node and have it randomly include one per block. Even if a proposal appears to have passed, it should not be discarded immediately, since it might still be reorged out.

No cascading votes

When a signer is removed, the majority threshold drops by 1, which can suddenly push another pending proposal over the threshold. That execution could in turn trigger yet another proposal to pass. If conflicting proposals (for example, adding a new signer and removing an existing one) pass at the same time, the evaluation order can significantly change the final list, and since signers can flip their vote every block, it is not even clear which proposal came first. Clique avoids this pitfall by explicitly forbidding cascading effects. Only the account named in the current header's beneficiary can be added to or removed from the list, and any other proposal that reaches a majority as a side effect is executed only when that target is voted on again later and the majority still holds at that point.

Four attack vectors and their defenses

Malicious signer: even if a malicious user joins the list or a signing key is stolen, the damage is limited because each signer can only sign 1 out of every K blocks, and the remaining signers can vote them out. Censoring signer: to guard against a signer trying to censor a block containing a vote to remove them, the signing frequency is capped at 1 in N/2. Succeeding at censorship would require controlling more than 51% of signing accounts, in which case the game is already over anyway. Spam signer: since injecting a new proposal every block would let the votes a node must track grow without bound, votes older than W blocks are treated as invalid; this window is called the epoch. Simultaneous blocks: with N signers, N-K+1 of them can produce a block at any given time, creating contention, so each signer adds a small random delay to its block release time so that small forks happen only rarely.

Status, implementation, and test cases

This EIP is a specification with Final status. The reference implementation lives in go-ethereum's consensus/clique package and has served as the consensus engine for the Rinkeby testnet since April 2017. The source document also includes test cases for various voting scenarios that pin down the edge cases. A block from an unauthorized signer must fail with errUnauthorizedSigner, a re-signature from a recently-signed signer must fail with errRecentlySigned, and bulk-importing checkpoint blocks must not reset the recent-signing record. It also verifies, through scenarios where signers are quickly added, removed, and re-added, that pending votes from a passed proposal must not remain in the system and contaminate later results.

Original EIP · ← EIPs