Automatically merged updates to draft EIP(s) 1011

Hi, I'm a bot! This change was automatically merged because:

 - It only modifies existing draft EIP(s)
 - The PR was approved or written by at least one author of each modified EIP
 - The build is passing
This commit is contained in:
Danny Ryan 2018-05-16 12:06:30 +09:00 committed by EIP Automerge Bot
parent 7b56fab797
commit 46927c516f
1 changed files with 131 additions and 49 deletions

View File

@ -23,11 +23,13 @@ This EIP does not contain safety and liveness proofs or validator implementation
## Glossary
* **epoch**: The span of blocks between checkpoints.
* **epoch**: The span of blocks between checkpoints. Epochs are numbered starting at the hybrid casper fork, incrementing by one at the start of each epoch.
* **finality**: The point at which a block has been decided upon by a client to _never_ revert. Proof of Work does not have the concept of finality, only of further deep block confirmations.
* **checkpoint**: The start block of an epoch. Rather than dealing with every block, Casper FFG only considers checkpoints for finalization.
* **dynasty**: The number of finalized checkpoints in the chain from root to the parent of a block. The dynasty is used to define when a validator starts and ends validating.
* **slash**: The burning of a validator's deposit. Slashing occurs when a validator signs two conflicting messages that violate a slashing condition. For an in-depth discussion of slashing conditions, see the [Casper FFG Paper](https://arxiv.org/abs/1710.09437).
* **checkpoint**: The block/hash under consideration for finality for a given epoch. This block is the _last_ block of the previous epoch. Rather than dealing with every block, Casper FFG only considers checkpoints for finalization. When a checkpoint is explicitly finalized, all ancestor blocks of the checkpoint are implicitly finalized.
* **validator**: A participant in the Casper FFG consensus that has deposited ether in the casper contract and has the responsibility to vote and finalize checkpoints.
* **validator set**: The set of validators in the casper contract at any given time.
* **dynasty**: The number of finalized checkpoints in the chain from root to the parent of a block. The dynasty is used to define when a validator starts and ends validating. The current dynasty only increments when a checkpoint is finalized as opposed to epoch numbers that increment regardless of finality.
* **slash**: The burning of some amount of a validator's deposit along with an immediate logout from the validator set. Slashing occurs when a validator signs two conflicting `vote` messages that violate a slashing condition. For an in-depth discussion of slashing conditions, see the [Casper FFG Paper](https://arxiv.org/abs/1710.09437).
## Motivation
@ -35,7 +37,7 @@ Transitioning the Ethereum network from PoW to PoS has been on the roadmap and i
Until recently, the proper way to make this transition was still an open area of research. In October of 2017 [Casper the Friendly Finality Gadget](https://arxiv.org/abs/1710.09437) was published, solving open questions of economic finality through validator deposits and crypto-economic incentives. For a detailed discussion and proofs of "accountable safety" and "plausible liveness", see the [Casper FFG](https://arxiv.org/abs/1710.09437) paper.
The Casper FFG contract can be layered on top of any block proposal mechanism, providing finality to the underlying chain. This EIP proposes layering FFG on top of the existing PoW block proposal mechanism as a conservative step-wise approach in the transition to full PoS. The new FFG staking mechanism requires minimal changes to the protocol, allowing the Ethereum network to fully test and vet Casper FFG on top of PoW before moving to a validator based block proposal mechanism.
The Casper FFG contract can be layered on top of any block proposal mechanism, providing finality to the underlying chain. This EIP proposes layering FFG on top of the existing PoW block proposal mechanism as a conservative step-wise approach in the transition to full PoS. The new FFG staking mechanism requires minimal changes to the protocol, allowing the Ethereum network to fully test and evaluate Casper FFG on top of PoW before moving to a validator based block proposal mechanism.
## Parameters
@ -43,19 +45,23 @@ The Casper FFG contract can be layered on top of any block proposal mechanism, p
* `CASPER_ADDR`: TBD
* `CASPER_CODE`: see below
* `CASPER_BALANCE`: 1.25e24 wei (1,250,000 ETH)
* `SIGHASHER_ADDR`: TBD
* `SIGHASHER_CODE`: see below
* `MSG_HASHER_ADDR`: TBD
* `MSG_HASHER_CODE`: see below
* `PURITY_CHECKER_ADDR`: TBD
* `PURITY_CHECKER_CODE`: see below
* `NULL_SENDER`: `2**160 - 1`
* `NEW_BLOCK_REWARD`: 6e17 wei (0.6 ETH)
* `REWARD_STEPDOWN_BLOCK_COUNT`: 5.5e5 blocks (~3 months)
* `CASPER_INIT_DATA`: TBD
* `VOTE_BYTES`: `0xe9dc0614`
* `INITIALIZE_EPOCH_BYTES`: `0x5dcffc17`
* `NON_REVERT_MIN_DEPOSIT`: amount in wei configurable by client
### Casper Contract Parameters
* `EPOCH_LENGTH`: 50 blocks
* `WITHDRAWAL_DELAY`: 15,000 epochs
* `WARM_UP_PERIOD`: 1.8e5 blocks (~1 month)
* `WITHDRAWAL_DELAY`: 1.5e4 epochs
* `DYNASTY_LOGOUT_DELAY`: 700 dynasties
* `BASE_INTEREST_FACTOR`: 7e-3
* `BASE_PENALTY_FACTOR`: 2e-7
@ -66,29 +72,46 @@ The Casper FFG contract can be layered on top of any block proposal mechanism, p
#### Deploying Casper Contract
If `block.number == HYBRID_CASPER_FORK_BLKNUM`, then when processing the block, before processing any transactions:
If `block.number == HYBRID_CASPER_FORK_BLKNUM`, then when processing the block before processing any transactions:
* set the code of `SIGHASHER_ADDR` to `SIGHASHER_CODE`
* set the code of `MSG_HASHER_ADDR` to `MSG_HASHER_CODE`
* set the code of `PURITY_CHECKER_ADDR` to `PURITY_CHECKER_CODE`
* set the code of `CASPER_ADDR` to `CASPER_CODE`
* set balance of `CASPER_ADDR` to `CASPER_BALANCE`
#### Initialize Epochs
Then execute a `CALL` with the following parameters before executing any normal block transactions:
If `block.number >= HYBRID_CASPER_FORK_BLKNUM` and `block.number % EPOCH_LENGTH == 0`, execute a `CALL` with the following parameters before executing any normal block transactions:
* `SENDER`: NULL_SENDER
* `SENDER`: `NULL_SENDER`
* `GAS`: 3141592
* `TO`: CASPER_ADDR
* `TO`: `CASPER_ADDR`
* `VALUE`: 0
* `NONCE`: 0
* `GASPRICE`: 0
* `DATA`: `0x5dcffc17` followed by the 32-byte encoding of `block.number // EPOCH_LENGTH`
* `DATA`: `CASPER_INIT_DATA`
This `CALL` utilizes no gas and does not increment the nonce of `NULL_SENDER`
#### Initialize Epochs
If `block.number >= (HYBRID_CASPER_FORK_BLKNUM + WARM_UP_PERIOD)` and `block.number % EPOCH_LENGTH == 0`, execute a `CALL` with the following parameters before executing any normal block transactions:
* `SENDER`: `NULL_SENDER`
* `GAS`: 3141592
* `TO`: `CASPER_ADDR`
* `VALUE`: 0
* `NONCE`: 0
* `GASPRICE`: 0
* `DATA`: `INITIALIZE_EPOCH_BYTES` followed by the 32-byte encoding of `floor(block.number / EPOCH_LENGTH)`
This `CALL` utilizes no gas and does not increment the nonce of `NULL_SENDER`
#### Casper Votes
A `vote` transaction is defined as a transaction with the follow parameters:
* `TO`: `CASPER_ADDR`
* `DATA`: Begins with `VOTE_BYTES`
If `block.number >= HYBRID_CASPER_FORK_BLKNUM`, then:
* A valid `vote` transaction to `CASPER_ADDR` must satisfy each of the following:
@ -97,45 +120,79 @@ If `block.number >= HYBRID_CASPER_FORK_BLKNUM`, then:
* When producing and validating a block, when handling `vote` transactions to `CASPER_ADDR`:
* Only include "valid" `vote` transactions as defined above
* Place all `vote` transactions at the end of the block
* Track total gas used by votes separately from total gas used by normal transactions
* The `vote_gas_limit` is equal to the `block_gas_limit`
* Total gas used by votes cannot exceed the `vote_gas_limit`
* Track cumulative gas used by votes separately from cumulative gas used by normal transactions via `vote_gas_used`
* Total `vote_gas_used` of `vote` transactions cannot exceed the `block_gas_limit`, independent of gas used by normal block transactions
* When applying `vote` transactions to `CASPER_ADDR` to vm state:
* Set sender to `NULL_SENDER`
* Count gas of `vote` toward the `vote_gas_limit`
* Do not count gas of `vote` toward the `block_gas_limit`
* Count gas of `vote` toward `vote_gas_used`
* Do not count gas of `vote` toward the normal `gas_used`. For all `vote` transaction receipts, cumulative gas used is equal to last non-`vote` transaction receipt
* Do not increment the nonce of `NULL_SENDER`
* All unsuccessful `vote` transactions to `CASPER_ADDR` are invalid and must not be included in the block
#### Fork Choice
If `block.number >= HYBRID_CASPER_FORK_BLKNUM`, the chain scoring rule is the following:
#### Fork Choice and Finalization
If `block.number >= HYBRID_CASPER_FORK_BLKNUM`, the fork choice rule is the logic represented by the following pseudocode. Note that options `--casper-fork-choice` and `--exclude` are discussed below in "Client Settings".
```python
highest_justified_epoch * 10**40 + total_difficulty
def handle_block(new_block):
if not is_new_head(new_block):
return
set_head(new_block)
if --casper-fork-choice is on:
check_and_finalize_new_checkpoint(new_block)
def is_new_head(new_block):
if --casper-fork-choice is off
# old pure PoW chain scoring rule
return new_block.total_difficuty > current_head.total_difficulty
if new_block is in --exclude list or one of its descendants
return false
# don't revert finalized blocks
if db.last_finalized_block is not in new_block.ancestors:
return false
# new casper chain scoring rule
return highest_justified_epoch(new_block) * 10**40 + new_block.total_difficuty >
highest_justified_epoch(current_head) * 10**40 + current_head.total_difficulty
def highest_justified_epoch(block):
casper = block.post_state.casper_contract
return casper.highest_justified_epoch(NON_REVERT_MIN_DEPOSITS)
def check_and_finalize_new_checkpoint(new_block):
casper = new_block.post_state.casper_contract
# If no finalized blocks, db.last_finalized_epoch initialized to -1
finalized_epoch = casper.highest_finalized_epoch(NON_REVERT_MIN_DEPOSITS)
if finalized_epoch > db.last_finalized_epoch:
finalized_hash = casper.checkpoint_hashes(finalized_epoch)
# ensure not trivially finalized
if finalized_hash == b'\x00' * 32:
return
db.last_finalized_epoch = finalized_epoch
db.last_finalized_block = finalized_hash
```
With the additional rule of _never reverting finalized blocks_.
The new chain scoring rule queries the casper contract to find the highest justified epoch that meets the client's minimum deposit requirement (`NON_REVERT_MIN_DEPOSITS`). The `10**40` multiplier ensures that the justified epoch takes precendence over block mining difficulty. `total_difficulty` only serves as a tie breaker if the two blocks in question have an equivalent `highest_justified_epoch`.
_Note_: If the client has no justified checkpoints, `highest_justified_epoch = 0`.
_Note_: If the client has no justified checkpoints, the contract returns `highest_justified_epoch` as `0` essentially reverting the fork choice rule to pure PoW.
#### Justification and Finalization
A client considers a checkpoint finalized if during an epoch, the previous epoch's checkpoint is finalized within the casper contract:
```python
casper.last_finalized_epoch() == casper.current_epoch() - 1
```
When assessing a new block as the chain's head, clients must _never revert finalized blocks_ as seen by the code commented as "don't revert finalized blocks".
A client considers a checkpoint justified if during an epoch, the current epoch's checkpoint is justified within the casper contract:
```python
casper.last_justified_epoch() == casper.current_epoch()
```
When a new block is added as the chain's head, clients then check for a new finalized block. This is handled by the `check_and_finalized_new_checkpoint(new_block)` method above. If the highest finalized epoch in the casper contract is greater than the previous finalized epoch, then the client finalizes the block with the hash `casper.checkpoint_hashes(finalized_epoch)`, storing this block and the related epoch number in the client database as finalized.
Clients should only consider checkpoints justified or finalized if deposits were greater than `NON_REVERT_MIN_DEPOSIT` _during the epoch in question_\*:
```python
casper_state_during_epoch_in_question.total_curdyn_deposits_scaled() > NON_REVERT_MIN_DEPOSIT
casper_state_during_epoch_in_question.total_prevdyn_deposits_scaled() > NON_REVERT_MIN_DEPOSIT
```
Clients only consider checkpoints justified or finalized if deposits were greater than `NON_REVERT_MIN_DEPOSIT` _during the epoch in question_. This logic is encapsulated in `casper.highest_justified_epoch(NON_REVERT_MIN_DEPOSIT)` and `casper.highest_finalized_epoch(NON_REVERT_MIN_DEPOSIT)`, respectively.
\* When assessing the size of total deposits for epoch finalization and justification, use `total_*dyn_deposits_scaled` from the state of the VM during the epoch. For example, if assessing whether epoch 10 should be finalized and epoch 10 occurred from block 500 to 550, then get the `total_*dyn_deposits_scaled` during that 500 to 550 block range rather than during the current epoch.
#### Block Reward
@ -160,10 +217,10 @@ else:
The mechanics and responsibilities of validators are not specified in this EIP because they rely upon network transactions to the contract at `CASPER_ADDR` rather than on protocol level implementation and changes.
See the [Validator Implementation Guide](https://github.com/ethereum/casper/blob/master/VALIDATOR_GUIDE.md) for validator details.
#### SIGHASHER_CODE
#### MSG_HASHER_CODE
The source code for `SIGHASHER_CODE` is located [here](https://github.com/ethereum/casper/blob/master/casper/contracts/sighash.se.py).
The source is to be migrated to Vyper LLL before its bytecode is finalized for this EIP.
The source code for `MSG_HASHER_CODE` is located [here](https://github.com/ethereum/casper/blob/master/casper/contracts/msg_hash.se.py).
The source is to be migrated to Vyper LLL before the bytecode is finalized for this EIP.
The EVM init code is:
```
@ -178,7 +235,7 @@ TBD
#### PURITY_CHECKER_CODE
The source code for `PURITY_CHECKER_CODE` is located [here](https://github.com/ethereum/research/blob/master/impurity/check_for_impurity.se).
The source is to be migrated to Vyper LLL before its bytecode is finalized for this EIP.
The source is to be migrated to Vyper LLL before the bytecode is finalized for this EIP.
The EVM init code is:
```
@ -194,7 +251,7 @@ TBD
The source code for `CASPER_CODE` is located at
[here](https://github.com/ethereum/casper/blob/master/casper/contracts/simple_casper.v.py).
The contract is to be formally verified and further tested before its bytecode is finalized for this EIP.
The contract is to be formally verified and further tested before the bytecode is finalized for this EIP.
The EVM init code with the above specified params is:
```
@ -268,9 +325,10 @@ def surrounds(vote_msg_1, vote_msg_2):
def violates_slashing_condition(vote_msg_1, vote_msg_2):
return same_target_epoch(vote_msg_1, vote_msg_2) or surrounds(vote_msg_1, vote_msg_2)
```
This setting is to be used for clients that wish to monitor vote transactions for slashing conditions. If a slashing condition is found, the client creates and sends a transaction to `slash` on the casper contract. The first transaction to include the slashing condition proof slashes the validator in question and sends a 4% finder's fee to the transaction sender.
Suggested default disabled. Block producers would be the most likely to want to enable this flag as they are likely to frontrun anyone else that submit the slashing tx to grab the reward. Because block producers are likely to front-run, others would probably leave off so they don't submit a tx that will be included, cost them gas, but be too late to get the reward
The casper contract also provides a helper method `slashable(vote_msg_1, vote_msg_2)` to check if two votes violate a slashing condition. Clients should use the above pseudocode in combination with `casper.slashable()` as a final check when deciding whether to submit a `slash` to the contract.
The `--monitor-votes` setting is to be used for clients that wish to monitor vote transactions for slashing conditions. If a slashing condition is found, the client creates and sends a transaction to `slash` on the casper contract. The first transaction to include the slashing condition proof slashes the validator in question and sends a 4% finder's fee to the transaction sender.
## Rationale
@ -281,9 +339,28 @@ The finality gadget is designed to minimize changes across clients. For this rea
Most other decisions were made to minimize changes across clients. For example, it would be possible to allow `CASPER_ADDR` to mint Ether each time it paid rewards (as compared to creating the contract with `CASPER_BALANCE`), but this would be more invasive and error-prone than relying on existing EVM mechanics.
#### Deploying Casper Contract
The `MSG_HASHER_CODE` and `PURITY_CHECKER_CODE` both do not require any initialization so the EVM bytecode can simply be placed at `MSG_HASHER_ADDR` and `PURITY_CHECKER_ADDR`. On the other hand, the casper contract _does_ require passing in parameters and initialization of state. This initialization would normally occur by the EVM init code interacting with the CREATE opcode. Due to the nature of this contract being deployed outside of normal block transactions and to a particular address, the EVM init code/CREATE method requires client specific "hacks" to make it work. For simplicity of specifying across clients, the EVM bytecode -- `CASPER_CODE` -- is placed at `CASPER_ADDR` followed by an explicit `CALL` to a one-time `init` method on the casper contract. `init` handles all of the logic that a constructor normally would, accepting contract parameters as arguments and setting initial variable values, and can only be run _once_.
`CASPER_INIT_DATA` is composed of the the byte signature of the `init` method of the casper contract concatenated with the 32-byte encodings of the following variables in the following order:
* `EPOCH_LENGTH`
* `WITHDRAWAL_DELAY`
* `DYNASTY_LOGOUT_DELAY`
* `MSG_HASHER_ADDR`
* `PURITY_CHECKER_ADDR`
* `BASE_INTEREST_FACTOR`
* `BASE_PENALTY_FACTOR`
* `MIN_DEPOSIT_SIZE`
The entirety of this data is provided as a bytestring -- `CASPER_INIT_DATA` -- to reduce the chance of encoding errors across clients, especially regarding fixed decimal types which are new in vyper and not yet supported by all clients.
#### Casper Contract Params
`EPOCH_LENGTH` is set to 50 blocks as a balance between time to finality and message overhead.
`WARM_UP_PERIOD` is set to 1.8e5 blocks to provide validators with an approximate 1 month period to make initial deposits before full contract functionality and voting begin. This helps prevent degenerate cases such as having very few or even just one validator in the initial dynasty. This 1 month period also gives the network time to observe on the order of how many validators will initially be participating in consensus. If for some reason there is an unexpectedly low turnout, the community might choose to delay validation and consider design alternatives.
`WITHDRAWAL_DELAY` is set to 15000 epochs to freeze a validator's funds for approximately 4 months after logout. This allows for at least a 4 month window to identify and slash a validator for attempting to finalize two conflicting checkpoints. This also defines the window of time with which a client must log on to sync the network due to weak subjectivity.
`DYNASTY_LOGOUT_DELAY` is set to 700 dynasties to prevent immediate logout in the event of an attack from being a viable strategy.
@ -294,6 +371,11 @@ Most other decisions were made to minimize changes across clients. For example,
`MIN_DEPOSIT_SIZE` is set to 1500 ETH to form a natural upper bound on the total number of validators, bounding the overhead due to `vote` messages. Using formulas found [here](https://medium.com/@VitalikButerin/parametrizing-casper-the-decentralization-finality-time-overhead-tradeoff-3f2011672735) under "From validator count to minimum staking ETH", we estimate that with 1500 ETH minimum deposit at an assumed ~10M in total deposits there will be approximately 900 validators at any given time. `vote`s are only sent after the first quarter of an epoch so 900 votes have to fit into 37 blocks or ~24 `vote`s per block. We have experimented with more dynamic models for `MIN_DEPOSIT_SIZE`, but these tend to introduce significant complexities and without data from a live network seem to be premature optimizations.
#### Initialize Epochs
The call to the method at `INITIALIZE_EPOCH_BYTES` at `CASPER_ADDR` at the start of each epoch is a call to the `initialize_epoch` method in the casper contract. This method can only be called once per epoch and is guaranteed by the protocol to be called at the start block of each epoch by `NULL_SENDER`. This method performs a number of bookkeeping tasks around incrementing variables, updating rewards, etc.
Any call to this method fails prior to the end of the `WARM_UP_PERIOD`. Thus the protocol does not begin executing `initialize_epoch` calls until `block.number >= HYBRID_CASPER_FORK_BLKNUM + WARM_UP_PERIOD`.
#### Issuance
A fixed amount of 1.25M ETH was chosen as `CASPER_BALANCE` to fund the casper contract. This gives the contract enough runway to operate for approximately 2 years (assuming ~10M ETH in validator deposits). Acting similarly to the "difficulty bomb", this "funding crunch" forces the network to hardfork in the relative near future to further fund the contract. This future hardfork is an opportunity to upgrade the contract and transition to full PoS.
@ -313,7 +395,7 @@ Below is a table of deposit sizes with associated annual interest rate and appro
#### Gas Changes
Normal block transactions cannot affect casper `vote` validation results, but casper `vote` validation results can affect normal block transaction execution. Due to this asymmetrical relationship, `vote` transactions can be processed in parallel with normal block transactions if `vote` transactions are placed after all normal block transactions. Because `vote` transactions can be processed in parallel to normal block transactions, `vote` transactions cost 0 gas for validators, ensuring that validators can submit votes even in highly congested or high gas-price periods.
`vote_gas_limit` is introduced to ensure that `vote` transactions do not put an undue burden on block processing. The additional overhead from `vote` transactions is capped at the overhead of normal block transactions so that when run in parallel, neither sets of transactions exceeds the overhead defined by the `block_gas_limit`.
`vote_gas_used` is introduced to ensure that `vote` transactions do not put an undue burden on block processing. The additional overhead from `vote` transactions is capped at the same limit as normal block transactions so that, when run in parallel, neither sets of transactions exceeds the overhead defined by the `block_gas_limit`.
The call to `initialize_epoch` at the beginning of each epoch requires 0 gas so that this protocol state transition does not take any gas allowance away from normal transactions.