Esempio n. 1
0
class HistoricalBatch(ssz.Serializable):

    fields = [
        ('block_roots', Vector(bytes32, 1)),
        ('state_roots', Vector(bytes32, 1)),
    ]

    def __init__(self,
                 *,
                 block_roots: Sequence[Hash32] = default_tuple,
                 state_roots: Sequence[Hash32] = default_tuple,
                 config: Eth2Config = None) -> None:
        if config:
            # try to provide sane defaults
            if block_roots == default_tuple:
                block_roots = default_tuple_of_size(
                    config.SLOTS_PER_HISTORICAL_ROOT, ZERO_HASH32)
            if state_roots == default_tuple:
                state_roots = default_tuple_of_size(
                    config.SLOTS_PER_HISTORICAL_ROOT, ZERO_HASH32)

        super().__init__(
            block_roots=block_roots,
            state_roots=state_roots,
        )
Esempio n. 2
0
class HistoricalBatch(ssz.Serializable):

    fields = [
        # Block roots
        ('block_roots', Vector(bytes32, 1)),
        # State roots
        ('state_roots', Vector(bytes32, 1)),
    ]

    def __init__(self, *, block_roots: Sequence[Hash32],
                 state_roots: Sequence[Hash32]) -> None:
        super().__init__(
            block_roots=block_roots,
            state_roots=state_roots,
        )
Esempio n. 3
0
def test_byte_vector(value):
    byte_vector = ByteVector(len(value))
    serialized_value = ssz.encode(value, byte_vector)
    assert serialized_value == ssz.encode(
        tuple(bytes([byte_value]) for byte_value in value),
        Vector(byte, len(value)))
    assert ssz.decode(serialized_value, byte_vector) == value
Esempio n. 4
0
def test_tuple_of_static_sized_entries(value, serialized):
    sedes = Vector(uint8, len(value))
    assert encode_hex(ssz.encode(value, sedes)) == serialized
    decoded = ssz.decode(decode_hex(serialized), sedes)
    assert isinstance(decoded, HashableVector)
    assert tuple(decoded) == value
    assert decoded.sedes == sedes
Esempio n. 5
0
class Deposit(ssz.Serializable):
    """
    A :class:`~eth2.beacon.types.deposits.Deposit` contains the data represented by an instance
    of :class:`~eth2.beacon.types.deposit_data.DepositData`, along with a Merkle proof (``branch``
    and ``index``) that can be used to verify inclusion in the canonical deposit tree.
    """

    fields = [
        # Merkle branch in the deposit tree
        ('proof', Vector(bytes32, 1)),
        # Index in the deposit tree
        ('index', uint64),
        # Deposit data
        ('deposit_data', DepositData),
    ]

    def __init__(self,
                 proof: Sequence[Hash32],
                 index: int,
                 deposit_data: DepositData)-> None:
        super().__init__(
            proof,
            index,
            deposit_data,
        )
Esempio n. 6
0
def parse_type_definition(type_definition):
    error_message = f"Could not parse type definition {type_definition}"

    if isinstance(type_definition, str):
        try:
            sedes = sedes_by_name[type_definition]
        except KeyError:
            raise ValueError(error_message)
        else:
            return sedes

    elif isinstance(type_definition, Sequence):
        if len(type_definition) == 1:
            return List(parse_type_definition(type_definition[0]))
        elif len(type_definition) == 2:
            element_type = parse_type_definition(type_definition[0])
            try:
                length = int(type_definition[1])
            except ValueError:
                raise ValueError(error_message)
            return Vector(element_type, length)
        else:
            raise ValueError(error_message)

    elif isinstance(type_definition, Mapping):
        return Container(tuple(
            (field_name, parse_type_definition(field_type))
            for field_name, field_type in type_definition.items()
        ))

    else:
        raise ValueError(error_message)
Esempio n. 7
0
def test_list_of_dynamic_sized_entries(value, serialized):
    sedes = Vector(List(uint8, 2**32), len(value))
    assert encode_hex(ssz.encode(value, sedes)) == serialized
    decoded = ssz.decode(decode_hex(serialized), sedes)
    assert isinstance(decoded, HashableVector)
    assert tuple(tuple(element) for element in decoded) == value
    assert decoded.sedes == sedes
Esempio n. 8
0
class State(Serializable):
    fields = [
        ("validators", List(Validator, VALIDATOR_REGISTRY_LIMIT)),
        ("balances", List(uint64, VALIDATOR_REGISTRY_LIMIT)),
        ("randao_mixes", Vector(bytes32, EPOCHS_PER_HISTORICAL_VECTOR)),
        ("latest_block_header", BeaconBlockHeader),
        ("eth1_data", Eth1Data),
    ]
Esempio n. 9
0
def general_vector_sedes_and_values_st(draw,
                                       element_sedes_and_elements,
                                       size=None):
    element_sedes, elements = element_sedes_and_elements

    if size is None:
        size = draw(st.integers(min_value=1, max_value=10))

    sedes = Vector(length=size, element_sedes=element_sedes)
    values = st.builds(tuple, st.lists(elements, min_size=size, max_size=size))
    return sedes, values
Esempio n. 10
0
class HistoricalBatch(HashableContainer):

    fields = [("block_roots", Vector(bytes32, 1)), ("state_roots", Vector(bytes32, 1))]

    @classmethod
    def create(
        cls: Type[THistoricalBatch],
        *,
        block_roots: Sequence[Root] = default_tuple,
        state_roots: Sequence[Hash32] = default_tuple,
        config: Eth2Config = None
    ) -> THistoricalBatch:
        if config:
            # try to provide sane defaults
            if block_roots == default_tuple:
                block_roots = default_tuple_of_size(
                    config.SLOTS_PER_HISTORICAL_ROOT, ZERO_ROOT
                )
            if state_roots == default_tuple:
                state_roots = default_tuple_of_size(
                    config.SLOTS_PER_HISTORICAL_ROOT, ZERO_HASH32
                )

        return super().create(block_roots=block_roots, state_roots=state_roots)
Esempio n. 11
0
class Deposit(ssz.Serializable):
    """
    A :class:`~eth2.beacon.types.deposits.Deposit` contains the data represented by an instance
    of :class:`~eth2.beacon.types.deposit_data.DepositData`, along with a Merkle proof that can be
    used to verify inclusion in the canonical deposit tree.
    """

    fields = [
        # Merkle path to deposit root
        ("proof", Vector(bytes32, DEPOSIT_PROOF_VECTOR_SIZE)),
        ("data", DepositData),
    ]

    def __init__(
        self,
        proof: Sequence[Hash32] = default_proof_tuple,
        data: DepositData = default_deposit_data,
    ) -> None:
        super().__init__(proof, data)

    def __repr__(self) -> str:
        return f"<Deposit hash_tree_root: {encode_hex(self.hash_tree_root)[0:8]} data: {self.data}>"
Esempio n. 12
0
def test_vector_of_basics(serialized_uints128, result):
    sedes = Vector(uint128, len(serialized_uints128))
    int_values = tuple(ssz.decode(value, uint128) for value in serialized_uints128)
    assert ssz.get_hash_tree_root(int_values, sedes) == result
Esempio n. 13
0
class BeaconState(ssz.Serializable):

    fields = [
        # Versioning
        ('genesis_time', uint64),
        ('slot', uint64),
        ('fork', Fork),

        # History
        ('latest_block_header', BeaconBlockHeader),
        ('block_roots', Vector(bytes32, 1)
         ),  # Needed to process attestations, older to newer  # noqa: E501
        ('state_roots', Vector(bytes32, 1)),
        (
            'historical_roots', List(bytes32)
        ),  # allow for a log-sized Merkle proof from any block to any historical block root  # noqa: E501

        # Ethereum 1.0 chain
        ('eth1_data', Eth1Data),
        ('eth1_data_votes', List(Eth1Data)),
        ('eth1_deposit_index', uint64),

        # Validator registry
        ('validators', List(Validator)),
        ('balances', List(uint64)),

        # Shuffling
        ('start_shard', uint64),
        ('randao_mixes', Vector(bytes32, 1)),
        ('active_index_roots', Vector(bytes32, 1)),

        # Slashings
        ('slashed_balances', Vector(uint64, 1)
         ),  # Balances slashed at every withdrawal period  # noqa: E501

        # Attestations
        ('previous_epoch_attestations', List(PendingAttestation)),
        ('current_epoch_attestations', List(PendingAttestation)),

        # Crosslinks
        ('previous_crosslinks', Vector(Crosslink, 1)),
        ('current_crosslinks', Vector(Crosslink, 1)),

        # Justification
        ('previous_justified_epoch', uint64),
        ('previous_justified_root', bytes32),
        ('current_justified_epoch', uint64),
        ('current_justified_root', bytes32),
        # Note: justification_bitfield is meant to be defined as an integer type,
        # so its bit operation is in Python and is easier to specify and implement.
        ('justification_bitfield', uint64),

        # Finality
        ('finalized_epoch', uint64),
        ('finalized_root', bytes32),
    ]

    def __init__(self,
                 *,
                 genesis_time: Timestamp = default_timestamp,
                 slot: Slot = default_slot,
                 fork: Fork = default_fork,
                 latest_block_header:
                 BeaconBlockHeader = default_beacon_block_header,
                 block_roots: Sequence[Hash32] = default_tuple,
                 state_roots: Sequence[Hash32] = default_tuple,
                 historical_roots: Sequence[Hash32] = default_tuple,
                 eth1_data: Eth1Data = default_eth1_data,
                 eth1_data_votes: Sequence[Eth1Data] = default_tuple,
                 eth1_deposit_index: int = 0,
                 validators: Sequence[Validator] = default_tuple,
                 balances: Sequence[Gwei] = default_tuple,
                 start_shard: Shard = default_shard,
                 randao_mixes: Sequence[Hash32] = default_tuple,
                 active_index_roots: Sequence[Hash32] = default_tuple,
                 slashed_balances: Sequence[Gwei] = default_tuple,
                 previous_epoch_attestations: Sequence[
                     PendingAttestation] = default_tuple,
                 current_epoch_attestations: Sequence[
                     PendingAttestation] = default_tuple,
                 previous_crosslinks: Sequence[Crosslink] = default_tuple,
                 current_crosslinks: Sequence[Crosslink] = default_tuple,
                 previous_justified_epoch: Epoch = default_epoch,
                 previous_justified_root: Hash32 = ZERO_HASH32,
                 current_justified_epoch: Epoch = default_epoch,
                 current_justified_root: Hash32 = ZERO_HASH32,
                 justification_bitfield: int = 0,
                 finalized_epoch: Epoch = default_epoch,
                 finalized_root: Hash32 = ZERO_HASH32,
                 config: Eth2Config = None) -> None:
        if len(validators) != len(balances):
            raise ValueError(
                "The length of validators and balances lists should be the same."
            )

        if config:
            # try to provide sane defaults
            if block_roots == default_tuple:
                block_roots = default_tuple_of_size(
                    config.SLOTS_PER_HISTORICAL_ROOT, ZERO_HASH32)
            if state_roots == default_tuple:
                state_roots = default_tuple_of_size(
                    config.SLOTS_PER_HISTORICAL_ROOT, ZERO_HASH32)
            if randao_mixes == default_tuple:
                randao_mixes = default_tuple_of_size(
                    config.EPOCHS_PER_HISTORICAL_VECTOR, ZERO_HASH32)
            if active_index_roots == default_tuple:
                active_index_roots = default_tuple_of_size(
                    config.EPOCHS_PER_HISTORICAL_VECTOR, ZERO_HASH32)
            if slashed_balances == default_tuple:
                slashed_balances = default_tuple_of_size(
                    config.EPOCHS_PER_SLASHED_BALANCES_VECTOR,
                    Gwei(0),
                )
            if previous_crosslinks == default_tuple:
                previous_crosslinks = default_tuple_of_size(
                    config.SHARD_COUNT,
                    default_crosslink,
                )
            if current_crosslinks == default_tuple:
                current_crosslinks = default_tuple_of_size(
                    config.SHARD_COUNT,
                    default_crosslink,
                )

        super().__init__(
            genesis_time=genesis_time,
            slot=slot,
            fork=fork,
            latest_block_header=latest_block_header,
            block_roots=block_roots,
            state_roots=state_roots,
            historical_roots=historical_roots,
            eth1_data=eth1_data,
            eth1_data_votes=eth1_data_votes,
            eth1_deposit_index=eth1_deposit_index,
            validators=validators,
            balances=balances,
            start_shard=start_shard,
            randao_mixes=randao_mixes,
            active_index_roots=active_index_roots,
            slashed_balances=slashed_balances,
            previous_epoch_attestations=previous_epoch_attestations,
            current_epoch_attestations=current_epoch_attestations,
            previous_crosslinks=previous_crosslinks,
            current_crosslinks=current_crosslinks,
            previous_justified_epoch=previous_justified_epoch,
            previous_justified_root=previous_justified_root,
            current_justified_epoch=current_justified_epoch,
            current_justified_root=current_justified_root,
            justification_bitfield=justification_bitfield,
            finalized_epoch=finalized_epoch,
            finalized_root=finalized_root,
        )

    def __repr__(self) -> str:
        return f"<BeaconState #{self.slot} {encode_hex(self.root)[2:10]}>"

    @property
    def validator_count(self) -> int:
        return len(self.validators)

    def update_validator(self,
                         validator_index: ValidatorIndex,
                         validator: Validator,
                         balance: Gwei = None) -> 'BeaconState':
        """
        Replace ``self.validators[validator_index]`` with ``validator``.

        Callers can optionally provide a ``balance`` which will replace
        ``self.balances[validator_index] with ``balance``.
        """
        if (validator_index >= len(self.validators)
                or validator_index >= len(self.balances)
                or validator_index < 0):
            raise IndexError("Incorrect validator index")

        state = self.update_validator_with_fn(
            validator_index,
            lambda *_: validator,
        )
        if balance:
            return state._update_validator_balance(
                validator_index,
                balance,
            )
        else:
            return state

    def update_validator_with_fn(self, validator_index: ValidatorIndex,
                                 fn: Callable[[Validator, Any], Validator],
                                 *args: Any) -> 'BeaconState':
        """
        Replace ``self.validators[validator_index]`` with
        the result of calling ``fn`` on the existing ``validator``.
        Any auxillary args passed in ``args`` are provided to ``fn`` along with the
        ``validator``.
        """
        if validator_index >= len(self.validators) or validator_index < 0:
            raise IndexError("Incorrect validator index")

        return self.copy(validators=update_tuple_item_with_fn(
            self.validators,
            validator_index,
            fn,
            *args,
        ), )

    def _update_validator_balance(self, validator_index: ValidatorIndex,
                                  balance: Gwei) -> 'BeaconState':
        """
        Update the balance of validator of the given ``validator_index``.
        """
        if validator_index >= len(self.balances) or validator_index < 0:
            raise IndexError("Incorrect validator index")

        return self.copy(balances=update_tuple_item(
            self.balances,
            validator_index,
            balance,
        ))

    def current_epoch(self, slots_per_epoch: int) -> Epoch:
        return slot_to_epoch(self.slot, slots_per_epoch)

    def previous_epoch(self, slots_per_epoch: int,
                       genesis_epoch: Epoch) -> Epoch:
        current_epoch = self.current_epoch(slots_per_epoch)
        if current_epoch == genesis_epoch:
            return genesis_epoch
        else:
            return Epoch(current_epoch - 1)

    def next_epoch(self, slots_per_epoch: int) -> Epoch:
        return Epoch(self.current_epoch(slots_per_epoch) + 1)
Esempio n. 14
0
class Zoo(HashableContainer):
    fields = [("animals", Vector(Animal, 3))]
Esempio n. 15
0
    byte_list,
    bytes32,
    bytes48,
    bytes96,
    uint8,
    uint256,
)


@pytest.mark.parametrize(
    ("sedes", "size"),
    (
        (boolean, 1),
        (uint8, 1),
        (uint256, 32),
        (Vector(uint8, 0), 0),
        (Vector(uint8, 2), 2),
        (Container((uint8, Vector(uint8, 4))), 5),
        (Vector(List(uint8), 0), 0),
        (Vector(Container((uint8, Vector(uint8, 4))), 4), 20),
        (byte, 1),
        (ByteVector(0), 0),
        (bytes32, 32),
        (bytes48, 48),
        (bytes96, 96),
    ),
)
def test_fixed_size(sedes, size):
    assert sedes.is_fixed_sized
    assert sedes.get_fixed_size() == size
Esempio n. 16
0
class BeaconState(ssz.Serializable):

    fields = [
        # Misc
        ('slot', uint64),
        ('genesis_time', uint64),
        ('fork', Fork),  # For versioning hard forks

        # Validator registry
        ('validator_registry', List(Validator)),
        ('validator_balances', List(uint64)),
        ('validator_registry_update_epoch', uint64),

        # Randomness and committees
        ('latest_randao_mixes', Vector(bytes32, 1)),
        ('previous_shuffling_start_shard', uint64),
        ('current_shuffling_start_shard', uint64),
        ('previous_shuffling_epoch', uint64),
        ('current_shuffling_epoch', uint64),
        ('previous_shuffling_seed', bytes32),
        ('current_shuffling_seed', bytes32),

        # Finality
        ('previous_epoch_attestations', List(PendingAttestation)),
        ('current_epoch_attestations', List(PendingAttestation)),
        ('previous_justified_epoch', uint64),
        ('current_justified_epoch', uint64),
        ('previous_justified_root', bytes32),
        ('current_justified_root', bytes32),
        # Note: justification_bitfield is meant to be defined as an integer type,
        # so its bit operation is in Python and is easier to specify and implement.
        ('justification_bitfield', uint64),
        ('finalized_epoch', uint64),
        ('finalized_root', bytes32),

        # Recent state
        ('latest_crosslinks', Vector(Crosslink, 1)),
        ('latest_block_roots', Vector(bytes32, 1)
         ),  # Needed to process attestations, older to newer  # noqa: E501
        ('latest_state_roots', Vector(bytes32, 1)),
        ('latest_active_index_roots', Vector(bytes32, 1)),
        ('latest_slashed_balances', Vector(
            uint64,
            1)),  # Balances slashed at every withdrawal period  # noqa: E501
        ('latest_block_header', BeaconBlockHeader),
        (
            'historical_roots', List(bytes32)
        ),  # allow for a log-sized Merkle proof from any block to any historical block root"  # noqa: E501

        # Ethereum 1.0 chain
        ('latest_eth1_data', Eth1Data),
        ('eth1_data_votes', List(Eth1DataVote)),
        ('deposit_index', uint64),
    ]

    def __init__(
            self,
            *,
            # Misc
            slot: Slot,
            genesis_time: Timestamp,
            fork: Fork,
            # Validator registry
            validator_registry: Sequence[Validator],
            validator_balances: Sequence[Gwei],
            validator_registry_update_epoch: Epoch,
            # Randomness and committees
            latest_randao_mixes: Sequence[Hash32],
            previous_shuffling_start_shard: Shard,
            current_shuffling_start_shard: Shard,
            previous_shuffling_epoch: Epoch,
            current_shuffling_epoch: Epoch,
            previous_shuffling_seed: Hash32,
            current_shuffling_seed: Hash32,
            # Finality
            previous_epoch_attestations: Sequence[PendingAttestation],
            current_epoch_attestations: Sequence[PendingAttestation],
            previous_justified_epoch: Epoch,
            current_justified_epoch: Epoch,
            previous_justified_root: Hash32,
            current_justified_root: Hash32,
            justification_bitfield: int,
            finalized_epoch: Epoch,
            finalized_root: Hash32,
            # Recent state
            latest_crosslinks: Sequence[Crosslink],
            latest_block_roots: Sequence[Hash32],
            latest_state_roots: Sequence[Hash32],
            latest_active_index_roots: Sequence[Hash32],
            latest_slashed_balances: Sequence[Gwei],
            latest_block_header: BeaconBlockHeader,
            historical_roots: Sequence[Hash32],
            # Ethereum 1.0 chain
            latest_eth1_data: Eth1Data,
            eth1_data_votes: Sequence[Eth1DataVote],
            deposit_index: int) -> None:
        if len(validator_registry) != len(validator_balances):
            raise ValueError(
                "The length of validator_registry and validator_balances should be the same."
            )

        super().__init__(
            # Misc
            slot=slot,
            genesis_time=genesis_time,
            fork=fork,
            # Validator registry
            validator_registry=validator_registry,
            validator_balances=validator_balances,
            validator_registry_update_epoch=validator_registry_update_epoch,
            # Randomness and committees
            latest_randao_mixes=latest_randao_mixes,
            previous_shuffling_start_shard=previous_shuffling_start_shard,
            current_shuffling_start_shard=current_shuffling_start_shard,
            previous_shuffling_epoch=previous_shuffling_epoch,
            current_shuffling_epoch=current_shuffling_epoch,
            previous_shuffling_seed=previous_shuffling_seed,
            current_shuffling_seed=current_shuffling_seed,
            # Finality
            previous_epoch_attestations=previous_epoch_attestations,
            current_epoch_attestations=current_epoch_attestations,
            previous_justified_epoch=previous_justified_epoch,
            current_justified_epoch=current_justified_epoch,
            previous_justified_root=previous_justified_root,
            current_justified_root=current_justified_root,
            justification_bitfield=justification_bitfield,
            finalized_epoch=finalized_epoch,
            finalized_root=finalized_root,
            # Recent state
            latest_crosslinks=latest_crosslinks,
            latest_block_roots=latest_block_roots,
            latest_state_roots=latest_state_roots,
            latest_active_index_roots=latest_active_index_roots,
            latest_slashed_balances=latest_slashed_balances,
            latest_block_header=latest_block_header,
            historical_roots=historical_roots,
            # Ethereum 1.0 chain
            latest_eth1_data=latest_eth1_data,
            eth1_data_votes=eth1_data_votes,
            deposit_index=deposit_index,
        )

    def __repr__(self) -> str:
        return f"<BeaconState #{self.slot} {encode_hex(self.root)[2:10]}>"

    @property
    def num_validators(self) -> int:
        return len(self.validator_registry)

    @property
    def num_crosslinks(self) -> int:
        return len(self.latest_crosslinks)

    @classmethod
    def create_filled_state(
        cls,
        *,
        genesis_epoch: Epoch,
        genesis_start_shard: Shard,
        genesis_slot: Slot,
        shard_count: int,
        slots_per_historical_root: int,
        latest_active_index_roots_length: int,
        latest_randao_mixes_length: int,
        latest_slashed_exit_length: int,
        activated_genesis_validators: Sequence[Validator] = (),
        genesis_balances: Sequence[Gwei] = ()
    ) -> 'BeaconState':
        return cls(
            # Misc
            slot=genesis_slot,
            genesis_time=Timestamp(0),
            fork=Fork(
                previous_version=(0).to_bytes(4, 'little'),
                current_version=(0).to_bytes(4, 'little'),
                epoch=genesis_epoch,
            ),

            # Validator registry
            validator_registry=activated_genesis_validators,
            validator_balances=genesis_balances,
            validator_registry_update_epoch=genesis_epoch,

            # Randomness and committees
            latest_randao_mixes=(ZERO_HASH32, ) * latest_randao_mixes_length,
            previous_shuffling_start_shard=genesis_start_shard,
            current_shuffling_start_shard=genesis_start_shard,
            previous_shuffling_epoch=genesis_epoch,
            current_shuffling_epoch=genesis_epoch,
            previous_shuffling_seed=ZERO_HASH32,
            current_shuffling_seed=ZERO_HASH32,

            # Finality
            previous_epoch_attestations=(),
            current_epoch_attestations=(),
            previous_justified_epoch=genesis_epoch,
            current_justified_epoch=genesis_epoch,
            previous_justified_root=ZERO_HASH32,
            current_justified_root=ZERO_HASH32,
            justification_bitfield=0,
            finalized_epoch=genesis_epoch,
            finalized_root=ZERO_HASH32,

            # Recent state
            latest_crosslinks=((Crosslink(
                epoch=genesis_epoch,
                crosslink_data_root=ZERO_HASH32,
            ), ) * shard_count),
            latest_block_roots=(ZERO_HASH32, ) * slots_per_historical_root,
            latest_state_roots=(ZERO_HASH32, ) * slots_per_historical_root,
            latest_active_index_roots=(ZERO_HASH32, ) *
            latest_active_index_roots_length,
            latest_slashed_balances=(Gwei(0), ) * latest_slashed_exit_length,
            latest_block_header=get_temporary_block_header(
                BeaconBlock.create_empty_block(genesis_slot), ),
            historical_roots=(),

            # Ethereum 1.0 chain data
            latest_eth1_data=Eth1Data.create_empty_data(),
            eth1_data_votes=(),
            deposit_index=len(activated_genesis_validators),
        )

    def update_validator_registry(self, validator_index: ValidatorIndex,
                                  validator: Validator) -> 'BeaconState':
        """
        Replace ``self.validator_registry[validator_index]`` with ``validator``.
        """
        if validator_index >= self.num_validators or validator_index < 0:
            raise IndexError("Incorrect validator index")

        validator_registry = list(self.validator_registry)
        validator_registry[validator_index] = validator

        updated_state = self.copy(
            validator_registry=tuple(validator_registry), )
        return updated_state

    def update_validator_balance(self, validator_index: ValidatorIndex,
                                 balance: Gwei) -> 'BeaconState':
        """
        Update the balance of validator of the given ``validator_index``.
        """
        if validator_index >= self.num_validators or validator_index < 0:
            raise IndexError("Incorrect validator index")

        validator_balances = list(self.validator_balances)
        validator_balances[validator_index] = balance

        updated_state = self.copy(
            validator_balances=tuple(validator_balances), )
        return updated_state

    def update_validator(self, validator_index: ValidatorIndex,
                         validator: Validator, balance: Gwei) -> 'BeaconState':
        """
        Update the ``Validator`` and balance of validator of the given ``validator_index``.
        """
        state = self.update_validator_registry(validator_index, validator)
        state = state.update_validator_balance(validator_index, balance)
        return state

    def current_epoch(self, slots_per_epoch: int) -> Epoch:
        return slot_to_epoch(self.slot, slots_per_epoch)

    def previous_epoch(self, slots_per_epoch: int) -> Epoch:
        return Epoch(self.current_epoch(slots_per_epoch) - 1)

    def next_epoch(self, slots_per_epoch: int) -> Epoch:
        return Epoch(self.current_epoch(slots_per_epoch) + 1)
Esempio n. 17
0
    ("sedes1", "sedes2"), ((uint8, uint8), (UInt(8), UInt(8)), (UInt(256), UInt(256)))
)
def test_uint_eq(sedes1, sedes2):
    assert sedes1 == sedes1
    assert sedes2 == sedes2
    assert sedes1 == sedes2
    assert hash(sedes1) == hash(sedes2)


@pytest.mark.parametrize(
    ("sedes1", "sedes2"),
    (
        (UInt(8), UInt(256)),
        (UInt(8), Byte()),
        (UInt(8), boolean),
        (UInt(8), Vector(UInt(8), 1)),
    ),
)
def test_uint_neq(sedes1, sedes2):
    assert sedes1 != sedes2
    assert hash(sedes1) != hash(sedes2)


@pytest.mark.parametrize(
    ("sedes1", "sedes2"), ((boolean, boolean), (Boolean(), Boolean()))
)
def test_bool_eq(sedes1, sedes2):
    assert sedes1 == sedes1
    assert sedes2 == sedes2
    assert sedes1 == sedes2
    assert hash(sedes1) == hash(sedes2)
Esempio n. 18
0
class BeaconState(ssz.Serializable):

    fields = [
        # Versioning
        ("genesis_time", uint64),
        ("slot", uint64),
        ("fork", Fork),
        # History
        ("latest_block_header", BeaconBlockHeader),
        (
            "block_roots",
            Vector(bytes32, 1),
        ),  # Needed to process attestations, older to newer  # noqa: E501
        ("state_roots", Vector(bytes32, 1)),
        (
            "historical_roots",
            List(bytes32, 1),
        ),  # allow for a log-sized Merkle proof from any block to any historical block root  # noqa: E501
        # Ethereum 1.0 chain
        ("eth1_data", Eth1Data),
        ("eth1_data_votes", List(Eth1Data, 1)),
        ("eth1_deposit_index", uint64),
        # Validator registry
        ("validators", List(Validator, 1)),
        ("balances", List(uint64, 1)),
        # Shuffling
        ("start_shard", uint64),
        ("randao_mixes", Vector(bytes32, 1)),
        ("active_index_roots", Vector(bytes32, 1)),
        ("compact_committees_roots", Vector(bytes32, 1)),
        # Slashings
        (
            "slashings",
            Vector(uint64, 1),
        ),  # Balances slashed at every withdrawal period  # noqa: E501
        # Attestations
        ("previous_epoch_attestations", List(PendingAttestation, 1)),
        ("current_epoch_attestations", List(PendingAttestation, 1)),
        # Crosslinks
        ("previous_crosslinks", Vector(Crosslink, 1)),
        ("current_crosslinks", Vector(Crosslink, 1)),
        # Justification
        ("justification_bits", Bitvector(JUSTIFICATION_BITS_LENGTH)),
        ("previous_justified_checkpoint", Checkpoint),
        ("current_justified_checkpoint", Checkpoint),
        # Finality
        ("finalized_checkpoint", Checkpoint),
    ]

    def __init__(
        self,
        *,
        genesis_time: Timestamp = default_timestamp,
        slot: Slot = default_slot,
        fork: Fork = default_fork,
        latest_block_header: BeaconBlockHeader = default_beacon_block_header,
        block_roots: Sequence[Hash32] = default_tuple,
        state_roots: Sequence[Hash32] = default_tuple,
        historical_roots: Sequence[Hash32] = default_tuple,
        eth1_data: Eth1Data = default_eth1_data,
        eth1_data_votes: Sequence[Eth1Data] = default_tuple,
        eth1_deposit_index: int = 0,
        validators: Sequence[Validator] = default_tuple,
        balances: Sequence[Gwei] = default_tuple,
        start_shard: Shard = default_shard,
        randao_mixes: Sequence[Hash32] = default_tuple,
        active_index_roots: Sequence[Hash32] = default_tuple,
        compact_committees_roots: Sequence[Hash32] = default_tuple,
        slashings: Sequence[Gwei] = default_tuple,
        previous_epoch_attestations: Sequence[
            PendingAttestation] = default_tuple,
        current_epoch_attestations: Sequence[
            PendingAttestation] = default_tuple,
        previous_crosslinks: Sequence[Crosslink] = default_tuple,
        current_crosslinks: Sequence[Crosslink] = default_tuple,
        justification_bits: Bitfield = default_justification_bits,
        previous_justified_checkpoint: Checkpoint = default_checkpoint,
        current_justified_checkpoint: Checkpoint = default_checkpoint,
        finalized_checkpoint: Checkpoint = default_checkpoint,
        config: Eth2Config = None,
    ) -> None:
        if len(validators) != len(balances):
            raise ValueError(
                "The length of validators and balances lists should be the same."
            )

        if config:
            # try to provide sane defaults
            if block_roots == default_tuple:
                block_roots = default_tuple_of_size(
                    config.SLOTS_PER_HISTORICAL_ROOT, ZERO_HASH32)
            if state_roots == default_tuple:
                state_roots = default_tuple_of_size(
                    config.SLOTS_PER_HISTORICAL_ROOT, ZERO_HASH32)
            if randao_mixes == default_tuple:
                randao_mixes = default_tuple_of_size(
                    config.EPOCHS_PER_HISTORICAL_VECTOR, ZERO_HASH32)
            if active_index_roots == default_tuple:
                active_index_roots = default_tuple_of_size(
                    config.EPOCHS_PER_HISTORICAL_VECTOR, ZERO_HASH32)
            if compact_committees_roots == default_tuple:
                compact_committees_roots = default_tuple_of_size(
                    config.EPOCHS_PER_HISTORICAL_VECTOR, ZERO_HASH32)
            if slashings == default_tuple:
                slashings = default_tuple_of_size(
                    config.EPOCHS_PER_SLASHINGS_VECTOR, Gwei(0))
            if previous_crosslinks == default_tuple:
                previous_crosslinks = default_tuple_of_size(
                    config.SHARD_COUNT, default_crosslink)
            if current_crosslinks == default_tuple:
                current_crosslinks = default_tuple_of_size(
                    config.SHARD_COUNT, default_crosslink)

        super().__init__(
            genesis_time=genesis_time,
            slot=slot,
            fork=fork,
            latest_block_header=latest_block_header,
            block_roots=block_roots,
            state_roots=state_roots,
            historical_roots=historical_roots,
            eth1_data=eth1_data,
            eth1_data_votes=eth1_data_votes,
            eth1_deposit_index=eth1_deposit_index,
            validators=validators,
            balances=balances,
            start_shard=start_shard,
            randao_mixes=randao_mixes,
            active_index_roots=active_index_roots,
            compact_committees_roots=compact_committees_roots,
            slashings=slashings,
            previous_epoch_attestations=previous_epoch_attestations,
            current_epoch_attestations=current_epoch_attestations,
            previous_crosslinks=previous_crosslinks,
            current_crosslinks=current_crosslinks,
            justification_bits=justification_bits,
            previous_justified_checkpoint=previous_justified_checkpoint,
            current_justified_checkpoint=current_justified_checkpoint,
            finalized_checkpoint=finalized_checkpoint,
        )

    def __repr__(self) -> str:
        return f"<BeaconState #{self.slot} {encode_hex(self.hash_tree_root)[2:10]}>"

    @property
    def validator_count(self) -> int:
        return len(self.validators)

    def update_validator(
        self,
        validator_index: ValidatorIndex,
        validator: Validator,
        balance: Gwei = None,
    ) -> "BeaconState":
        """
        Replace ``self.validators[validator_index]`` with ``validator``.

        Callers can optionally provide a ``balance`` which will replace
        ``self.balances[validator_index] with ``balance``.
        """
        if (validator_index >= len(self.validators)
                or validator_index >= len(self.balances)
                or validator_index < 0):
            raise IndexError("Incorrect validator index")

        state = self.update_validator_with_fn(validator_index,
                                              lambda *_: validator)
        if balance:
            return state._update_validator_balance(validator_index, balance)
        else:
            return state

    def update_validator_with_fn(
        self,
        validator_index: ValidatorIndex,
        fn: Callable[[Validator, Any], Validator],
        *args: Any,
    ) -> "BeaconState":
        """
        Replace ``self.validators[validator_index]`` with
        the result of calling ``fn`` on the existing ``validator``.
        Any auxillary args passed in ``args`` are provided to ``fn`` along with the
        ``validator``.
        """
        if validator_index >= len(self.validators) or validator_index < 0:
            raise IndexError("Incorrect validator index")

        return self.copy(validators=update_tuple_item_with_fn(
            self.validators, validator_index, fn, *args))

    def _update_validator_balance(self, validator_index: ValidatorIndex,
                                  balance: Gwei) -> "BeaconState":
        """
        Update the balance of validator of the given ``validator_index``.
        """
        if validator_index >= len(self.balances) or validator_index < 0:
            raise IndexError("Incorrect validator index")

        return self.copy(balances=update_tuple_item(self.balances,
                                                    validator_index, balance))

    def current_epoch(self, slots_per_epoch: int) -> Epoch:
        return compute_epoch_of_slot(self.slot, slots_per_epoch)

    def previous_epoch(self, slots_per_epoch: int,
                       genesis_epoch: Epoch) -> Epoch:
        current_epoch = self.current_epoch(slots_per_epoch)
        if current_epoch == genesis_epoch:
            return genesis_epoch
        else:
            return Epoch(current_epoch - 1)

    def next_epoch(self, slots_per_epoch: int) -> Epoch:
        return Epoch(self.current_epoch(slots_per_epoch) + 1)
Esempio n. 19
0
def test_byte_vector(value):
    byte_sequence = tuple(bytes([byte_value]) for byte_value in value)
    expected_vector_root = ssz.hash_tree_root(byte_sequence,
                                              Vector(byte, len(value)))
    assert ssz.hash_tree_root(value,
                              ByteVector(len(value))) == expected_vector_root
Esempio n. 20
0
class Zoo(Serializable):
    fields = [
        ('animals', Vector(Animal, 3)),
    ]
Esempio n. 21
0
from ssz.hashable_container import HashableContainer, SignedHashableContainer
from ssz.sedes import (
    Bitlist,
    Bitvector,
    List,
    Vector,
    boolean,
    bytes32,
    bytes48,
    bytes96,
    uint64,
)

import sys
import argparse


if __name__ == "__main__":
    # Setup argument parser
    # the parameters are the elements of the vector
    parser = argparse.ArgumentParser()
    parser.add_argument('element', type=int, nargs='*')
    args = parser.parse_args()

    # Execute function/method to test
    hash = Vector(uint64, len(args.element)).get_hash_tree_root(args.element)

    # Write result to stdout in binary
    sys.stdout.buffer.write(hash)
Esempio n. 22
0
def test_vector_of_composite(bytes16_vector, result):
    sedes = Vector(ByteVector(16), len(bytes16_vector))
    assert ssz.get_hash_tree_root(bytes16_vector, sedes) == result
def test_bitvector_round_trip_no_sedes(size, value):
    foo = Bitvector(size)
    assert decode(encode(value, foo), foo) == value

    @pytest.mark.parametrize(("sedes", "id"),
                             ((Bitvector(64), "Bitvector64"), ))
    def test_get_sedes_id(sedes, id):
        assert sedes.get_sedes_id() == id


@pytest.mark.parametrize(("sedes1", "sedes2"),
                         ((Bitvector(2), Bitvector(2)), ))
def test_eq(sedes1, sedes2):
    assert sedes1 == sedes1
    assert sedes2 == sedes2
    assert sedes1 == sedes2
    assert hash(sedes1) == hash(sedes2)


@pytest.mark.parametrize(
    ("sedes1", "sedes2"),
    (
        (Bitvector(2), Bitvector(3)),
        (Bitvector(2), Bitlist(2)),
        (Bitvector(2), Vector(boolean, 2)),
    ),
)
def test_neq(sedes1, sedes2):
    assert sedes1 != sedes2
    assert hash(sedes1) != hash(sedes2)
Esempio n. 24
0
def test_container_of_dynamic_sized_fields(fields, value, serialized):
    sedes = Container(fields)

    assert encode_hex(ssz.encode(value, sedes)) == serialized
    decoded = ssz.decode(decode_hex(serialized), sedes)
    pure_decoded = tuple(
        tuple(element) if isinstance(element, HashableList) else element
        for element in decoded)
    assert pure_decoded == value


@pytest.mark.parametrize(
    ("sedes", "id"),
    (
        (List(uint8, 2), "List(UInt8,2)"),
        (Vector(uint8, 2), "Vector(UInt8,2)"),
        (Container((uint8, bytes32)), "UInt8,ByteVector32"),
        (Container((uint8, List(uint8, 2))), "UInt8,List(UInt8,2)"),
        (
            Vector(Container((uint8, List(uint8, 2))), 2),
            "Vector(UInt8,List(UInt8,2),2)",
        ),
    ),
)
def test_get_sedes_id(sedes, id):
    assert sedes.get_sedes_id() == id


@pytest.mark.parametrize(
    ("sedes1", "sedes2"),
    (
Esempio n. 25
0
def test_tuple_of_dynamic_sized_entries(value, serialized):
    sedes = Vector(List(uint8), len(value))
    assert encode_hex(ssz.encode(value, sedes)) == serialized
    assert ssz.decode(decode_hex(serialized), sedes) == value
Esempio n. 26
0
class BeaconState(HashableContainer):

    fields = [
        # Versioning
        ("genesis_time", uint64),
        ("slot", uint64),
        ("fork", Fork),
        # History
        ("latest_block_header", BeaconBlockHeader),
        (
            "block_roots",
            Vector(bytes32, 1),
        ),  # Needed to process attestations, older to newer  # noqa: E501
        ("state_roots", Vector(bytes32, 1)),
        (
            "historical_roots",
            List(bytes32, 1),
        ),  # allow for a log-sized Merkle proof from any block to any historical block root  # noqa: E501
        # Ethereum 1.0 chain
        ("eth1_data", Eth1Data),
        ("eth1_data_votes", List(Eth1Data, 1)),
        ("eth1_deposit_index", uint64),
        # Validator registry
        ("validators", List(Validator, 1)),
        ("balances", List(uint64, 1)),
        # Shuffling
        ("randao_mixes", Vector(bytes32, 1)),
        # Slashings
        (
            "slashings",
            Vector(uint64, 1),
        ),  # Balances slashed at every withdrawal period  # noqa: E501
        # Attestations
        ("previous_epoch_attestations", List(PendingAttestation, 1)),
        ("current_epoch_attestations", List(PendingAttestation, 1)),
        # Justification
        ("justification_bits", Bitvector(JUSTIFICATION_BITS_LENGTH)),
        ("previous_justified_checkpoint", Checkpoint),
        ("current_justified_checkpoint", Checkpoint),
        # Finality
        ("finalized_checkpoint", Checkpoint),
    ]

    @classmethod
    def create(
        cls: Type[TBeaconState],
        *,
        genesis_time: Timestamp = default_timestamp,
        slot: Slot = default_slot,
        fork: Fork = default_fork,
        latest_block_header: BeaconBlockHeader = default_beacon_block_header,
        block_roots: Sequence[SigningRoot] = default_block_roots,
        state_roots: Sequence[Hash32] = default_state_roots,
        historical_roots: Sequence[Hash32] = default_tuple,
        eth1_data: Eth1Data = default_eth1_data,
        eth1_data_votes: Sequence[Eth1Data] = default_tuple,
        eth1_deposit_index: int = 0,
        validators: Sequence[Validator] = default_tuple,
        balances: Sequence[Gwei] = default_tuple,
        randao_mixes: Sequence[Hash32] = default_randao_mixes,
        slashings: Sequence[Gwei] = default_slashings,
        previous_epoch_attestations: Sequence[
            PendingAttestation] = default_tuple,
        current_epoch_attestations: Sequence[
            PendingAttestation] = default_tuple,
        justification_bits: Bitfield = default_justification_bits,
        previous_justified_checkpoint: Checkpoint = default_checkpoint,
        current_justified_checkpoint: Checkpoint = default_checkpoint,
        finalized_checkpoint: Checkpoint = default_checkpoint,
        config: Eth2Config = None,
        validator_and_balance_length_check: bool = True,
    ) -> TBeaconState:
        # We usually want to check that the lengths of each list are the same
        # In some cases, e.g. SSZ fuzzing, they are not and we still want to instantiate an object.
        if validator_and_balance_length_check:
            if len(validators) != len(balances):
                raise ValueError(
                    f"The length of validators ({len(validators)}) and balances ({len(balances)}) "
                    "lists should be the same.")

        if config:
            # try to provide sane defaults
            if block_roots == default_tuple:
                block_roots = default_tuple_of_size(
                    config.SLOTS_PER_HISTORICAL_ROOT, ZERO_SIGNING_ROOT)
            if state_roots == default_tuple:
                state_roots = default_tuple_of_size(
                    config.SLOTS_PER_HISTORICAL_ROOT, ZERO_HASH32)
            if randao_mixes == default_tuple:
                randao_mixes = default_tuple_of_size(
                    config.EPOCHS_PER_HISTORICAL_VECTOR, ZERO_HASH32)
            if slashings == default_tuple:
                slashings = default_tuple_of_size(
                    config.EPOCHS_PER_SLASHINGS_VECTOR, Gwei(0))

        return super().create(
            genesis_time=genesis_time,
            slot=slot,
            fork=fork,
            latest_block_header=latest_block_header,
            block_roots=block_roots,
            state_roots=state_roots,
            historical_roots=historical_roots,
            eth1_data=eth1_data,
            eth1_data_votes=eth1_data_votes,
            eth1_deposit_index=eth1_deposit_index,
            validators=validators,
            balances=balances,
            randao_mixes=randao_mixes,
            slashings=slashings,
            previous_epoch_attestations=previous_epoch_attestations,
            current_epoch_attestations=current_epoch_attestations,
            justification_bits=justification_bits,
            previous_justified_checkpoint=previous_justified_checkpoint,
            current_justified_checkpoint=current_justified_checkpoint,
            finalized_checkpoint=finalized_checkpoint,
        )

    def __str__(self) -> str:
        return (
            f"[hash_tree_root]={humanize_hash(self.hash_tree_root)}, slot={self.slot}"
        )

    @property
    def validator_count(self) -> int:
        return len(self.validators)

    def current_epoch(self, slots_per_epoch: int) -> Epoch:
        return compute_epoch_at_slot(self.slot, slots_per_epoch)

    def previous_epoch(self, slots_per_epoch: int,
                       genesis_epoch: Epoch) -> Epoch:
        current_epoch = self.current_epoch(slots_per_epoch)
        if current_epoch == genesis_epoch:
            return genesis_epoch
        else:
            return Epoch(current_epoch - 1)

    def next_epoch(self, slots_per_epoch: int) -> Epoch:
        return Epoch(self.current_epoch(slots_per_epoch) + 1)
Esempio n. 27
0
    byte,
    bytes32,
    bytes48,
    bytes96,
    uint8,
    uint256,
)


@pytest.mark.parametrize(
    ("sedes", "size"),
    (
        (boolean, 1),
        (uint8, 1),
        (uint256, 32),
        (Vector(uint8, 1), 1),
        (Vector(uint8, 2), 2),
        (Container((uint8, Vector(uint8, 4))), 5),
        (Vector(Container((uint8, Vector(uint8, 4))), 4), 20),
        (byte, 1),
        (bytes32, 32),
        (bytes48, 48),
        (bytes96, 96),
    ),
)
def test_fixed_size(sedes, size):
    assert sedes.is_fixed_sized
    assert sedes.get_fixed_size() == size


@pytest.mark.parametrize(