Fix `is_genesis_trigger` and add test case

This commit is contained in:
Hsiao-Wei Wang 2019-06-21 16:30:31 -06:00
parent b36ffd5c41
commit ac34221f55
No known key found for this signature in database
GPG Key ID: 95B070122902DEA4
4 changed files with 41 additions and 8 deletions

View File

@ -17,6 +17,8 @@ MIN_PER_EPOCH_CHURN_LIMIT: 4
CHURN_LIMIT_QUOTIENT: 65536 CHURN_LIMIT_QUOTIENT: 65536
# See issue 563 # See issue 563
SHUFFLE_ROUND_COUNT: 90 SHUFFLE_ROUND_COUNT: 90
# `2**16` (= 65,536)
GENESIS_ACTIVE_VALIDATOR_COUNT: 65536
# Deposit contract # Deposit contract

View File

@ -16,6 +16,8 @@ MIN_PER_EPOCH_CHURN_LIMIT: 4
CHURN_LIMIT_QUOTIENT: 65536 CHURN_LIMIT_QUOTIENT: 65536
# [customized] Faster, but unsecure. # [customized] Faster, but unsecure.
SHUFFLE_ROUND_COUNT: 10 SHUFFLE_ROUND_COUNT: 10
# [customized]
GENESIS_ACTIVE_VALIDATOR_COUNT: 100
# Deposit contract # Deposit contract

View File

@ -194,6 +194,7 @@ These configurations are updated for releases, but may be out of sync during `de
| `MIN_PER_EPOCH_CHURN_LIMIT` | `2**2` (= 4) | | `MIN_PER_EPOCH_CHURN_LIMIT` | `2**2` (= 4) |
| `CHURN_LIMIT_QUOTIENT` | `2**16` (= 65,536) | | `CHURN_LIMIT_QUOTIENT` | `2**16` (= 65,536) |
| `SHUFFLE_ROUND_COUNT` | `90` | | `SHUFFLE_ROUND_COUNT` | `90` |
| `GENESIS_ACTIVE_VALIDATOR_COUNT` | `2**16` (= 65,536) |
* For the safety of crosslinks `TARGET_COMMITTEE_SIZE` exceeds [the recommended minimum committee size of 111](https://vitalik.ca/files/Ithaca201807_Sharding.pdf); with sufficient active validators (at least `SLOTS_PER_EPOCH * TARGET_COMMITTEE_SIZE`), the shuffling algorithm ensures committee sizes of at least `TARGET_COMMITTEE_SIZE`. (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) * For the safety of crosslinks `TARGET_COMMITTEE_SIZE` exceeds [the recommended minimum committee size of 111](https://vitalik.ca/files/Ithaca201807_Sharding.pdf); with sufficient active validators (at least `SLOTS_PER_EPOCH * TARGET_COMMITTEE_SIZE`), the shuffling algorithm ensures committee sizes of at least `TARGET_COMMITTEE_SIZE`. (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.)
@ -1134,10 +1135,11 @@ Before genesis has been triggered and whenever the deposit contract emits a `Dep
* `deposits` is the list of all deposits, ordered chronologically, up to and including the deposit triggering the latest `Deposit` log * `deposits` is the list of all deposits, ordered chronologically, up to and including the deposit triggering the latest `Deposit` log
* `timestamp` is the Unix timestamp in the Ethereum 1.0 block that emitted the latest `Deposit` log * `timestamp` is the Unix timestamp in the Ethereum 1.0 block that emitted the latest `Deposit` log
When `is_genesis_trigger(deposits, timestamp) is True` for the first time let: When `is_genesis_trigger(deposits, timestamp, deposit_root) is True` for the first time let:
* `genesis_deposits = deposits` * `genesis_deposits = deposits`
* `genesis_time = timestamp - timestamp % SECONDS_PER_DAY + 2 * SECONDS_PER_DAY` where `SECONDS_PER_DAY = 86400` * `genesis_time = timestamp - timestamp % SECONDS_PER_DAY + 2 * SECONDS_PER_DAY` where `SECONDS_PER_DAY = 86400`
* `deposit_root` is the tree root of the given `deposits`
* `genesis_eth1_data` be the object of type `Eth1Data` where: * `genesis_eth1_data` be the object of type `Eth1Data` where:
* `genesis_eth1_data.block_hash` is the Ethereum 1.0 block hash that emitted the log for the last deposit in `deposits` * `genesis_eth1_data.block_hash` is the Ethereum 1.0 block hash that emitted the log for the last deposit in `deposits`
* `genesis_eth1_data.deposit_root` is the deposit root for the last deposit in `deposits` * `genesis_eth1_data.deposit_root` is the deposit root for the last deposit in `deposits`
@ -1146,20 +1148,19 @@ When `is_genesis_trigger(deposits, timestamp) is True` for the first time let:
*Note*: The function `is_genesis_trigger` has yet to be agreed by the community, and can be updated as necessary. We define the following testing placeholder: *Note*: The function `is_genesis_trigger` has yet to be agreed by the community, and can be updated as necessary. We define the following testing placeholder:
```python ```python
def is_genesis_trigger(deposits: List[Deposit], timestamp: uint64) -> bool: def is_genesis_trigger(deposits: List[Deposit], timestamp: uint64, deposit_root: Hash) -> bool:
# Process deposits # Process deposits
state = BeaconState() state = BeaconState()
for deposit in deposits: for index, deposit in enumerate(deposits):
process_deposit(state, deposit) process_deposit(state, deposit, deposit_index=index, deposit_root=deposit_root)
# Count active validators at genesis # Count active validators at genesis
active_validator_count = 0 active_validator_count = 0
for validator in state.validator_registry: for validator in state.validators:
if validator.effective_balance == MAX_EFFECTIVE_BALANCE: if validator.effective_balance == MAX_EFFECTIVE_BALANCE:
active_validator_count += 1 active_validator_count += 1
# Check effective balance to trigger genesis # Check effective balance to trigger genesis
GENESIS_ACTIVE_VALIDATOR_COUNT = 2**16
return active_validator_count == GENESIS_ACTIVE_VALIDATOR_COUNT return active_validator_count == GENESIS_ACTIVE_VALIDATOR_COUNT
``` ```
@ -1730,19 +1731,21 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
##### Deposits ##### Deposits
```python ```python
def process_deposit(state: BeaconState, deposit: Deposit, deposit_index: Optional[uint64]=None) -> None: def process_deposit(state: BeaconState, deposit: Deposit, deposit_index: Optional[uint64]=None, deposit_root: Optional[Hash]=None) -> None:
""" """
Process an Eth1 deposit, registering a validator or increasing its balance. Process an Eth1 deposit, registering a validator or increasing its balance.
""" """
if deposit_index is None: if deposit_index is None:
deposit_index = state.eth1_deposit_index deposit_index = state.eth1_deposit_index
if deposit_root is None:
deposit_root = state.eth1_data.deposit_root
# Verify the Merkle branch # Verify the Merkle branch
assert verify_merkle_branch( assert verify_merkle_branch(
leaf=hash_tree_root(deposit.data), leaf=hash_tree_root(deposit.data),
proof=deposit.proof, proof=deposit.proof,
depth=DEPOSIT_CONTRACT_TREE_DEPTH, depth=DEPOSIT_CONTRACT_TREE_DEPTH,
index=deposit_index, index=deposit_index,
root=state.eth1_data.deposit_root, root=deposit_root,
) )
# Deposits must be processed in order # Deposits must be processed in order

View File

@ -4,6 +4,32 @@ from eth2spec.test.helpers.deposits import (
) )
@with_phases(['phase0'])
@spec_state_test
def test_is_genesis_trigger_false(spec, state):
deposit_count = 2
genesis_deposits, deposit_root = prepare_genesis_deposits(spec, deposit_count)
genesis_time = 1234
is_triggered = spec.is_genesis_trigger(genesis_deposits, genesis_time, deposit_root)
assert is_triggered is False
yield is_triggered
@with_phases(['phase0'])
@spec_state_test
def test_is_genesis_trigger_true(spec, state):
deposit_count = spec.GENESIS_ACTIVE_VALIDATOR_COUNT
genesis_deposits, deposit_root = prepare_genesis_deposits(spec, deposit_count)
genesis_time = 1234
is_triggered = spec.is_genesis_trigger(genesis_deposits, genesis_time, deposit_root)
assert is_triggered is True
yield is_triggered
@with_phases(['phase0']) @with_phases(['phase0'])
@spec_state_test @spec_state_test
def test_genesis(spec, state): def test_genesis(spec, state):