Fix SyncCommittee

1. Make `get_sync_committee_indices` do not return duplicate indices
2. Pad default values to Vectors
This commit is contained in:
Hsiao-Wei Wang 2021-01-13 17:28:23 +08:00
parent 002dfaa891
commit b2658f1091
No known key found for this signature in database
GPG Key ID: 1111A8A81778319E
4 changed files with 35 additions and 10 deletions

View File

@ -50,6 +50,7 @@ This is a standalone beacon chain patch adding light client support via sync com
| Name | Value |
| - | - |
| `G1_POINT_AT_INFINITY` | `BLSPubkey(b'\xc0' + b'\x00' * 47)` |
| `G2_POINT_AT_INFINITY` | `BLSSignature(b'\xc0' + b'\x00' * 95)` |
### Misc
@ -138,12 +139,19 @@ def get_sync_committee_indices(state: BeaconState, epoch: Epoch) -> Sequence[Val
seed = get_seed(state, base_epoch, DOMAIN_SYNC_COMMITTEE)
i = 0
sync_committee_indices: List[ValidatorIndex] = []
while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE:
if len(active_validator_indices) < SYNC_COMMITTEE_SIZE:
committee_size = len(active_validator_indices)
else:
committee_size = SYNC_COMMITTEE_SIZE
while len(sync_committee_indices) < committee_size:
shuffled_index = compute_shuffled_index(uint64(i % active_validator_count), active_validator_count, seed)
candidate_index = active_validator_indices[shuffled_index]
random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32]
effective_balance = state.validators[candidate_index].effective_balance
if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte:
if (
effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte
and candidate_index not in sync_committee_indices
):
sync_committee_indices.append(candidate_index)
i += 1
return sync_committee_indices
@ -163,6 +171,11 @@ def get_sync_committee(state: BeaconState, epoch: Epoch) -> SyncCommittee:
bls.AggregatePKs(pubkeys[i:i + SYNC_COMMITTEE_PUBKEY_AGGREGATES_SIZE])
for i in range(0, len(pubkeys), SYNC_COMMITTEE_PUBKEY_AGGREGATES_SIZE)
]
# Pad G1_POINT_AT_INFINITY to the BLSPubkey Vectors
if len(pubkeys) < SYNC_COMMITTEE_SIZE:
pubkeys += [G1_POINT_AT_INFINITY] * (SYNC_COMMITTEE_SIZE - len(pubkeys))
aggregates_length = SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_PUBKEY_AGGREGATES_SIZE
aggregates += [G1_POINT_AT_INFINITY] * (aggregates_length - len(aggregates))
return SyncCommittee(pubkeys=pubkeys, pubkey_aggregates=aggregates)
```

View File

@ -31,3 +31,9 @@ def compute_aggregate_sync_committee_signature(spec, state, slot, participants):
)
)
return bls.Aggregate(signatures)
def get_padded_sync_committee_bits(spec, sync_committee_bits):
if len(sync_committee_bits) < spec.SYNC_COMMITTEE_SIZE:
return sync_committee_bits + [False] * (spec.SYNC_COMMITTEE_SIZE - len(sync_committee_bits))
return sync_committee_bits

View File

@ -9,6 +9,7 @@ from eth2spec.test.helpers.state import (
)
from eth2spec.test.helpers.sync_committee import (
compute_aggregate_sync_committee_signature,
get_padded_sync_committee_bits,
)
from eth2spec.test.context import (
PHASE0, PHASE1,
@ -28,7 +29,9 @@ def test_invalid_signature_missing_participant(spec, state):
block = build_empty_block_for_next_slot(spec, state)
# Exclude one participant whose signature was included.
block.body.sync_committee_bits = [index != random_participant for index in committee]
block.body.sync_committee_bits = get_padded_sync_committee_bits(
spec, [index != random_participant for index in committee]
)
block.body.sync_committee_signature = compute_aggregate_sync_committee_signature(
spec,
state,
@ -51,7 +54,7 @@ def test_invalid_signature_extra_participant(spec, state):
block = build_empty_block_for_next_slot(spec, state)
# Exclude one signature even though the block claims the entire committee participated.
block.body.sync_committee_bits = [True] * len(committee)
block.body.sync_committee_bits = get_padded_sync_committee_bits(spec, [True] * len(committee))
block.body.sync_committee_signature = compute_aggregate_sync_committee_signature(
spec,
state,
@ -83,7 +86,7 @@ def test_sync_committee_rewards(spec, state):
pre_balances = state.balances.copy()
block = build_empty_block_for_next_slot(spec, state)
block.body.sync_committee_bits = [True] * committee_size
block.body.sync_committee_bits = get_padded_sync_committee_bits(spec, [True] * committee_size)
block.body.sync_committee_signature = compute_aggregate_sync_committee_signature(
spec,
state,
@ -126,7 +129,7 @@ def test_invalid_signature_past_block(spec, state):
# NOTE: need to transition twice to move beyond the degenerate case at genesis
block = build_empty_block_for_next_slot(spec, state)
# Valid sync committee signature here...
block.body.sync_committee_bits = [True] * len(committee)
block.body.sync_committee_bits = get_padded_sync_committee_bits(spec, [True] * len(committee))
block.body.sync_committee_signature = compute_aggregate_sync_committee_signature(
spec,
state,
@ -139,7 +142,7 @@ def test_invalid_signature_past_block(spec, state):
invalid_block = build_empty_block_for_next_slot(spec, state)
# Invalid signature from a slot other than the previous
invalid_block.body.sync_committee_bits = [True] * len(committee)
invalid_block.body.sync_committee_bits = get_padded_sync_committee_bits(spec, [True] * len(committee))
invalid_block.body.sync_committee_signature = compute_aggregate_sync_committee_signature(
spec,
state,
@ -175,7 +178,7 @@ def test_invalid_signature_previous_committee(spec, state):
yield 'pre', state
block = build_empty_block_for_next_slot(spec, state)
block.body.sync_committee_bits = [True] * len(committee)
block.body.sync_committee_bits = get_padded_sync_committee_bits(spec, [True] * len(committee))
block.body.sync_committee_signature = compute_aggregate_sync_committee_signature(
spec,
state,
@ -218,7 +221,7 @@ def test_valid_signature_future_committee(spec, state):
yield 'pre', state
block = build_empty_block_for_next_slot(spec, state)
block.body.sync_committee_bits = [True] * len(committee_indices)
block.body.sync_committee_bits = get_padded_sync_committee_bits(spec, [True] * len(committee_indices))
block.body.sync_committee_signature = compute_aggregate_sync_committee_signature(
spec,
state,

View File

@ -8,6 +8,7 @@ from eth2spec.test.helpers.block import (
)
from eth2spec.test.helpers.sync_committee import (
compute_aggregate_sync_committee_signature,
get_padded_sync_committee_bits,
)
from eth2spec.test.context import (
PHASE0, PHASE1,
@ -23,7 +24,9 @@ def run_sync_committee_sanity_test(spec, state, fraction_full=1.0):
yield 'pre', state
block = build_empty_block_for_next_slot(spec, state)
block.body.sync_committee_bits = [index in participants for index in committee]
block.body.sync_committee_bits = get_padded_sync_committee_bits(
spec, [index in participants for index in committee]
)
block.body.sync_committee_signature = compute_aggregate_sync_committee_signature(
spec,
state,