Skip to content
This repository has been archived by the owner on Jul 1, 2021. It is now read-only.

Implement per-block processing - eth1 data #253

Merged
merged 2 commits into from
Feb 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 39 additions & 0 deletions eth2/beacon/state_machines/forks/serenity/block_processing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from eth_utils.toolz import (
first,
)

from eth2._utils.tuple import update_tuple_item

from eth2.beacon.types.states import BeaconState
from eth2.beacon.types.blocks import BaseBeaconBlock
from eth2.beacon.types.eth1_data_vote import Eth1DataVote

from eth2.beacon.state_machines.configs import BeaconConfig


def process_eth1_data(state: BeaconState,
block: BaseBeaconBlock,
config: BeaconConfig) -> BeaconState:
try:
vote_index, original_vote = first(
(index, eth1_data_vote)
for index, eth1_data_vote in enumerate(state.eth1_data_votes)
if block.eth1_data == eth1_data_vote.eth1_data
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, this try, except StopIteration, else pattern looks interesting to me! But since ethereum/consensus-specs#561 clarified ethereum/consensus-specs#555 and using first makes us lose the advantage of that we can break the for-loop earlier once we find block.eth1_data == eth1_data_vote.eth1_data. IMHO I think the formal boring for-if-break is better in this case now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First will also break early as it's given a generator instead of a list.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh yes!

except StopIteration:
new_vote = Eth1DataVote(
eth1_data=block.eth1_data,
vote_count=1,
)
state = state.copy(
eth1_data_votes=state.eth1_data_votes + (new_vote,)
)
else:
updated_vote = original_vote.copy(
vote_count=original_vote.vote_count + 1
)
state = state.copy(
eth1_data_votes=update_tuple_item(state.eth1_data_votes, vote_index, updated_vote)
)

return state
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import pytest

from eth2.beacon.types.eth1_data_vote import Eth1DataVote
from eth2.beacon.types.states import BeaconState
from eth2.beacon.types.blocks import BeaconBlock

from eth2.beacon.state_machines.forks.serenity.block_processing import (
process_eth1_data,
)

HASH1 = b"\x11" * 32
HASH2 = b"\x22" * 32


@pytest.mark.parametrize(("original_votes", "block_data", "expected_votes"), (
((), HASH1, ((HASH1, 1),)),
(((HASH1, 5),), HASH1, ((HASH1, 6),)),
(((HASH2, 5),), HASH1, ((HASH2, 5), (HASH1, 1))),
(((HASH1, 10), (HASH2, 2)), HASH2, ((HASH1, 10), (HASH2, 3))),
))
def test_process_eth1_data(original_votes,
block_data,
expected_votes,
sample_beacon_state_params,
sample_beacon_block_params,
config):
eth1_data_votes = tuple(
Eth1DataVote(data, vote_count)
for data, vote_count in original_votes
)
state = BeaconState(**sample_beacon_state_params).copy(
eth1_data_votes=eth1_data_votes,
)

block = BeaconBlock(**sample_beacon_block_params).copy(
eth1_data=block_data,
)

updated_state = process_eth1_data(state, block, config)
updated_votes = tuple(
(vote.eth1_data, vote.vote_count)
for vote in updated_state.eth1_data_votes
)
assert updated_votes == expected_votes