Changed attestation and custody bitfields
This commit is contained in:
parent
d641e94151
commit
67c50cb197
|
@ -26,7 +26,7 @@ from eth2spec.utils.ssz.ssz_impl import (
|
|||
)
|
||||
from eth2spec.utils.ssz.ssz_typing import (
|
||||
bit, boolean, Container, List, Vector, Bytes, uint64,
|
||||
Bytes4, Bytes32, Bytes48, Bytes96,
|
||||
Bytes4, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector,
|
||||
)
|
||||
from eth2spec.utils.bls import (
|
||||
bls_aggregate_pubkeys,
|
||||
|
@ -53,7 +53,7 @@ from eth2spec.utils.ssz.ssz_impl import (
|
|||
)
|
||||
from eth2spec.utils.ssz.ssz_typing import (
|
||||
bit, boolean, Container, List, Vector, Bytes, uint64,
|
||||
Bytes4, Bytes32, Bytes48, Bytes96,
|
||||
Bytes4, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector,
|
||||
)
|
||||
from eth2spec.utils.bls import (
|
||||
bls_aggregate_pubkeys,
|
||||
|
@ -175,7 +175,7 @@ def combine_constants(old_constants: Dict[str, str], new_constants: Dict[str, st
|
|||
|
||||
ignored_dependencies = [
|
||||
'bit', 'boolean', 'Vector', 'List', 'Container', 'Hash', 'BLSPubkey', 'BLSSignature', 'Bytes', 'BytesN'
|
||||
'Bytes4', 'Bytes32', 'Bytes48', 'Bytes96',
|
||||
'Bytes4', 'Bytes32', 'Bytes48', 'Bytes96', 'Bitlist', 'Bitvector',
|
||||
'uint8', 'uint16', 'uint32', 'uint64', 'uint128', 'uint256',
|
||||
'bytes' # to be removed after updating spec doc
|
||||
]
|
||||
|
|
|
@ -80,8 +80,6 @@
|
|||
- [`bytes_to_int`](#bytes_to_int)
|
||||
- [`get_total_balance`](#get_total_balance)
|
||||
- [`get_domain`](#get_domain)
|
||||
- [`get_bitfield_bit`](#get_bitfield_bit)
|
||||
- [`verify_bitfield`](#verify_bitfield)
|
||||
- [`convert_to_indexed`](#convert_to_indexed)
|
||||
- [`validate_indexed_attestation`](#validate_indexed_attestation)
|
||||
- [`is_slashable_attestation_data`](#is_slashable_attestation_data)
|
||||
|
@ -354,7 +352,7 @@ class IndexedAttestation(Container):
|
|||
|
||||
```python
|
||||
class PendingAttestation(Container):
|
||||
aggregation_bitfield: Bytes[MAX_INDICES_PER_ATTESTATION // 8]
|
||||
aggregation_bitfield: Bitlist[MAX_INDICES_PER_ATTESTATION]
|
||||
data: AttestationData
|
||||
inclusion_delay: Slot
|
||||
proposer_index: ValidatorIndex
|
||||
|
@ -421,9 +419,9 @@ class AttesterSlashing(Container):
|
|||
|
||||
```python
|
||||
class Attestation(Container):
|
||||
aggregation_bitfield: Bytes[MAX_INDICES_PER_ATTESTATION // 8]
|
||||
aggregation_bitfield: Bitlist[MAX_INDICES_PER_ATTESTATION]
|
||||
data: AttestationData
|
||||
custody_bitfield: Bytes[MAX_INDICES_PER_ATTESTATION // 8]
|
||||
custody_bitfield: Bitlist[MAX_INDICES_PER_ATTESTATION]
|
||||
signature: BLSSignature
|
||||
```
|
||||
|
||||
|
@ -865,13 +863,12 @@ def get_crosslink_committee(state: BeaconState, epoch: Epoch, shard: Shard) -> S
|
|||
```python
|
||||
def get_attesting_indices(state: BeaconState,
|
||||
attestation_data: AttestationData,
|
||||
bitfield: bytes) -> Sequence[ValidatorIndex]:
|
||||
bitfield: Bitlist[MAX_INDICES_PER_ATTESTATION]) -> Sequence[ValidatorIndex]:
|
||||
"""
|
||||
Return the sorted attesting indices corresponding to ``attestation_data`` and ``bitfield``.
|
||||
"""
|
||||
committee = get_crosslink_committee(state, attestation_data.target_epoch, attestation_data.crosslink.shard)
|
||||
assert verify_bitfield(bitfield, len(committee))
|
||||
return sorted([index for i, index in enumerate(committee) if get_bitfield_bit(bitfield, i) == 0b1])
|
||||
return sorted([index for i, index in enumerate(committee) if bitfield[i]])
|
||||
```
|
||||
|
||||
### `int_to_bytes`
|
||||
|
@ -912,34 +909,6 @@ def get_domain(state: BeaconState,
|
|||
return bls_domain(domain_type, fork_version)
|
||||
```
|
||||
|
||||
### `get_bitfield_bit`
|
||||
|
||||
```python
|
||||
def get_bitfield_bit(bitfield: bytes, i: int) -> int:
|
||||
"""
|
||||
Extract the bit in ``bitfield`` at position ``i``.
|
||||
"""
|
||||
return (bitfield[i // 8] >> (i % 8)) % 2
|
||||
```
|
||||
|
||||
### `verify_bitfield`
|
||||
|
||||
```python
|
||||
def verify_bitfield(bitfield: bytes, committee_size: int) -> bool:
|
||||
"""
|
||||
Verify ``bitfield`` against the ``committee_size``.
|
||||
"""
|
||||
if len(bitfield) != (committee_size + 7) // 8:
|
||||
return False
|
||||
|
||||
# Check `bitfield` is padded with zero bits only
|
||||
for i in range(committee_size, len(bitfield) * 8):
|
||||
if get_bitfield_bit(bitfield, i) == 0b1:
|
||||
return False
|
||||
|
||||
return True
|
||||
```
|
||||
|
||||
### `convert_to_indexed`
|
||||
|
||||
```python
|
||||
|
|
|
@ -3,7 +3,7 @@ from enum import Enum
|
|||
|
||||
from eth2spec.utils.ssz.ssz_typing import (
|
||||
SSZType, SSZValue, BasicValue, BasicType, uint, Container, Bytes, List, boolean,
|
||||
Vector, BytesN
|
||||
Vector, BytesN, Bitlist, Bitvector
|
||||
)
|
||||
|
||||
# in bytes
|
||||
|
@ -83,12 +83,12 @@ def get_random_ssz_object(rng: Random,
|
|||
return get_max_basic_value(typ)
|
||||
else:
|
||||
return get_random_basic_value(rng, typ)
|
||||
elif issubclass(typ, Vector):
|
||||
elif issubclass(typ, Vector) or issubclass(typ, Bitvector):
|
||||
return typ(
|
||||
get_random_ssz_object(rng, typ.elem_type, max_bytes_length, max_list_length, mode, chaos)
|
||||
for _ in range(typ.length)
|
||||
)
|
||||
elif issubclass(typ, List):
|
||||
elif issubclass(typ, List) or issubclass(typ, Bitlist):
|
||||
length = rng.randint(0, min(typ.length, max_list_length))
|
||||
if mode == RandomizationMode.mode_one_count:
|
||||
length = 1
|
||||
|
|
|
@ -18,7 +18,14 @@ def translate_typ(typ) -> ssz.BaseSedes:
|
|||
elif issubclass(typ, spec_ssz.Vector):
|
||||
return ssz.Vector(translate_typ(typ.elem_type), typ.length)
|
||||
elif issubclass(typ, spec_ssz.List):
|
||||
# TODO: Make py-ssz List support the new fixed length list
|
||||
return ssz.List(translate_typ(typ.elem_type))
|
||||
elif issubclass(typ, spec_ssz.Bitlist):
|
||||
# TODO: Once Bitlist implemented in py-ssz, use appropriate type
|
||||
return ssz.List(translate_typ(typ.elem_type))
|
||||
elif issubclass(typ, spec_ssz.Bitvector):
|
||||
# TODO: Once Bitvector implemented in py-ssz, use appropriate type
|
||||
return ssz.Vector(translate_typ(typ.elem_type), typ.length)
|
||||
elif issubclass(typ, spec_ssz.boolean):
|
||||
return ssz.boolean
|
||||
elif issubclass(typ, spec_ssz.uint):
|
||||
|
@ -68,6 +75,10 @@ def translate_value(value, typ):
|
|||
return value
|
||||
elif issubclass(typ, spec_ssz.Vector):
|
||||
return typ(*(translate_value(elem, typ.elem_type) for elem in value))
|
||||
elif issubclass(typ, spec_ssz.Bitlist):
|
||||
return typ(value)
|
||||
elif issubclass(typ, spec_ssz.Bitvector):
|
||||
return typ(value)
|
||||
elif issubclass(typ, spec_ssz.BytesN):
|
||||
return typ(value)
|
||||
elif issubclass(typ, spec_ssz.Bytes):
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from typing import List
|
||||
|
||||
from eth2spec.test.helpers.bitfields import set_bitfield_bit
|
||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, sign_block
|
||||
from eth2spec.test.helpers.keys import privkeys
|
||||
from eth2spec.utils.bls import bls_sign, bls_aggregate_signatures
|
||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||
from eth2spec.utils.ssz.ssz_typing import Bitlist
|
||||
|
||||
|
||||
def build_attestation_data(spec, state, slot, shard):
|
||||
|
@ -69,9 +69,8 @@ def get_valid_attestation(spec, state, slot=None, signed=False):
|
|||
)
|
||||
|
||||
committee_size = len(crosslink_committee)
|
||||
bitfield_length = (committee_size + 7) // 8
|
||||
aggregation_bitfield = b'\x00' * bitfield_length
|
||||
custody_bitfield = b'\x00' * bitfield_length
|
||||
aggregation_bitfield = Bitlist[spec.MAX_INDICES_PER_ATTESTATION](*([0] * committee_size))
|
||||
custody_bitfield = Bitlist[spec.MAX_INDICES_PER_ATTESTATION](*([0] * committee_size))
|
||||
attestation = spec.Attestation(
|
||||
aggregation_bitfield=aggregation_bitfield,
|
||||
data=attestation_data,
|
||||
|
@ -138,7 +137,7 @@ def fill_aggregate_attestation(spec, state, attestation):
|
|||
attestation.data.crosslink.shard,
|
||||
)
|
||||
for i in range(len(crosslink_committee)):
|
||||
attestation.aggregation_bitfield = set_bitfield_bit(attestation.aggregation_bitfield, i)
|
||||
attestation.aggregation_bitfield[i] = True
|
||||
|
||||
|
||||
def add_attestation_to_state(spec, state, attestation, slot):
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
def set_bitfield_bit(bitfield, i):
|
||||
"""
|
||||
Set the bit in ``bitfield`` at position ``i`` to ``1``.
|
||||
"""
|
||||
byte_index = i // 8
|
||||
bit_index = i % 8
|
||||
return (
|
||||
bitfield[:byte_index] +
|
||||
bytes([bitfield[byte_index] | (1 << bit_index)]) +
|
||||
bitfield[byte_index + 1:]
|
||||
)
|
|
@ -10,6 +10,7 @@ from eth2spec.test.helpers.state import (
|
|||
next_slot,
|
||||
)
|
||||
from eth2spec.test.helpers.block import apply_empty_block
|
||||
from eth2spec.utils.ssz.ssz_typing import Bitlist
|
||||
|
||||
|
||||
def run_attestation_processing(spec, state, attestation, valid=True):
|
||||
|
@ -281,7 +282,10 @@ def test_inconsistent_bitfields(spec, state):
|
|||
attestation = get_valid_attestation(spec, state)
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
attestation.custody_bitfield = deepcopy(attestation.aggregation_bitfield) + b'\x00'
|
||||
custody_bitfield = deepcopy(attestation.aggregation_bitfield)
|
||||
custody_bitfield.append(False)
|
||||
|
||||
attestation.custody_bitfield = custody_bitfield
|
||||
|
||||
sign_attestation(spec, state, attestation)
|
||||
|
||||
|
@ -307,7 +311,7 @@ def test_empty_aggregation_bitfield(spec, state):
|
|||
attestation = get_valid_attestation(spec, state)
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
attestation.aggregation_bitfield = b'\x00' * len(attestation.aggregation_bitfield)
|
||||
attestation.aggregation_bitfield = Bitlist[spec.MAX_INDICES_PER_ATTESTATION](*([0] * len(attestation.aggregation_bitfield)))
|
||||
|
||||
sign_attestation(spec, state, attestation)
|
||||
|
||||
|
|
|
@ -351,11 +351,15 @@ class BaseBitfield(BaseList, metaclass=BitElementsType):
|
|||
|
||||
|
||||
class Bitlist(BaseBitfield):
|
||||
pass
|
||||
@classmethod
|
||||
def is_fixed_size(cls):
|
||||
return False
|
||||
|
||||
|
||||
class Bitvector(BaseBitfield):
|
||||
pass
|
||||
@classmethod
|
||||
def is_fixed_size(cls):
|
||||
return True
|
||||
|
||||
|
||||
class List(BaseList):
|
||||
|
|
Loading…
Reference in New Issue