After an additional two months of work after the release of the first python proof of concept release of Serenity, I am pleased to announce that Serenity PoC2 is now available. Although the release continues to be far from a testnet-ready client, much less a production-ready one, PoC2 brings with it a number of important improvements. First and foremost, the goal of PoC2 was to implement the complete protocol, including the basic corner cases (slashing bets and deposits), so as to make sure that we have a grasp of every detail of the protocol and see it in action even if in a highly restricted test environment. This goal has been achieved. Whereas PoC1 included only the bare minimum functionality needed to make Casper and EIP 101 run, PoC2 includes essentially the full Casper/Serenity protocol, EIP 101 and 105 included.
The specific features that can be found in PoC2 that were not available in PoC1 are as follows:
- EIP 105 implementation – EIP 105 is the “sharding scaffolding” EIP, which will allow processing Ethereum transactions to be somewhat parallelized, and will set the stage for a later sharding scheme (which is yet to be determined). It uses the binary tree sharding mechanism described here to allow transactions to specify an “activity range” which restricts the addresses that transaction execution can touch, guaranteeing that sets of transactions with disjoint activity ranges can be processed in parallel. It also introduces SSTOREEXT and SLOADEXT opcodes to allow contracts to access storage of the same address in other shards (provided that the target shard is within the activity range); this mechanism essentially means that the binary shard tree serves as a super-contract sharding mechanism and a sub-contract sharding mechanism at the same time.
- Gas checking – the algorithm that pattern-matches a transaction to make sure that it correctly pays gas. Currently, this is accomplished by only accepting transactions going to accounts that have a particular piece of “mandatory account code“, which gives the account holder freedom to specify two pieces of code: the checker code and the runner code. Checker code is meant to perform quick checks such as signature and nonce verification; the pattern-matching algorithm gives a maximum of 250,000 gas for the checker code to run. Runner code is meant to perform any expensive operations that the transaction needed to carry out (eg. calling another contract with more than 250,000 gas). The main practical consequence of this is that users will be able to pay for gas directly out of contracts (eg. multisig wallets, ring signature mixers, etc) and will not need to separately always have a small amount of ETH in their primary account in order to pay for gas – as long as the gas payment from the contract is made within 250,000 gas all is good.
- Ring signature mixer – part of the test.py script now includes creating an instance of a ring signature verification contract which is designed as a mixer: five users send their public keys in alongside a deposit of 0.1 ETH, and then withdraw the 0.1 ETH specifying the address with a linkable ring signature, simultaneously guaranteeing that (i) everyone who deposited 0.1 ETH will be able to withdraw 0.1 ETH exactly once, and (ii) it’s impossible to tell which withdrawal corresponds to which deposit. This is implemented in a way that is compliant with the gas checker, providing the key advantage that the transaction withdrawing the 0.1 ETH does not need to be sent from an additional account that pays gas (something which a ring signature implementation on top of the current ethereum would need to do, and which causes a potential privacy leak at the time that you transfer the ETH to that account to pay for the gas); instead, the withdrawal transaction can simply be sent in by itself, and the gas checker algorithm can verify that the signature is correct and that the mixer will pay the miner a fee if the withdrawal transaction gets included into a block.
- More precise numbers on interest rates and scoring rule parameters – the scoring rule (ie. the mechanism that determines how much validators get paid based on how they bet) is now a linear combination of a logarithmic scoring rule and a quadratic scoring rule, and the parameters are such that: (i) betting absolutely correctly immediately and with maximal “bravery” (willingness to converge to 100% quickly) on both blocks and stateroots will get you an expected reward of ~97.28 parts per billion per block, or 50.58% base annual return, (ii) there is a penalty of 74 parts per billion per block, or ~36.98% annual, that everyone pays, hence the expected net return from betting perfectly is ~22 parts per billion per block, or ~10% annual. Betting absolutely incorrectly (ie. betting with maximum certainty and being wrong) on any single block or state root will destroy >90% of your deposit, and betting somewhat incorrectly will cause a much less extreme but still negative return. These parameters will continue to be adjusted so as to make sure that realistic validators will be able to be reasonably profitable.
- More precise validator induction rules – maximum 250 validators, minimum ether amount starts off at 1250 ETH and goes up hyperbolically with the formula min = 1250 * 250 / (250 – v) where v is the current active number of validators (ie. if there are 125 validators active, the minimum becomes 2500 ETH, if there are 225 validators active it becomes 12500 ETH, if there are 248 validators active it becomes 156250 ETH). When you are inducted, you can make bets and earn profits for up to 30 million seconds (~1 year), and after that point a special penalty of 100 parts per billion per block starts getting tacked on, making further validation unprofitable; this forces validator churn.
- New precompiles including ECADD and ECMUL (critical for ring signatures), MODEXP, RLP decoding and the “gas deposit contract” (a mechanism used in the mandatory account code to pay for gas; theoretically it could be written in EVM code if need be but there may be efficiency concerns with that)
- Rearchitecting of LOG and CREATE as precompiles – the opcodes still exist for backwards compatibility purposes, but they simply call the precompile addresses. This is a further move in the direction of “abstraction”.
- New mechanism for betting directly on state roots
- Logic for detecting and slashing double bets and double blocks
- Logic for coming to consensus at a height even if a validator produced multiple blocks at that height
The protocol decisions made here are by no means final; many of them are still actively being debated within the research channels. The next few rounds of PoC releases will thus move toward creating something resembling a Serenity node implementation, alongside a proper p2p networking layer, with the eventual goal of running a Serenity testnet between multiple computers; at the same time, our research team will continue hammering away at the finer details of the protocol and make sure that every single protocol decision is made correctly and well justified.
Additionally, we will be coming out with more accessible materials on the Casper protocol specification and design rationale in the next few weeks, covering both the broad consensus-by-bet concept as well as specific design decisions ranging from validator induction rules to betting mechanisms and block proposer selection.