Proof-of-stake in RChain will be handled by the PoS "blessed" contract within the RChain state. Since all validators must know about each other, this contract will live in the top level namespace (see Powerset shards). This contract will perform the following functions:
- Bonding (adding new validators)
- Unbonding (removing validators)
Additionally, each namespace will have a local version of the PoS blessed contract which performs the following functions:
- Rewards distribution (paying validators for the blocks they publish)
Each of these functions will be detailed in the remaining sections of this document.
Each region will define the following properties for itself when it is created:
- The maximum number of active validators
- The maximum number of "queued" validators
- The maximum unbonding rate (N validators per 100 blocks)
- The post-unbonding stake holding time (measured in blocks)
- The minimum bond amount
- The maximum bond amount
- Cryptographic evidence for proof-of-performance (both for joining and for slashing)
This information will be known by the PoS contract. In order to be considered for becoming a validator, a user invokes the PoS contract as they would any other contract (see Rchain State). When invoking the PoS contract bonding method the user provides the following arguments:
- The region they wish to join
- A form of cryptographic identification (e.g. a public key)
- A purse
- Cryptographic evidence (as needed)
The final two arguments are compared against the requirements of the region specified in the first argument. The identification is used to recognize when messages come from that validator and for the validator to obtain the rewards they earn. If the purse does not contain the correct number of tokens or the evidence is invalid, the bond request is rejected. As a deterrent to DOS attacks, requests with empty purses will be immediately rejected (i.e. no computation will be done to look up region requirements or confirm cryptographic evidence) and tokens will be deduced from the purse if the evidence is invalid for the region. Moreover, no evidence checking is done if the queue for the specified region is already full.
If the purse contents and evidence check out, but there are already the maximum number of active validators in the requested region, then the user is added to the region's queue. The tokens are still taken from the purse and kept in the PoS contract bond holding while the user is in the queue. When an unbonding event occurs in the region, a new validator randomly chosen from the queue becomes active to replace the one which left. Note that since currently active validators and their bonds are stored in the top level namespace, but the weights derived from that information must be used in all namespaces, all blocks in namespaces other than the top must include the hash of the top-level block which contains the current stakes state (in the block proposer's view). Validator weights are derived from the information contained in the parent block; this prevents a validator from changing the consensus on forks which occurred before they joined, as any block they create which points to a block that does not list them as a validator would have 0 weight. In the case of a multi-parent block, all parents must have the same stake state hash.
Unbonding is triggered when the PoS contract is invoked (again in the normal way) with the signature of an existing validator (this signature could be on the hash of the parent of the block after which they want to be unbonded) along with a return channel. On the return channel, an unforgable name is sent, which the now ex-validator can listen on. After the post-unbonding stake holding time has elapsed, a purse containing the ex-validaor's stake is sent on that name, thus allowing the validator to recover their bond. Note that no rewards are distributed at this time, only the exact original stake (minus any slashed amount) is returned. Rewards can be withdrawn from the shard's local PoS contract after unbonding has occurred (see below). The unbonding is successful so long as it does not exceed the unbonding rate specified for the region.
During the post-unbonding stake holding period the validator is not active, but their stake is still held by the PoS contract and they can still be slashed by other validators. The purpose of this holding time is to prevent a variant of the "long range attack" in which a validator "re-writes history" on a separate chain from the main one. If, after a validator unbonds, they get their stake back immediately then they can start producing a different chain off a recent past block where they had stake without fear of being slashed for equivocation because their stake has already been recovered in the main chain. By holding the stake for a period after the validator is no longer active they can still be slashed for attempting a long range attack during that time. If the time is long enough that the network has moved sufficiently far ahead since the validator unbonded then "weak subjectivity" should be enough to combat a long range attack attempted after the holding period.
As mentioned above, when unbonding happens a new validator from the queue will become active if the queue is non-empty.
Slashing is triggered when the PoS contract is invoked with the following arguments:
- ID of the offender (a validator)
- Signature of the accuser (also a validator)
- Offence descriptor
- Cryptographic evidence of the offence
- A purse return channel
Any validator can slash any other validator (including those from other regions) because slashing happens at the top level. If the evidence is accepted then the amount which was deduced from the offender is given to the accuser in a purse via the return channel. If the evidence is invalid then the accusers bond is deduced instead. If a validator's stake drops to 0 then they are automatically unbonded. The following are slashable offences:
- Breach of SLA (as defined by the specific region; the evidence to prove performance failure is also region specific)
- Not following the rules
- Producing an invalid block: evidence = signed message from offender sending that block
- Equivocation (as defined in CBC Casper protocols): evidence = pair of signed messages from offender which cannot be causally ordered by justifications
Rewards distribution is handled by a local PoS contract. When a validator proposes a block they include an additional transaction which invokes the local PoS contract with their validator identity and the fees from user code, this updates their "reward balance" tracked by the local PoS contract. The update also includes some newly minted tokens in addition to the fees. In the case of multi-parent blocks, the reward balances of the other validators who created parent blocks are also updated based on the fees in those blocks (because those transactions have now joined the new main chain). The function to calculate rewards from fees will have the form
proposing_discount is a function which penalizes a validator from publishing many blocks in a row (i.e. incentivizes building a chain cooperatively with other validators).
An ex-validator can withdraw their rewards from a local PoS contract by invoking it with the following arguments:
- Signature (using the private key corresponding the the public key they were identified by while validating), the signature will likely need to be on a nonce (similar to Ethereum) for security
- A purse return channel
The PoS contract sends a purse on the return channel containing all the rewards that have been accumulated on that ID since the last withdraw. Withdraws can only happen in blocks where the validator is no longer active, i.e. a block which includes a withdraw by a validator who is still listed as active in the block's skate state hash is invalid. Note that a validator can still leverage their own weight to perform a withdraw because weights are based on the parent block, but withdraw eligibility is based on the current block.
- Is it too much of a security risk to allow validators to pick their own regions?
- What will be used as cryptographic evidence for various performance requirements (or performance failures)?
- Is it a good idea to give the tokens from a valid slash to the accuser?
- On the one hand it gives an economic incentive to slash other validators
- But on the other hand it gives an unbonding backdoor. A pair of validators could have an agreement that one slashes the other then returns the stake, allowing an unbond which circumvents the
- What to do with tokens deducted due to failed slash?
- At what rate are new tokens minted in validator rewards? How does this minting interact with the blessed Rev mint contract (which can only exist in a single namespace)?