Fix `is_genesis_trigger` and add test case
This commit is contained in:
parent
b36ffd5c41
commit
ac34221f55
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
Loading…
Reference in New Issue