Skip to content

Commit

Permalink
Merge pull request #949 from ethereum/JustinDrake-patch-14
Browse files Browse the repository at this point in the history
Revamp balances and incentivisation
  • Loading branch information
djrtwo committed Apr 24, 2019
2 parents 6c7ab59 + 20d65e0 commit ade74f0
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 261 deletions.
389 changes: 160 additions & 229 deletions specs/core/0_beacon-chain.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions specs/light_client/sync_protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ def verify_block_validity_proof(proof: BlockValidityProof, validator_memory: Val
assert proof.shard_parent_block.beacon_chain_root == hash_tree_root(proof.header)
committee = compute_committee(proof.header, validator_memory)
# Verify that we have >=50% support
support_balance = sum([v.high_balance for i, v in enumerate(committee) if get_bitfield_bit(proof.shard_bitfield, i) is True])
total_balance = sum([v.high_balance for i, v in enumerate(committee)])
support_balance = sum([v.effective_balance for i, v in enumerate(committee) if get_bitfield_bit(proof.shard_bitfield, i) is True])
total_balance = sum([v.effective_balance for i, v in enumerate(committee)])
assert support_balance * 2 > total_balance
# Verify shard attestations
group_public_key = bls_aggregate_pubkeys([
Expand Down
4 changes: 2 additions & 2 deletions specs/validator/0_beacon-chain-validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ A validator has two primary responsibilities to the beacon chain -- [proposing b

### Block proposal

A validator is expected to propose a [`BeaconBlock`](../core/0_beacon-chain.md#beaconblock) at the beginning of any slot during which `get_beacon_proposer_index(state, slot)` returns the validator's `validator_index`. To propose, the validator selects the `BeaconBlock`, `parent`, that in their view of the fork choice is the head of the chain during `slot - 1`. The validator is to create, sign, and broadcast a `block` that is a child of `parent` and that executes a valid [beacon chain state transition](../core/0_beacon-chain.md#beacon-chain-state-transition-function).
A validator is expected to propose a [`BeaconBlock`](../core/0_beacon-chain.md#beaconblock) at the beginning of any slot during which `get_beacon_proposer_index(state)` returns the validator's `validator_index`. To propose, the validator selects the `BeaconBlock`, `parent`, that in their view of the fork choice is the head of the chain during `slot - 1`. The validator is to create, sign, and broadcast a `block` that is a child of `parent` and that executes a valid [beacon chain state transition](../core/0_beacon-chain.md#beacon-chain-state-transition-function).

There is one proposer per slot, so if there are N active validators any individual validator will on average be assigned to propose once per N slots (e.g. at 312500 validators = 10 million ETH, that's once per ~3 weeks).

Expand Down Expand Up @@ -368,7 +368,7 @@ def get_committee_assignment(
return assignment
```

A validator can use the following function to see if they are supposed to propose during their assigned committee slot. This function can only be run during the slot in question and can not reliably be used to predict in advance.
A validator can use the following function to see if they are supposed to propose during their assigned committee slot. This function can only be run during the slot in question. Proposer selection is only stable within the context of the current epoch.

```python
def is_proposer_at_slot(state: BeaconState,
Expand Down
2 changes: 0 additions & 2 deletions test_libs/pyspec/eth2spec/phase0/state_transition.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
BeaconState,
BeaconBlock,
Slot,
process_proposer_attestation_rewards,
)


Expand Down Expand Up @@ -52,7 +51,6 @@ def process_operations(state: BeaconState, block: BeaconBlock) -> None:
spec.MAX_ATTESTATIONS,
spec.process_attestation,
)
process_proposer_attestation_rewards(state)

assert len(block.body.deposits) == expected_deposit_count(state)
process_operation_type(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

import eth2spec.phase0.spec as spec
from eth2spec.phase0.spec import (
get_balance,
get_beacon_proposer_index,
process_attester_slashing,
)
from tests.helpers import (
get_balance,
get_valid_attester_slashing,
next_epoch,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import eth2spec.phase0.spec as spec

from eth2spec.phase0.spec import (
get_balance,
ZERO_HASH,
process_deposit,
)
from tests.helpers import (
get_balance,
build_deposit,
privkeys,
pubkeys,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

import eth2spec.phase0.spec as spec
from eth2spec.phase0.spec import (
get_balance,
get_current_epoch,
process_proposer_slashing,
)
from tests.helpers import (
get_balance,
get_valid_proposer_slashing,
)

Expand Down
10 changes: 4 additions & 6 deletions test_libs/pyspec/tests/block_processing/test_process_transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@

from eth2spec.phase0.spec import (
get_active_validator_indices,
get_balance,
get_beacon_proposer_index,
get_current_epoch,
process_transfer,
set_balance,
)
from tests.helpers import (
get_valid_transfer,
Expand Down Expand Up @@ -75,7 +73,7 @@ def test_success_withdrawable(state):
def test_success_active_above_max_effective(state):
sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1]
amount = spec.MAX_EFFECTIVE_BALANCE // 32
set_balance(state, sender_index, spec.MAX_EFFECTIVE_BALANCE + amount)
state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE + amount
transfer = get_valid_transfer(state, sender_index=sender_index, amount=amount, fee=0)

pre_state, post_state = run_transfer_processing(state, transfer)
Expand All @@ -86,7 +84,7 @@ def test_success_active_above_max_effective(state):
def test_active_but_transfer_past_effective_balance(state):
sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1]
amount = spec.MAX_EFFECTIVE_BALANCE // 32
set_balance(state, sender_index, spec.MAX_EFFECTIVE_BALANCE)
state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE
transfer = get_valid_transfer(state, sender_index=sender_index, amount=amount, fee=0)

pre_state, post_state = run_transfer_processing(state, transfer, False)
Expand All @@ -107,7 +105,7 @@ def test_incorrect_slot(state):
def test_insufficient_balance(state):
sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1]
amount = spec.MAX_EFFECTIVE_BALANCE
set_balance(state, sender_index, spec.MAX_EFFECTIVE_BALANCE)
state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE
transfer = get_valid_transfer(state, sender_index=sender_index, amount=amount + 1, fee=0)

# un-activate so validator can transfer
Expand Down Expand Up @@ -140,4 +138,4 @@ def test_invalid_pubkey(state):

pre_state, post_state = run_transfer_processing(state, transfer, False)

return pre_state, transfer, post_state
return pre_state, transfer, post_state
12 changes: 8 additions & 4 deletions test_libs/pyspec/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
# functions
convert_to_indexed,
get_active_validator_indices,
get_balance,
get_attesting_indices,
get_block_root,
get_block_root_at_slot,
get_crosslink_committees_at_slot,
get_current_epoch,
get_domain,
Expand All @@ -53,6 +53,10 @@
pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)}


def get_balance(state, index):
return state.balances[index]


def set_bitfield_bit(bitfield, i):
"""
Set the bit in ``bitfield`` at position ``i`` to ``1``.
Expand Down Expand Up @@ -150,16 +154,16 @@ def build_attestation_data(state, slot, shard):
if slot == state.slot:
block_root = build_empty_block_for_next_slot(state).previous_block_root
else:
block_root = get_block_root(state, slot)
block_root = get_block_root_at_slot(state, slot)

current_epoch_start_slot = get_epoch_start_slot(get_current_epoch(state))
if slot < current_epoch_start_slot:
print(slot)
epoch_boundary_root = get_block_root(state, get_epoch_start_slot(get_previous_epoch(state)))
epoch_boundary_root = get_block_root(state, get_previous_epoch(state))
elif slot == current_epoch_start_slot:
epoch_boundary_root = block_root
else:
epoch_boundary_root = get_block_root(state, current_epoch_start_slot)
epoch_boundary_root = get_block_root(state, get_current_epoch(state))

if slot < current_epoch_start_slot:
justified_epoch = state.previous_justified_epoch
Expand Down
20 changes: 8 additions & 12 deletions test_libs/pyspec/tests/test_sanity.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,13 @@
VoluntaryExit,
# functions
get_active_validator_indices,
get_balance,
get_beacon_proposer_index,
get_block_root,
get_block_root_at_slot,
get_state_root,
get_current_epoch,
get_domain,
get_state_root,
advance_slot,
cache_state,
set_balance,
slot_to_epoch,
verify_merkle_branch,
hash,
)
Expand All @@ -37,6 +34,7 @@
get_merkle_root,
)
from .helpers import (
get_balance,
build_deposit_data,
build_empty_block_for_next_slot,
fill_aggregate_attestation,
Expand All @@ -52,7 +50,6 @@
# mark entire file as 'sanity'
pytestmark = pytest.mark.sanity


def check_finality(state,
prev_state,
current_justified_changed,
Expand Down Expand Up @@ -96,7 +93,7 @@ def test_empty_block_transition(state):
state_transition(test_state, block)

assert len(test_state.eth1_data_votes) == len(state.eth1_data_votes) + 1
assert get_block_root(test_state, state.slot) == block.previous_block_root
assert get_block_root_at_slot(test_state, state.slot) == block.previous_block_root

return state, [block], test_state

Expand All @@ -110,7 +107,7 @@ def test_skipped_slots(state):

assert test_state.slot == block.slot
for slot in range(state.slot, test_state.slot):
assert get_block_root(test_state, slot) == block.previous_block_root
assert get_block_root_at_slot(test_state, slot) == block.previous_block_root

return state, [block], test_state

Expand All @@ -124,7 +121,7 @@ def test_empty_epoch_transition(state):

assert test_state.slot == block.slot
for slot in range(state.slot, test_state.slot):
assert get_block_root(test_state, slot) == block.previous_block_root
assert get_block_root_at_slot(test_state, slot) == block.previous_block_root

return state, [block], test_state

Expand Down Expand Up @@ -303,6 +300,7 @@ def test_deposit_top_up(state):


def test_attestation(state):
state.slot = spec.SLOTS_PER_EPOCH
test_state = deepcopy(state)
attestation = get_valid_attestation(state)

Expand All @@ -316,8 +314,6 @@ def test_attestation(state):

assert len(test_state.current_epoch_attestations) == len(state.current_epoch_attestations) + 1

proposer_index = get_beacon_proposer_index(test_state)
assert test_state.balances[proposer_index] > state.balances[proposer_index]

#
# Epoch transition should move to previous_epoch_attestations
Expand Down Expand Up @@ -441,7 +437,7 @@ def test_balance_driven_status_transitions(state):
assert pre_state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH

# set validator balance to below ejection threshold
set_balance(pre_state, validator_index, spec.EJECTION_BALANCE - 1)
pre_state.validator_registry[validator_index].effective_balance = spec.EJECTION_BALANCE

post_state = deepcopy(pre_state)
#
Expand Down
3 changes: 2 additions & 1 deletion tests/phase0/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
VoluntaryExit,
# functions
get_block_root,
get_block_root_at_slot,
get_current_epoch,
get_domain,
get_empty_block,
Expand Down Expand Up @@ -141,7 +142,7 @@ def build_attestation_data(state, slot, shard):
if epoch_start_slot == slot:
epoch_boundary_root = block_root
else:
get_block_root(state, epoch_start_slot)
epoch_boundary_root = get_block_root(state, get_current_epoch(state))

if slot < epoch_start_slot:
justified_block_root = state.previous_justified_root
Expand Down

0 comments on commit ade74f0

Please sign in to comment.