Merge branch 'v011x' into fix-memoization

This commit is contained in:
protolambda 2020-03-23 21:06:58 +01:00
commit c00d8e30ad
No known key found for this signature in database
GPG Key ID: EC89FDBB2B4C7623
6 changed files with 66 additions and 14 deletions

View File

@ -996,10 +996,11 @@ def get_beacon_proposer_index(state: BeaconState) -> ValidatorIndex:
```python
def get_total_balance(state: BeaconState, indices: Set[ValidatorIndex]) -> Gwei:
"""
Return the combined effective balance of the ``indices``. (1 Gwei minimum to avoid divisions by zero.)
Return the combined effective balance of the ``indices``.
``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
Math safe up to ~10B ETH, afterwhich this overflows uint64.
"""
return Gwei(max(1, sum([state.validators[index].effective_balance for index in indices])))
return Gwei(max(EFFECTIVE_BALANCE_INCREMENT, sum([state.validators[index].effective_balance for index in indices])))
```
#### `get_total_active_balance`
@ -1008,6 +1009,7 @@ def get_total_balance(state: BeaconState, indices: Set[ValidatorIndex]) -> Gwei:
def get_total_active_balance(state: BeaconState) -> Gwei:
"""
Return the combined effective balance of the active validators.
Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
"""
return get_total_balance(state, set(get_active_validator_indices(state, get_current_epoch(state))))
```
@ -1289,6 +1291,10 @@ def get_unslashed_attesting_indices(state: BeaconState,
```python
def get_attesting_balance(state: BeaconState, attestations: Sequence[PendingAttestation]) -> Gwei:
"""
Return the combined effective balance of the set of unslashed validators participating in ``attestations``.
Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
"""
return get_total_balance(state, get_unslashed_attesting_indices(state, attestations))
```

View File

@ -404,12 +404,12 @@ Set `attestation.data = attestation_data` where `attestation_data` is the `Attes
##### Aggregate signature
Set `attestation.signature = signed_attestation_data` where `signed_attestation_data` is obtained from:
Set `attestation.signature = attestation_signature` where `attestation_signature` is obtained from:
```python
def get_signed_attestation_data(state: BeaconState, attestation: IndexedAttestation, privkey: int) -> BLSSignature:
domain = get_domain(state, DOMAIN_BEACON_ATTESTER, attestation.data.target.epoch)
signing_root = compute_signing_root(attestation.data, domain)
def get_attestation_signature(state: BeaconState, attestation_data: AttestationData, privkey: int) -> BLSSignature:
domain = get_domain(state, DOMAIN_BEACON_ATTESTER, attestation_data.target.epoch)
signing_root = compute_signing_root(attestation_data, domain)
return bls.Sign(privkey, signing_root)
```

View File

@ -72,6 +72,14 @@ def default_activation_threshold(spec):
return spec.MAX_EFFECTIVE_BALANCE
def zero_activation_threshold(spec):
"""
Helper method to use 0 gwei as the activation threshold for state creation for tests.
Usage: `@with_custom_state(threshold_fn=zero_activation_threshold, ...)`
"""
return 0
def default_balances(spec):
"""
Helper method to create a series of default balances.
@ -107,6 +115,14 @@ def misc_balances(spec):
return balances
def low_single_balance(spec):
"""
Helper method to create a single of balance of 1 Gwei.
Usage: `@with_custom_state(balances_fn=low_single_balance, ...)`
"""
return [1]
def single_phase(fn):
"""
Decorator that filters out the phases data.

View File

@ -39,7 +39,7 @@ def build_attestation_data(spec, state, slot, index):
)
def get_valid_attestation(spec, state, slot=None, index=None, signed=False):
def get_valid_attestation(spec, state, slot=None, index=None, empty=False, signed=False):
if slot is None:
slot = state.slot
if index is None:
@ -59,7 +59,8 @@ def get_valid_attestation(spec, state, slot=None, index=None, signed=False):
aggregation_bits=aggregation_bits,
data=attestation_data,
)
fill_aggregate_attestation(spec, state, attestation)
if not empty:
fill_aggregate_attestation(spec, state, attestation)
if signed:
sign_attestation(spec, state, attestation)
return attestation

View File

@ -292,14 +292,12 @@ def test_bad_source_root(spec, state):
@with_all_phases
@spec_state_test
def test_empty_aggregation_bits(spec, state):
attestation = get_valid_attestation(spec, state)
attestation = get_valid_attestation(spec, state, empty=True)
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
attestation.aggregation_bits = Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE](
assert attestation.aggregation_bits == Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE](
*([0b0] * len(attestation.aggregation_bits)))
sign_attestation(spec, state, attestation)
yield from run_attestation_processing(spec, state, attestation)

View File

@ -1,6 +1,7 @@
from eth2spec.test.context import (
spec_state_test, with_all_phases, spec_test,
misc_balances, with_custom_state,
low_single_balance, zero_activation_threshold,
single_phase,
)
from eth2spec.test.helpers.state import (
@ -58,12 +59,12 @@ def test_genesis_epoch_full_attestations_no_rewards(spec, state):
assert state.balances[index] == pre_state.balances[index]
def prepare_state_with_full_attestations(spec, state):
def prepare_state_with_full_attestations(spec, state, empty=False):
attestations = []
for slot in range(spec.SLOTS_PER_EPOCH + spec.MIN_ATTESTATION_INCLUSION_DELAY):
# create an attestation for each slot in epoch
if slot < spec.SLOTS_PER_EPOCH:
attestation = get_valid_attestation(spec, state, signed=True)
attestation = get_valid_attestation(spec, state, empty=empty, signed=True)
attestations.append(attestation)
# fill each created slot in state after inclusion delay
if slot - spec.MIN_ATTESTATION_INCLUSION_DELAY >= 0:
@ -150,6 +151,20 @@ def test_full_attestations_misc_balances(spec, state):
brs[br] = state.validators[index].effective_balance
@with_all_phases
@spec_test
@with_custom_state(balances_fn=low_single_balance, threshold_fn=zero_activation_threshold)
@single_phase
def test_full_attestations_one_validaor_one_gwei(spec, state):
attestations = prepare_state_with_full_attestations(spec, state)
yield from run_process_rewards_and_penalties(spec, state)
# Few assertions. Mainly to check that this extreme case can run without exception
attesting_indices = spec.get_unslashed_attesting_indices(state, attestations)
assert len(attesting_indices) == 1
@with_all_phases
@spec_state_test
def test_no_attestations_all_penalties(spec, state):
@ -164,6 +179,22 @@ def test_no_attestations_all_penalties(spec, state):
assert state.balances[index] < pre_state.balances[index]
@with_all_phases
@spec_state_test
def test_empty_attestations(spec, state):
attestations = prepare_state_with_full_attestations(spec, state, empty=True)
pre_state = state.copy()
yield from run_process_rewards_and_penalties(spec, state)
attesting_indices = spec.get_unslashed_attesting_indices(state, attestations)
assert len(attesting_indices) == 0
for index in range(len(pre_state.validators)):
assert state.balances[index] < pre_state.balances[index]
@with_all_phases
@spec_state_test
def test_duplicate_attestation(spec, state):