Merge pull request #1746 from ethereum/hwwhww/strict-uint64

Apply strict uint64 casting
This commit is contained in:
Danny Ryan 2020-07-15 11:09:55 -06:00 committed by GitHub
commit 6a7a47dd5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 73 additions and 63 deletions

View File

@ -94,9 +94,9 @@ from dataclasses import (
from lru import LRU from lru import LRU
from eth2spec.utils.ssz.ssz_impl import hash_tree_root from eth2spec.utils.ssz.ssz_impl import hash_tree_root, copy
from eth2spec.utils.ssz.ssz_typing import ( from eth2spec.utils.ssz.ssz_typing import (
View, boolean, Container, List, Vector, uint64, View, boolean, Container, List, Vector, uint64, uint8,
Bytes1, Bytes4, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector, Bytes1, Bytes4, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector,
) )
from eth2spec.utils import bls from eth2spec.utils import bls
@ -118,7 +118,7 @@ from dataclasses import (
from lru import LRU from lru import LRU
from eth2spec.utils.ssz.ssz_impl import hash_tree_root from eth2spec.utils.ssz.ssz_impl import hash_tree_root, copy
from eth2spec.utils.ssz.ssz_typing import ( from eth2spec.utils.ssz.ssz_typing import (
View, boolean, Container, List, Vector, uint64, uint8, bit, View, boolean, Container, List, Vector, uint64, uint8, bit,
ByteList, ByteVector, Bytes1, Bytes4, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector, ByteList, ByteVector, Bytes1, Bytes4, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector,
@ -529,7 +529,7 @@ setup(
"py_ecc==4.0.0", "py_ecc==4.0.0",
"milagro_bls_binding==1.3.0", "milagro_bls_binding==1.3.0",
"dataclasses==0.6", "dataclasses==0.6",
"remerkleable==0.1.16", "remerkleable==0.1.17",
"ruamel.yaml==0.16.5", "ruamel.yaml==0.16.5",
"lru-dict==1.1.6" "lru-dict==1.1.6"
] ]

View File

@ -170,9 +170,9 @@ The following values are (non-configurable) constants used throughout the specif
| `GENESIS_SLOT` | `Slot(0)` | | `GENESIS_SLOT` | `Slot(0)` |
| `GENESIS_EPOCH` | `Epoch(0)` | | `GENESIS_EPOCH` | `Epoch(0)` |
| `FAR_FUTURE_EPOCH` | `Epoch(2**64 - 1)` | | `FAR_FUTURE_EPOCH` | `Epoch(2**64 - 1)` |
| `BASE_REWARDS_PER_EPOCH` | `4` | | `BASE_REWARDS_PER_EPOCH` | `uint64(4)` |
| `DEPOSIT_CONTRACT_TREE_DEPTH` | `2**5` (= 32) | | `DEPOSIT_CONTRACT_TREE_DEPTH` | `uint64(2**5)` (= 32) |
| `JUSTIFICATION_BITS_LENGTH` | `4` | | `JUSTIFICATION_BITS_LENGTH` | `uint64(4)` |
| `ENDIANNESS` | `'little'` | | `ENDIANNESS` | `'little'` |
## Configuration ## Configuration
@ -183,18 +183,18 @@ The following values are (non-configurable) constants used throughout the specif
| Name | Value | | Name | Value |
| - | - | | - | - |
| `ETH1_FOLLOW_DISTANCE` | `2**10` (= 1,024) | | `ETH1_FOLLOW_DISTANCE` | `uint64(2**10)` (= 1,024) |
| `MAX_COMMITTEES_PER_SLOT` | `2**6` (= 64) | | `MAX_COMMITTEES_PER_SLOT` | `uint64(2**6)` (= 64) |
| `TARGET_COMMITTEE_SIZE` | `2**7` (= 128) | | `TARGET_COMMITTEE_SIZE` | `uint64(2**7)` (= 128) |
| `MAX_VALIDATORS_PER_COMMITTEE` | `2**11` (= 2,048) | | `MAX_VALIDATORS_PER_COMMITTEE` | `uint64(2**11)` (= 2,048) |
| `MIN_PER_EPOCH_CHURN_LIMIT` | `2**2` (= 4) | | `MIN_PER_EPOCH_CHURN_LIMIT` | `uint64(2**2)` (= 4) |
| `CHURN_LIMIT_QUOTIENT` | `2**16` (= 65,536) | | `CHURN_LIMIT_QUOTIENT` | `uint64(2**16)` (= 65,536) |
| `SHUFFLE_ROUND_COUNT` | `90` | | `SHUFFLE_ROUND_COUNT` | `uint64(90)` |
| `MIN_GENESIS_ACTIVE_VALIDATOR_COUNT` | `2**14` (= 16,384) | | `MIN_GENESIS_ACTIVE_VALIDATOR_COUNT` | `uint64(2**14)` (= 16,384) |
| `MIN_GENESIS_TIME` | `1578009600` (Jan 3, 2020) | | `MIN_GENESIS_TIME` | `uint64(1578009600)` (Jan 3, 2020) |
| `HYSTERESIS_QUOTIENT` | `4` | | `HYSTERESIS_QUOTIENT` | `uint64(4)` |
| `HYSTERESIS_DOWNWARD_MULTIPLIER` | `1` | | `HYSTERESIS_DOWNWARD_MULTIPLIER` | `uint64(1)` |
| `HYSTERESIS_UPWARD_MULTIPLIER` | `5` | | `HYSTERESIS_UPWARD_MULTIPLIER` | `uint64(5)` |
- For the safety of committees, `TARGET_COMMITTEE_SIZE` exceeds [the recommended minimum committee size of 111](http://web.archive.org/web/20190504131341/https://vitalik.ca/files/Ithaca201807_Sharding.pdf); with sufficient active validators (at least `SLOTS_PER_EPOCH * TARGET_COMMITTEE_SIZE`), the shuffling algorithm ensures committee sizes of at least `TARGET_COMMITTEE_SIZE`. (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.) - For the safety of committees, `TARGET_COMMITTEE_SIZE` exceeds [the recommended minimum committee size of 111](http://web.archive.org/web/20190504131341/https://vitalik.ca/files/Ithaca201807_Sharding.pdf); with sufficient active validators (at least `SLOTS_PER_EPOCH * TARGET_COMMITTEE_SIZE`), the shuffling algorithm ensures committee sizes of at least `TARGET_COMMITTEE_SIZE`. (Unbiasable randomness with a Verifiable Delay Function (VDF) will improve committee robustness and lower the safe minimum committee size.)
@ -218,37 +218,37 @@ The following values are (non-configurable) constants used throughout the specif
| Name | Value | Unit | Duration | | Name | Value | Unit | Duration |
| - | - | :-: | :-: | | - | - | :-: | :-: |
| `GENESIS_DELAY` | `172800` | seconds | 2 days | | `GENESIS_DELAY` | `uint64(172800)` | seconds | 2 days |
| `SECONDS_PER_SLOT` | `12` | seconds | 12 seconds | | `SECONDS_PER_SLOT` | `uint64(12)` | seconds | 12 seconds |
| `SECONDS_PER_ETH1_BLOCK` | `14` | seconds | 14 seconds | | `SECONDS_PER_ETH1_BLOCK` | `uint64(14)` | seconds | 14 seconds |
| `MIN_ATTESTATION_INCLUSION_DELAY` | `2**0` (= 1) | slots | 12 seconds | | `MIN_ATTESTATION_INCLUSION_DELAY` | `uint64(2**0)` (= 1) | slots | 12 seconds |
| `SLOTS_PER_EPOCH` | `2**5` (= 32) | slots | 6.4 minutes | | `SLOTS_PER_EPOCH` | `uint64(2**5)` (= 32) | slots | 6.4 minutes |
| `MIN_SEED_LOOKAHEAD` | `2**0` (= 1) | epochs | 6.4 minutes | | `MIN_SEED_LOOKAHEAD` | `uint64(2**0)` (= 1) | epochs | 6.4 minutes |
| `MAX_SEED_LOOKAHEAD` | `2**2` (= 4) | epochs | 25.6 minutes | | `MAX_SEED_LOOKAHEAD` | `uint64(2**2)` (= 4) | epochs | 25.6 minutes |
| `MIN_EPOCHS_TO_INACTIVITY_PENALTY` | `2**2` (= 4) | epochs | 25.6 minutes | | `MIN_EPOCHS_TO_INACTIVITY_PENALTY` | `uint64(2**2)` (= 4) | epochs | 25.6 minutes |
| `EPOCHS_PER_ETH1_VOTING_PERIOD` | `2**5` (= 32) | epochs | ~3.4 hours | | `EPOCHS_PER_ETH1_VOTING_PERIOD` | `uint64(2**5)` (= 32) | epochs | ~3.4 hours |
| `SLOTS_PER_HISTORICAL_ROOT` | `2**13` (= 8,192) | slots | ~27 hours | | `SLOTS_PER_HISTORICAL_ROOT` | `uint64(2**13)` (= 8,192) | slots | ~27 hours |
| `MIN_VALIDATOR_WITHDRAWABILITY_DELAY` | `2**8` (= 256) | epochs | ~27 hours | | `MIN_VALIDATOR_WITHDRAWABILITY_DELAY` | `uint64(2**8)` (= 256) | epochs | ~27 hours |
| `SHARD_COMMITTEE_PERIOD` | `Epoch(2**8)` (= 256) | epochs | ~27 hours | | `SHARD_COMMITTEE_PERIOD` | `uint64(2**8)` (= 256) | epochs | ~27 hours |
### State list lengths ### State list lengths
| Name | Value | Unit | Duration | | Name | Value | Unit | Duration |
| - | - | :-: | :-: | | - | - | :-: | :-: |
| `EPOCHS_PER_HISTORICAL_VECTOR` | `2**16` (= 65,536) | epochs | ~0.8 years | | `EPOCHS_PER_HISTORICAL_VECTOR` | `uint64(2**16)` (= 65,536) | epochs | ~0.8 years |
| `EPOCHS_PER_SLASHINGS_VECTOR` | `2**13` (= 8,192) | epochs | ~36 days | | `EPOCHS_PER_SLASHINGS_VECTOR` | `uint64(2**13)` (= 8,192) | epochs | ~36 days |
| `HISTORICAL_ROOTS_LIMIT` | `2**24` (= 16,777,216) | historical roots | ~52,262 years | | `HISTORICAL_ROOTS_LIMIT` | `uint64(2**24)` (= 16,777,216) | historical roots | ~52,262 years |
| `VALIDATOR_REGISTRY_LIMIT` | `2**40` (= 1,099,511,627,776) | validators | | `VALIDATOR_REGISTRY_LIMIT` | `uint64(2**40)` (= 1,099,511,627,776) | validators |
### Rewards and penalties ### Rewards and penalties
| Name | Value | | Name | Value |
| - | - | | - | - |
| `BASE_REWARD_FACTOR` | `2**6` (= 64) | | `BASE_REWARD_FACTOR` | `uint64(2**6)` (= 64) |
| `WHISTLEBLOWER_REWARD_QUOTIENT` | `2**9` (= 512) | | `WHISTLEBLOWER_REWARD_QUOTIENT` | `uint64(2**9)` (= 512) |
| `PROPOSER_REWARD_QUOTIENT` | `2**3` (= 8) | | `PROPOSER_REWARD_QUOTIENT` | `uint64(2**3)` (= 8) |
| `INACTIVITY_PENALTY_QUOTIENT` | `2**24` (= 16,777,216) | | `INACTIVITY_PENALTY_QUOTIENT` | `uint64(2**24)` (= 16,777,216) |
| `MIN_SLASHING_PENALTY_QUOTIENT` | `2**5` (= 32) | | `MIN_SLASHING_PENALTY_QUOTIENT` | `uint64(2**5)` (= 32) |
- The `INACTIVITY_PENALTY_QUOTIENT` equals `INVERSE_SQRT_E_DROP_TIME**2` where `INVERSE_SQRT_E_DROP_TIME := 2**12` epochs (about 18 days) is the time it takes the inactivity penalty to reduce the balance of non-participating validators to about `1/sqrt(e) ~= 60.6%`. Indeed, the balance retained by offline validators after `n` epochs is about `(1 - 1/INACTIVITY_PENALTY_QUOTIENT)**(n**2/2)`; so after `INVERSE_SQRT_E_DROP_TIME` epochs, it is roughly `(1 - 1/INACTIVITY_PENALTY_QUOTIENT)**(INACTIVITY_PENALTY_QUOTIENT/2) ~= 1/sqrt(e)`. - The `INACTIVITY_PENALTY_QUOTIENT` equals `INVERSE_SQRT_E_DROP_TIME**2` where `INVERSE_SQRT_E_DROP_TIME := 2**12` epochs (about 18 days) is the time it takes the inactivity penalty to reduce the balance of non-participating validators to about `1/sqrt(e) ~= 60.6%`. Indeed, the balance retained by offline validators after `n` epochs is about `(1 - 1/INACTIVITY_PENALTY_QUOTIENT)**(n**2/2)`; so after `INVERSE_SQRT_E_DROP_TIME` epochs, it is roughly `(1 - 1/INACTIVITY_PENALTY_QUOTIENT)**(INACTIVITY_PENALTY_QUOTIENT/2) ~= 1/sqrt(e)`.
@ -579,7 +579,7 @@ def xor(bytes_1: Bytes32, bytes_2: Bytes32) -> Bytes32:
#### `int_to_bytes` #### `int_to_bytes`
```python ```python
def int_to_bytes(n: uint64, length: uint64) -> bytes: def int_to_bytes(n: uint64, length: int) -> bytes:
""" """
Return the ``length``-byte serialization of ``n`` in ``ENDIANNESS``-endian. Return the ``length``-byte serialization of ``n`` in ``ENDIANNESS``-endian.
""" """
@ -593,7 +593,7 @@ def bytes_to_int(data: bytes) -> uint64:
""" """
Return the integer deserialization of ``data`` interpreted as ``ENDIANNESS``-endian. Return the integer deserialization of ``data`` interpreted as ``ENDIANNESS``-endian.
""" """
return int.from_bytes(data, ENDIANNESS) return uint64(int.from_bytes(data, ENDIANNESS))
``` ```
### Crypto ### Crypto
@ -737,7 +737,7 @@ def compute_shuffled_index(index: uint64, index_count: uint64, seed: Bytes32) ->
flip = (pivot + index_count - index) % index_count flip = (pivot + index_count - index) % index_count
position = max(index, flip) position = max(index, flip)
source = hash(seed + int_to_bytes(current_round, length=1) + int_to_bytes(position // 256, length=4)) source = hash(seed + int_to_bytes(current_round, length=1) + int_to_bytes(position // 256, length=4))
byte = source[(position % 256) // 8] byte = uint8(source[(position % 256) // 8])
bit = (byte >> (position % 8)) % 2 bit = (byte >> (position % 8)) % 2
index = flip if bit else index index = flip if bit else index
@ -753,9 +753,10 @@ def compute_proposer_index(state: BeaconState, indices: Sequence[ValidatorIndex]
""" """
assert len(indices) > 0 assert len(indices) > 0
MAX_RANDOM_BYTE = 2**8 - 1 MAX_RANDOM_BYTE = 2**8 - 1
i = 0 i = uint64(0)
total = uint64(len(indices))
while True: while True:
candidate_index = indices[compute_shuffled_index(i % len(indices), len(indices), seed)] candidate_index = indices[compute_shuffled_index(i % total, total, seed)]
random_byte = hash(seed + int_to_bytes(i // 32, length=8))[i % 32] random_byte = hash(seed + int_to_bytes(i // 32, length=8))[i % 32]
effective_balance = state.validators[candidate_index].effective_balance 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:
@ -775,7 +776,7 @@ def compute_committee(indices: Sequence[ValidatorIndex],
""" """
start = (len(indices) * index) // count start = (len(indices) * index) // count
end = (len(indices) * (index + 1)) // count end = (len(indices) * (index + 1)) // count
return [indices[compute_shuffled_index(i, len(indices), seed)] for i in range(start, end)] return [indices[compute_shuffled_index(uint64(i), uint64(len(indices)), seed)] for i in range(start, end)]
``` ```
#### `compute_epoch_at_slot` #### `compute_epoch_at_slot`
@ -934,7 +935,7 @@ def get_validator_churn_limit(state: BeaconState) -> uint64:
Return the validator churn limit for the current epoch. Return the validator churn limit for the current epoch.
""" """
active_validator_indices = get_active_validator_indices(state, get_current_epoch(state)) active_validator_indices = get_active_validator_indices(state, get_current_epoch(state))
return max(MIN_PER_EPOCH_CHURN_LIMIT, len(active_validator_indices) // CHURN_LIMIT_QUOTIENT) return max(MIN_PER_EPOCH_CHURN_LIMIT, uint64(len(active_validator_indices)) // CHURN_LIMIT_QUOTIENT)
``` ```
#### `get_seed` #### `get_seed`
@ -955,9 +956,9 @@ def get_committee_count_per_slot(state: BeaconState, epoch: Epoch) -> uint64:
""" """
Return the number of committees in each slot for the given ``epoch``. Return the number of committees in each slot for the given ``epoch``.
""" """
return max(1, min( return max(uint64(1), min(
MAX_COMMITTEES_PER_SLOT, MAX_COMMITTEES_PER_SLOT,
len(get_active_validator_indices(state, epoch)) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE, uint64(len(get_active_validator_indices(state, epoch))) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE,
)) ))
``` ```
@ -1316,7 +1317,7 @@ def process_justification_and_finalization(state: BeaconState) -> None:
# Process justifications # Process justifications
state.previous_justified_checkpoint = state.current_justified_checkpoint state.previous_justified_checkpoint = state.current_justified_checkpoint
state.justification_bits[1:] = state.justification_bits[:-1] state.justification_bits[1:] = state.justification_bits[:JUSTIFICATION_BITS_LENGTH - 1]
state.justification_bits[0] = 0b0 state.justification_bits[0] = 0b0
matching_target_attestations = get_matching_target_attestations(state, previous_epoch) # Previous epoch matching_target_attestations = get_matching_target_attestations(state, previous_epoch) # Previous epoch
if get_attesting_balance(state, matching_target_attestations) * 3 >= get_total_active_balance(state) * 2: if get_attesting_balance(state, matching_target_attestations) * 3 >= get_total_active_balance(state) * 2:

View File

@ -102,7 +102,7 @@ _The block for `anchor_root` is incorrectly initialized to the block header, rat
```python ```python
def get_forkchoice_store(anchor_state: BeaconState) -> Store: def get_forkchoice_store(anchor_state: BeaconState) -> Store:
anchor_block_header = anchor_state.latest_block_header.copy() anchor_block_header = copy(anchor_state.latest_block_header)
if anchor_block_header.state_root == Bytes32(): if anchor_block_header.state_root == Bytes32():
anchor_block_header.state_root = hash_tree_root(anchor_state) anchor_block_header.state_root = hash_tree_root(anchor_state)
anchor_root = hash_tree_root(anchor_block_header) anchor_root = hash_tree_root(anchor_block_header)
@ -110,14 +110,14 @@ def get_forkchoice_store(anchor_state: BeaconState) -> Store:
justified_checkpoint = Checkpoint(epoch=anchor_epoch, root=anchor_root) justified_checkpoint = Checkpoint(epoch=anchor_epoch, root=anchor_root)
finalized_checkpoint = Checkpoint(epoch=anchor_epoch, root=anchor_root) finalized_checkpoint = Checkpoint(epoch=anchor_epoch, root=anchor_root)
return Store( return Store(
time=anchor_state.genesis_time + SECONDS_PER_SLOT * anchor_state.slot, time=uint64(anchor_state.genesis_time + SECONDS_PER_SLOT * anchor_state.slot),
genesis_time=anchor_state.genesis_time, genesis_time=anchor_state.genesis_time,
justified_checkpoint=justified_checkpoint, justified_checkpoint=justified_checkpoint,
finalized_checkpoint=finalized_checkpoint, finalized_checkpoint=finalized_checkpoint,
best_justified_checkpoint=justified_checkpoint, best_justified_checkpoint=justified_checkpoint,
blocks={anchor_root: anchor_block_header}, blocks={anchor_root: anchor_block_header},
block_states={anchor_root: anchor_state.copy()}, block_states={anchor_root: copy(anchor_state)},
checkpoint_states={justified_checkpoint: anchor_state.copy()}, checkpoint_states={justified_checkpoint: copy(anchor_state)},
) )
``` ```
@ -302,7 +302,7 @@ def validate_on_attestation(store: Store, attestation: Attestation) -> None:
def store_target_checkpoint_state(store: Store, target: Checkpoint) -> None: def store_target_checkpoint_state(store: Store, target: Checkpoint) -> None:
# Store target checkpoint state if not yet seen # Store target checkpoint state if not yet seen
if target not in store.checkpoint_states: if target not in store.checkpoint_states:
base_state = store.block_states[target.root].copy() base_state = copy(store.block_states[target.root])
if base_state.slot < compute_start_slot_at_epoch(target.epoch): if base_state.slot < compute_start_slot_at_epoch(target.epoch):
process_slots(base_state, compute_start_slot_at_epoch(target.epoch)) process_slots(base_state, compute_start_slot_at_epoch(target.epoch))
store.checkpoint_states[target] = base_state store.checkpoint_states[target] = base_state
@ -348,7 +348,7 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
# Parent block must be known # Parent block must be known
assert block.parent_root in store.block_states assert block.parent_root in store.block_states
# Make a copy of the state to avoid mutability issues # Make a copy of the state to avoid mutability issues
pre_state = store.block_states[block.parent_root].copy() pre_state = copy(store.block_states[block.parent_root])
# Blocks cannot be in the future. If they are, their consideration must be delayed until the are in the past. # Blocks cannot be in the future. If they are, their consideration must be delayed until the are in the past.
assert get_current_slot(store) >= block.slot assert get_current_slot(store) >= block.slot

View File

@ -273,7 +273,7 @@ An honest block proposer sets `block.body.eth1_data = get_eth1_vote(state)` wher
```python ```python
def compute_time_at_slot(state: BeaconState, slot: Slot) -> uint64: def compute_time_at_slot(state: BeaconState, slot: Slot) -> uint64:
return state.genesis_time + slot * SECONDS_PER_SLOT return uint64(state.genesis_time + slot * SECONDS_PER_SLOT)
``` ```
```python ```python
@ -443,7 +443,7 @@ def compute_subnet_for_attestation(committees_per_slot: uint64, slot: Slot, comm
slots_since_epoch_start = slot % SLOTS_PER_EPOCH slots_since_epoch_start = slot % SLOTS_PER_EPOCH
committees_since_epoch_start = committees_per_slot * slots_since_epoch_start committees_since_epoch_start = committees_per_slot * slots_since_epoch_start
return (committees_since_epoch_start + committee_index) % ATTESTATION_SUBNET_COUNT return uint64((committees_since_epoch_start + committee_index) % ATTESTATION_SUBNET_COUNT)
``` ```
### Attestation aggregation ### Attestation aggregation

View File

@ -48,7 +48,7 @@ def test_genesis_epoch_full_attestations_no_rewards(spec, state):
attestation = get_valid_attestation(spec, state, signed=True) attestation = get_valid_attestation(spec, state, signed=True)
attestations.append(attestation) attestations.append(attestation)
# fill each created slot in state after inclusion delay # fill each created slot in state after inclusion delay
if slot - spec.MIN_ATTESTATION_INCLUSION_DELAY >= 0: if slot >= spec.MIN_ATTESTATION_INCLUSION_DELAY:
include_att = attestations[slot - spec.MIN_ATTESTATION_INCLUSION_DELAY] include_att = attestations[slot - spec.MIN_ATTESTATION_INCLUSION_DELAY]
add_attestations_to_state(spec, state, [include_att], state.slot) add_attestations_to_state(spec, state, [include_att], state.slot)
next_slot(spec, state) next_slot(spec, state)

View File

@ -40,9 +40,9 @@ def run_is_candidate_block(spec, eth1_block, period_start, success=True):
def get_min_new_period_epochs(spec): def get_min_new_period_epochs(spec):
return int( return (
spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE * 2 # to seconds (spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE * 2) # to seconds
/ spec.SECONDS_PER_SLOT / spec.SLOTS_PER_EPOCH // spec.SECONDS_PER_SLOT // spec.SLOTS_PER_EPOCH
) )

View File

@ -1,3 +1,4 @@
from typing import TypeVar
from remerkleable.core import View from remerkleable.core import View
from remerkleable.byte_arrays import Bytes32 from remerkleable.byte_arrays import Bytes32
@ -8,3 +9,11 @@ def serialize(obj: View) -> bytes:
def hash_tree_root(obj: View) -> Bytes32: def hash_tree_root(obj: View) -> Bytes32:
return Bytes32(obj.get_backing().merkle_root()) return Bytes32(obj.get_backing().merkle_root())
V = TypeVar('V', bound=View)
# Helper method for typing copies, and avoiding a example_input.copy() method call, instead of copy(example_input)
def copy(obj: V) -> V:
return obj.copy()

View File

@ -5,4 +5,4 @@ from remerkleable.complex import Container, Vector, List
from remerkleable.basic import boolean, bit, uint, byte, uint8, uint16, uint32, uint64, uint128, uint256 from remerkleable.basic import boolean, bit, uint, byte, uint8, uint16, uint32, uint64, uint128, uint256
from remerkleable.bitfields import Bitvector, Bitlist from remerkleable.bitfields import Bitvector, Bitlist
from remerkleable.byte_arrays import ByteVector, Bytes1, Bytes4, Bytes8, Bytes32, Bytes48, Bytes96, ByteList from remerkleable.byte_arrays import ByteVector, Bytes1, Bytes4, Bytes8, Bytes32, Bytes48, Bytes96, ByteList
from remerkleable.core import BasicView, View, TypeDef from remerkleable.core import BasicView, View