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

Commit

Permalink
PR feedback, thanks to NIC619
Browse files Browse the repository at this point in the history
  • Loading branch information
hwwhww committed Mar 7, 2019
1 parent fd53495 commit ed26220
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 30 deletions.
14 changes: 8 additions & 6 deletions eth2/beacon/_utils/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@
def get_permuted_index(index: int,
list_size: int,
seed: Hash32,
shuffle_round_count: int=90) -> int:
shuffle_round_count: int) -> int:
"""
Return `p(index)` in a pseudorandom permutation `p` of `0...list_size-1` with ``seed`` as entropy.
Return `p(index)` in a pseudorandom permutation `p` of `0...list_size-1`
with ``seed`` as entropy.
Utilizes 'swap or not' shuffling found in
https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf
Expand All @@ -48,20 +49,21 @@ def get_permuted_index(index: int,
f"`MAX_LIST_SIZE` ({MAX_LIST_SIZE}"
)

new_index = index
for round in range(shuffle_round_count):
pivot = int.from_bytes(
hash_eth2(seed + round.to_bytes(1, 'little'))[0:8],
'little',
) % list_size

flip = (pivot - index) % list_size
hash_pos = max(index, flip)
flip = (pivot - new_index) % list_size
hash_pos = max(new_index, flip)
h = hash_eth2(seed + round.to_bytes(1, 'little') + (hash_pos // 256).to_bytes(4, 'little'))
byte = h[(hash_pos % 256) // 8]
bit = (byte >> (hash_pos % 8)) % 2
index = flip if bit else index
new_index = flip if bit else new_index

return index
return new_index


@to_tuple
Expand Down
17 changes: 7 additions & 10 deletions eth2/beacon/committee_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,7 @@ def get_shuffling(*,
seed: Hash32,
validators: Sequence['ValidatorRecord'],
epoch: Epoch,
slots_per_epoch: int,
target_committee_size: int,
shard_count: int,
shuffle_round_count: int) -> Tuple[Iterable[ValidatorIndex], ...]:
committee_config: CommitteeConfig) -> Tuple[Iterable[ValidatorIndex], ...]:
"""
Shuffle ``validators`` into crosslink committees seeded by ``seed`` and ``epoch``.
Return a list of ``committee_per_epoch`` committees where each
Expand All @@ -87,6 +84,11 @@ def get_shuffling(*,
of ``validators`` forever in phase 0, and until the ~1 year deletion delay in phase 2
and in the future.
"""
slots_per_epoch = committee_config.SLOTS_PER_EPOCH
target_committee_size = committee_config.TARGET_COMMITTEE_SIZE
shard_count = committee_config.SHARD_COUNT
shuffle_round_count = committee_config.SHUFFLE_ROUND_COUNT

active_validator_indices = get_active_validator_indices(validators, epoch)

committees_per_epoch = get_epoch_committee_count(
Expand Down Expand Up @@ -287,8 +289,6 @@ def get_crosslink_committees_at_slot(
genesis_epoch = committee_config.GENESIS_EPOCH
shard_count = committee_config.SHARD_COUNT
slots_per_epoch = committee_config.SLOTS_PER_EPOCH
target_committee_size = committee_config.TARGET_COMMITTEE_SIZE
shuffle_round_count = committee_config.SHUFFLE_ROUND_COUNT

epoch = slot_to_epoch(slot, slots_per_epoch)
current_epoch = state.current_epoch(slots_per_epoch)
Expand Down Expand Up @@ -330,10 +330,7 @@ def get_crosslink_committees_at_slot(
seed=shuffling_context.seed,
validators=state.validator_registry,
epoch=shuffling_context.shuffling_epoch,
slots_per_epoch=slots_per_epoch,
target_committee_size=target_committee_size,
shard_count=shard_count,
shuffle_round_count=shuffle_round_count,
committee_config=committee_config,
)
offset = slot % slots_per_epoch
committees_per_slot = shuffling_context.committees_per_epoch // slots_per_epoch
Expand Down
6 changes: 3 additions & 3 deletions tests/eth2/beacon/_utils/test_random.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def slow_shuffle(items, seed, shuffle_round_count):
length = len(items)
return tuple(
[
items[get_permuted_index(i, length, seed, shuffle_round_count=shuffle_round_count)]
items[get_permuted_index(i, length, seed, shuffle_round_count)]
for i in range(length)
]
)
Expand Down Expand Up @@ -44,6 +44,6 @@ def test_shuffle_consistent(values, seed, shuffle_round_count):
assert shuffle(values, seed, shuffle_round_count) == expect


def test_get_permuted_index_invalid():
def test_get_permuted_index_invalid(shuffle_round_count):
with pytest.raises(ValidationError):
get_permuted_index(2, 2, b'\x12' * 32)
get_permuted_index(2, 2, b'\x12' * 32, shuffle_round_count)
14 changes: 3 additions & 11 deletions tests/eth2/beacon/test_committee_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,17 +150,13 @@ def test_get_next_epoch_committee_count(n_validators_state,
def test_get_shuffling_is_complete(activated_genesis_validators,
slots_per_epoch,
target_committee_size,
shuffle_round_count,
shard_count,
committee_config,
epoch):
shuffling = get_shuffling(
seed=b'\x35' * 32,
validators=activated_genesis_validators,
epoch=epoch,
slots_per_epoch=slots_per_epoch,
target_committee_size=target_committee_size,
shard_count=shard_count,
shuffle_round_count=shuffle_round_count,
committee_config=committee_config,
)

assert len(shuffling) == slots_per_epoch
Expand Down Expand Up @@ -344,7 +340,6 @@ def test_get_crosslink_committees_at_slot(
slots_per_epoch,
target_committee_size,
shard_count,
shuffle_round_count,
genesis_epoch,
committee_config,
registry_change,
Expand Down Expand Up @@ -448,10 +443,7 @@ def mock_generate_seed(state,
seed=seed,
validators=state.validator_registry,
epoch=shuffling_epoch,
slots_per_epoch=slots_per_epoch,
target_committee_size=target_committee_size,
shard_count=shard_count,
shuffle_round_count=shuffle_round_count,
committee_config=committee_config,
)
assert shuffling[committees_per_slot * offset] == crosslink_committees_at_slot[0][0]

Expand Down

0 comments on commit ed26220

Please sign in to comment.