list-rework type fixes
This commit is contained in:
parent
8c6ddd5233
commit
4aefc078e9
|
@ -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)
|
||||||
```
|
```
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue