list-rework type fixes

This commit is contained in:
protolambda 2019-06-18 02:54:08 +02:00
parent 8c6ddd5233
commit 4aefc078e9
No known key found for this signature in database
GPG Key ID: EC89FDBB2B4C7623
3 changed files with 60 additions and 28 deletions

View File

@ -241,7 +241,7 @@ These configurations are updated for releases, but may be out of sync during `de
| `RANDAO_MIXES_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days | | `RANDAO_MIXES_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days |
| `ACTIVE_INDEX_ROOTS_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days | | `ACTIVE_INDEX_ROOTS_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days |
| `SLASHED_EXIT_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days | | `SLASHED_EXIT_LENGTH` | `2**13` (= 8,192) | epochs | ~36 days |
| `VALIDATOR_REGISTRY_SIZE` | `2**40 (= 1,099,511,627,776)` | | | | `VALIDATOR_REGISTRY_SIZE` | `2**40` (= 1,099,511,627,776) | | |
### Rewards and penalties ### Rewards and penalties
@ -372,7 +372,7 @@ class IndexedAttestation(Container):
```python ```python
class PendingAttestation(Container): class PendingAttestation(Container):
aggregation_bitfield: Bytes[MAX_COMMITTEE_SIZE] # Bit set for every attesting participant within a committee aggregation_bitfield: Bytes[MAX_INDICES_PER_ATTESTATION // 8]
data: AttestationData data: AttestationData
inclusion_delay: Slot inclusion_delay: Slot
proposer_index: ValidatorIndex proposer_index: ValidatorIndex
@ -439,9 +439,9 @@ class AttesterSlashing(Container):
```python ```python
class Attestation(Container): class Attestation(Container):
aggregation_bitfield: Bytes[MAX_COMMITTEE_SIZE] aggregation_bitfield: Bytes[MAX_INDICES_PER_ATTESTATION // 8]
data: AttestationData data: AttestationData
custody_bitfield: Bytes[MAX_COMMITTEE_SIZE] custody_bitfield: Bytes[MAX_INDICES_PER_ATTESTATION // 8]
signature: BLSSignature signature: BLSSignature
``` ```
@ -1629,20 +1629,8 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
assert len(body.deposits) == min(MAX_DEPOSITS, state.eth1_data.deposit_count - state.eth1_deposit_index) assert len(body.deposits) == min(MAX_DEPOSITS, state.eth1_data.deposit_count - state.eth1_deposit_index)
# Verify that there are no duplicate transfers # Verify that there are no duplicate transfers
assert len(body.transfers) == len(set(body.transfers)) assert len(body.transfers) == len(set(body.transfers))
<<<<<<< HEAD
all_operations = [
(body.proposer_slashings, MAX_PROPOSER_SLASHINGS, process_proposer_slashing),
(body.attester_slashings, MAX_ATTESTER_SLASHINGS, process_attester_slashing),
(body.attestations, MAX_ATTESTATIONS, process_attestation),
(body.deposits, MAX_DEPOSITS, process_deposit),
(body.voluntary_exits, MAX_VOLUNTARY_EXITS, process_voluntary_exit),
(body.transfers, MAX_TRANSFERS, process_transfer),
] # type: List[Tuple[List[Container], int, Callable]]
for operations, max_operations, function in all_operations:
assert len(operations) <= max_operations
=======
for operations, max_operations, function in ( for operations, function in (
(body.proposer_slashings, process_proposer_slashing), (body.proposer_slashings, process_proposer_slashing),
(body.attester_slashings, process_attester_slashing), (body.attester_slashings, process_attester_slashing),
(body.attestations, process_attestation), (body.attestations, process_attestation),
@ -1650,7 +1638,6 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
(body.voluntary_exits, process_voluntary_exit), (body.voluntary_exits, process_voluntary_exit),
(body.transfers, process_transfer), (body.transfers, process_transfer),
): ):
>>>>>>> f6a2345f... Update spec for new SSZ with list max length
for operation in operations: for operation in operations:
function(state, operation) function(state, operation)
``` ```

View File

@ -2,10 +2,6 @@ from typing import Tuple, Iterator
from types import GeneratorType from types import GeneratorType
class ValueCheckError(Exception):
pass
class DefaultingTypeMeta(type): class DefaultingTypeMeta(type):
def default(cls): def default(cls):
raise Exception("Not implemented") raise Exception("Not implemented")
@ -97,7 +93,7 @@ def coerce_type_maybe(v, typ: SSZType):
# shortcut if it's already the type we are looking for # shortcut if it's already the type we are looking for
if v_typ == typ: if v_typ == typ:
return v return v
elif isinstance(v, int): elif isinstance(v, int) and not isinstance(v, uint): # do not coerce from one uintX to another uintY
return typ(v) return typ(v)
elif isinstance(v, (list, tuple)): elif isinstance(v, (list, tuple)):
return typ(*v) return typ(*v)
@ -126,7 +122,7 @@ class Container(Series, metaclass=SSZType):
else: else:
value = coerce_type_maybe(kwargs[f], t) value = coerce_type_maybe(kwargs[f], t)
if not isinstance(value, t): if not isinstance(value, t):
raise ValueCheckError(f"Bad input for class {self.__class__}:" raise ValueError(f"Bad input for class {self.__class__}:"
f" field: {f} type: {t} value: {value} value type: {type(value)}") f" field: {f} type: {t} value: {value} value type: {type(value)}")
setattr(self, f, value) setattr(self, f, value)
@ -148,7 +144,7 @@ class Container(Series, metaclass=SSZType):
field_typ = self.__class__.__annotations__[name] field_typ = self.__class__.__annotations__[name]
value = coerce_type_maybe(value, field_typ) value = coerce_type_maybe(value, field_typ)
if not isinstance(value, field_typ): if not isinstance(value, field_typ):
raise ValueCheckError(f"Cannot set field of {self.__class__}:" raise ValueError(f"Cannot set field of {self.__class__}:"
f" field: {name} type: {field_typ} value: {value} value type: {type(value)}") f" field: {name} type: {field_typ} value: {value} value type: {type(value)}")
super().__setattr__(name, value) super().__setattr__(name, value)
@ -273,7 +269,7 @@ class Elements(ParamsBase, metaclass=ElementsType):
items = self.extract_args(*args) items = self.extract_args(*args)
if not self.value_check(items): if not self.value_check(items):
raise ValueCheckError(f"Bad input for class {self.__class__}: {items}") raise ValueError(f"Bad input for class {self.__class__}: {items}")
self.items = items self.items = items
@classmethod @classmethod
@ -296,6 +292,16 @@ class Elements(ParamsBase, metaclass=ElementsType):
return self.items[i] return self.items[i]
def __setitem__(self, k, v): def __setitem__(self, k, v):
if k < 0:
raise IndexError(f"cannot set item in type {self.__class__} at negative index {k} (to {v})")
if k > len(self.items):
raise IndexError(f"cannot set item in type {self.__class__}"
f" at out of bounds index {k} (to {v}, bound: {len(self.items)})")
typ = self.__class__.elem_type
v = coerce_type_maybe(v, typ)
if not isinstance(v, typ):
raise ValueError(f"Cannot set item in type {self.__class__},"
f" mismatched element type: {v} of {type(v)}, expected {typ}")
self.items[k] = v self.items[k] = v
def __len__(self): def __len__(self):

View File

@ -106,9 +106,14 @@ def test_container():
assert v.type().length == 1024 assert v.type().length == 1024
y.a = 42 y.a = 42
y.a = uint16(255)
try: try:
y.a = uint16(256) y.a = 256 # out of bounds
assert False
except ValueError:
pass
try:
y.a = uint16(255) # within bounds, wrong type
assert False assert False
except ValueError: except ValueError:
pass pass
@ -149,3 +154,37 @@ def test_list():
assert isinstance(v, Series) assert isinstance(v, Series)
assert issubclass(v.type(), Elements) assert issubclass(v.type(), Elements)
assert isinstance(v.type(), ElementsType) assert isinstance(v.type(), ElementsType)
foo = List[uint32, 128](0 for i in range(128))
foo[0] = 123
foo[1] = 654
foo[127] = 222
assert sum(foo) == 999
try:
foo[3] = 2**32 # out of bounds
except ValueError:
pass
try:
foo[3] = uint64(2**32 - 1) # within bounds, wrong type
assert False
except ValueError:
pass
try:
foo[128] = 100
assert False
except IndexError:
pass
try:
foo[-1] = 100 # valid in normal python lists
assert False
except IndexError:
pass
try:
foo[128] = 100 # out of bounds
assert False
except IndexError:
pass