Exemple #1
0
    def _read_state_randao_mixes(self, state_root: Root,
                                 EPOCHS_PER_HISTORICAL_VECTOR: int,
                                 SLOTS_PER_EPOCH: int) -> Iterable[Root]:
        """
        Reconstructs the ``randao_mixes`` at a given state root.
        """
        state_slot = self._read_state_slot(state_root)
        state_epoch = compute_epoch_at_slot(state_slot, SLOTS_PER_EPOCH)

        finalized_slot = self.get_finalized_head(BeaconBlock).slot
        non_finalized_state_roots = dict(
            enumerate(
                self.get_state_parents(state_root,
                                       state_slot - finalized_slot),
                finalized_slot,
            ))

        # create a list of epochs that corresponds to each mix in ``state.randao_mixes``
        epochs = [
            Epoch(n)
            for n in range(state_epoch - EPOCHS_PER_HISTORICAL_VECTOR +
                           1, state_epoch + 1)
        ]
        offset = EPOCHS_PER_HISTORICAL_VECTOR - epochs[
            0] % EPOCHS_PER_HISTORICAL_VECTOR
        epochs = epochs[offset:] + epochs[:offset]

        genesis_root = self._read_state_root_at_slot(Slot(0))
        genesis_randao_mix = Root(
            Hash32(self.db[SchemaV1.state_root_to_randao_mix(genesis_root)]))

        for epoch in epochs:
            if epoch < 0:
                yield genesis_randao_mix
            elif epoch == state_epoch:
                # yield the randao mix at the particular slot
                key = SchemaV1.state_root_to_randao_mix(state_root)
                yield Root(Hash32(self.db[key]))
            else:
                # yield the randao mix at the last slot in the epoch
                slot = Slot((epoch + 1) * SLOTS_PER_EPOCH - 1)
                if slot in non_finalized_state_roots:
                    root = non_finalized_state_roots[slot]
                else:
                    root = self._read_state_root_at_slot(slot)

                key = SchemaV1.state_root_to_randao_mix(root)
                yield Root(Hash32(self.db[key]))
Exemple #2
0
 def get_state_by_slot(self, slot: Slot, state_class: Type[BeaconState],
                       config: Eth2Config) -> Optional[BeaconState]:
     key = SchemaV1.slot_to_state_root(slot)
     try:
         root = Root(Hash32(self.db[key]))
     except KeyError:
         return None
     return self.get_state_by_root(root, state_class, config)
Exemple #3
0
 def get_block_by_slot(
         self, slot: Slot,
         block_class: Type[BaseBeaconBlock]) -> Optional[BaseBeaconBlock]:
     key = SchemaV1.slot_to_block_root(slot)
     try:
         root = Root(Hash32(self.db[key]))
     except KeyError:
         return None
     return self.get_block_by_root(root, block_class)
Exemple #4
0
def _bytes_to_roots(roots_bytes: bytes) -> Iterable[Root]:
    bytes_len = len(roots_bytes)
    if bytes_len % 32 != 0:
        raise ValueError("bytes not divisible by 32")

    for i in range(0, int(bytes_len / 32)):
        start = i * 32
        end = start + 32
        yield Root(Hash32(roots_bytes[start:end]))
Exemple #5
0
 def _get_genesis_data(self) -> Tuple[Timestamp, Root]:
     key = SchemaV1.genesis_data()
     try:
         data = self.db[key]
     except KeyError:
         return default_timestamp, default_root
     genesis_time = ssz.decode(data[:8], ssz.sedes.uint64)
     genesis_validators_root = ssz.decode(data[8:], ssz.sedes.bytes32)
     return Timestamp(genesis_time), Root(genesis_validators_root)
Exemple #6
0
    def _write_state_block_header(self, state_root: Root,
                                  block_header: BeaconBlockHeader) -> None:
        block_root = Root(block_header.hash_tree_root)
        state_root_to_latest_block_header_root = SchemaV1.state_root_to_latest_block_header_root(
            state_root)
        self.db[state_root_to_latest_block_header_root] = block_root

        block_root_to_block_header = SchemaV1.block_root_to_block_header(
            block_root)
        self.db[block_root_to_block_header] = ssz.encode(block_header)
Exemple #7
0
 def _read_state_balances(self, state_root: Root,
                          VALIDATOR_REGISTRY_LIMIT: int) -> Tuple[Gwei]:
     state_root_to_balances_root = SchemaV1.state_root_to_balances_root(
         state_root)
     balances_root = Root(Hash32(self.db[state_root_to_balances_root]))
     balances_root_to_balances = SchemaV1.balances_root_to_balances(
         balances_root)
     return ssz.decode(
         self.db[balances_root_to_balances],
         ssz.List(ssz.uint64, VALIDATOR_REGISTRY_LIMIT),
     )
Exemple #8
0
    def _read_state_validators(self, state_root: Root) -> Iterable[Validator]:
        state_root_to_validators_root = SchemaV1.state_root_to_validators_root(
            state_root)
        validators_root = Root(Hash32(self.db[state_root_to_validators_root]))
        validators_root_to_roots_of_validators = SchemaV1.validators_root_to_roots_of_validators(
            validators_root)
        roots = _bytes_to_roots(
            self.db[validators_root_to_roots_of_validators])

        for root in roots:
            yield ssz.decode(self.db[bytes(root)], Validator)
Exemple #9
0
 def _read_state_block_roots(
         self, state_root: Root,
         SLOTS_PER_HISTORICAL_ROOT: int) -> Iterable[Root]:
     """
     Reconstructs ``state.block_roots`` at a given state root.
     """
     for root in self._read_state_state_roots(state_root,
                                              SLOTS_PER_HISTORICAL_ROOT):
         if root == default_root:
             yield default_root
         else:
             key = SchemaV1.state_root_to_latest_block_header_root(root)
             yield Root(Hash32(self.db[key]))
Exemple #10
0
def sign(duty: Duty, operation: Operation,
         private_key_provider: PrivateKeyProvider) -> BLSSignature:
    privkey = private_key_provider(duty.validator_public_key)
    # TODO use correct ``domain`` value
    # NOTE currently only uses part of the domain value
    # need to get fork from the state and compute the full domain value locally
    # NOTE: hardcoded for testing, based on generating the minimal set of validators
    genesis_validators_root = Root(
        Hash32(
            bytes.fromhex(
                "83431ec7fcf92cfc44947fc0418e831c25e1d0806590231c439830db7ad54fda"
            )))
    domain = compute_domain(duty.signature_domain,
                            genesis_validators_root=genesis_validators_root)
    signing_root = compute_signing_root(operation, domain)

    return bls.sign(privkey, signing_root)
def test_get_matching_head_attestations(genesis_state, config):
    some_epoch = GENESIS_EPOCH + 20
    some_slot = (
        compute_start_slot_at_epoch(some_epoch, config.SLOTS_PER_EPOCH)
        + config.SLOTS_PER_EPOCH // 4
    )
    some_target_root = Root(Hash32(b"\x33" * 32))
    target_attestations = tuple(
        (
            PendingAttestation.create(
                data=AttestationData.create(
                    slot=some_slot - 1,
                    index=0,
                    beacon_block_root=some_target_root,
                    target=Checkpoint.create(
                        epoch=some_epoch - 1, root=some_target_root
                    ),
                )
            )
            for _ in range(3)
        )
    )
    current_epoch_attestations = target_attestations + tuple(
        (
            PendingAttestation.create(
                data=AttestationData.create(
                    beacon_block_root=b"\x44" * 32,
                    target=Checkpoint.create(epoch=some_epoch - 1),
                )
            )
            for _ in range(3)
        )
    )
    state = genesis_state.mset(
        "slot",
        some_slot,
        "block_roots",
        tuple(some_target_root for _ in range(config.SLOTS_PER_HISTORICAL_ROOT)),
        "current_epoch_attestations",
        current_epoch_attestations,
    )

    attestations = get_matching_head_attestations(state, some_epoch, config)

    assert attestations == target_attestations
Exemple #12
0
 def _randao_provider_of_epoch_signature(
     public_key: BLSPubkey, epoch: Epoch
 ) -> BLSSignature:
     privkey = private_key_provider(public_key)
     # NOTE: hardcoded for testing, based on generating the minimal set of validators
     genesis_validators_root = Root(
         Hash32(
             bytes.fromhex(
                 "83431ec7fcf92cfc44947fc0418e831c25e1d0806590231c439830db7ad54fda"
             )
         )
     )
     domain = compute_domain(
         SignatureDomain.DOMAIN_RANDAO,
         genesis_validators_root=genesis_validators_root,
     )
     signing_root = compute_signing_root(SerializableUint64(epoch), domain)
     return bls.sign(privkey, signing_root)
Exemple #13
0
 def _get_justified_head(
     cls, db: DatabaseAPI, block_class: Type[BaseBeaconBlock]
 ) -> BaseBeaconBlock:
     justified_head_root = cls._get_justified_head_root(db)
     return cls._get_block_by_root(db, Root(justified_head_root), block_class)
Exemple #14
0
 def _get_canonical_head(
     cls, db: DatabaseAPI, block_class: Type[BaseBeaconBlock]
 ) -> BaseBeaconBlock:
     canonical_head_root = cls._get_canonical_head_root(db)
     return cls._get_block_by_root(db, Root(canonical_head_root), block_class)
def _mini_stf(state: BeaconState, block: Optional[BeaconBlock],
              config: Eth2Config) -> BeaconState:
    """
    A simplified state transition for testing state storage.

    - updates ``state_roots`` with the previous slot's state root
    - updates ``block_roots`` with the previous slot's block root
    - updates ``randao_mixes`` with an arbitrary mix at the current epoch
    - creates a new ``latest_block_header`` and adds it to the state
    - fills in the rest of the attributes with arbitrary values
    """
    current_slot = state.slot + 1
    current_epoch = current_slot // config.SLOTS_PER_EPOCH

    if block:
        latest_block_header = block.header
    else:
        latest_block_header = state.latest_block_header

    # state changes that depend on the previous state for retrieval
    randao_mix = Root(Hash32(current_slot.to_bytes(32, byteorder="little")))
    state = (state.transform(
        ("state_roots", state.slot % config.SLOTS_PER_HISTORICAL_ROOT),
        state.hash_tree_root,
    ).transform(
        ("block_roots", state.slot % config.SLOTS_PER_HISTORICAL_ROOT),
        state.latest_block_header.hash_tree_root,
    ).transform(
        ("randao_mixes", current_epoch % config.EPOCHS_PER_HISTORICAL_VECTOR),
        randao_mix,
    ).mset("slot", current_slot, "latest_block_header", latest_block_header))

    # state changes that do not depend on the previous state for retrieval
    new_validators = [
        Validator.create(pubkey=BLSPubkey(n.to_bytes(48, byteorder="little")))
        for n in range(current_slot, current_slot + 20)
    ]
    new_eth1_data_votes = [
        Eth1Data.create(
            deposit_root=Root(Hash32(n.to_bytes(32, byteorder="little"))))
        for n in range(current_slot, current_slot + 7)
    ]
    new_previous_epoch_attestations = [
        PendingAttestation.create(proposer_index=ValidatorIndex(n))
        for n in range(current_slot, current_slot + 5)
    ]
    new_current_epoch_attestations = [
        PendingAttestation.create(proposer_index=ValidatorIndex(n))
        for n in range(current_slot + 5, current_slot + 10)
    ]
    state = state.mset(
        "validators",
        new_validators,
        "balances",
        (32, ) * len(new_validators),
        "eth1_data_votes",
        new_eth1_data_votes,
        "eth1_data",
        new_eth1_data_votes[0],
        "previous_epoch_attestations",
        new_previous_epoch_attestations,
        "current_epoch_attestations",
        new_current_epoch_attestations,
        "previous_justified_checkpoint",
        Checkpoint.create(epoch=Epoch(current_slot + 42)),
        "current_justified_checkpoint",
        Checkpoint.create(epoch=Epoch(current_slot + 43)),
        "finalized_checkpoint",
        Checkpoint.create(epoch=Epoch(current_slot + 44)),
    )

    return state
Exemple #16
0
 def get_justified_head(
         self, block_class: Type[BaseBeaconBlock]) -> BaseBeaconBlock:
     justified_head_root_key = SchemaV1.justified_head_root()
     justified_head_root = Root(Hash32(self.db[justified_head_root_key]))
     return self.get_block_by_root(justified_head_root, block_class)
Exemple #17
0
 def _read_state_parent_state_root(self, state_root: Root) -> Root:
     key = SchemaV1.state_root_to_parent_state_root(state_root)
     return Root(Hash32(self.db[key]))
Exemple #18
0
 def get_finalized_head(
         self, block_class: Type[BaseBeaconBlock]) -> BaseBeaconBlock:
     finalized_head_root_key = SchemaV1.finalized_head_root()
     finalized_head_root = Root(Hash32(self.db[finalized_head_root_key]))
     return self.get_block_by_root(finalized_head_root, block_class)
Exemple #19
0
from eth.constants import ZERO_HASH32
from eth_typing import BLSPubkey, BLSSignature

from eth2.beacon.typing import Epoch, Root, Timestamp

EMPTY_SIGNATURE = BLSSignature(b"\x00" * 96)
EMPTY_PUBKEY = BLSPubkey(b"\x00" * 48)
GWEI_PER_ETH = 10**9
FAR_FUTURE_EPOCH = Epoch(2**64 - 1)

ZERO_ROOT = Root(ZERO_HASH32)
GENESIS_PARENT_ROOT = ZERO_ROOT

ZERO_TIMESTAMP = Timestamp(0)

MAX_INDEX_COUNT = 2**40

MAX_RANDOM_BYTE = 2**8 - 1

BASE_REWARDS_PER_EPOCH = 4

DEPOSIT_CONTRACT_TREE_DEPTH = 2**5

SECONDS_PER_DAY = 86400

JUSTIFICATION_BITS_LENGTH = 4
Exemple #20
0
 def _read_state_root_at_slot(self, slot: Slot) -> Root:
     key = SchemaV1.slot_to_state_root(slot)
     return Root(Hash32(self.db[key]))
Exemple #21
0
 def _read_state_block_header(self, state_root: Root) -> BeaconBlockHeader:
     block_root = Root(
         Hash32(self.db[SchemaV1.state_root_to_latest_block_header_root(
             state_root)]))
     key = SchemaV1.block_root_to_block_header(block_root)
     return ssz.decode(self.db[key], BeaconBlockHeader)
Exemple #22
0
    )


def sign_transaction(*, message_hash: Hash32, privkey: int, state: BeaconState,
                     slot: Slot, signature_domain: SignatureDomain,
                     slots_per_epoch: int) -> BLSSignature:
    domain = get_domain(
        state,
        signature_domain,
        slots_per_epoch,
        message_epoch=compute_epoch_at_slot(slot, slots_per_epoch),
    )
    return bls.sign(message_hash=message_hash, privkey=privkey, domain=domain)


SAMPLE_HASH_1 = Root(Hash32(b"\x11" * 32))
SAMPLE_HASH_2 = Hash32(b"\x22" * 32)


def create_block_header_with_signature(
    state: BeaconState,
    body_root: Hash32,
    privkey: int,
    slots_per_epoch: int,
    parent_root: Root = SAMPLE_HASH_1,
    state_root: Hash32 = SAMPLE_HASH_2,
) -> SignedBeaconBlockHeader:
    block_header = BeaconBlockHeader.create(
        slot=state.slot,
        parent_root=parent_root,
        state_root=state_root,
Exemple #23
0
 def get_canonical_head(
         self, block_class: Type[BaseBeaconBlock]) -> BaseBeaconBlock:
     canonical_head_root_key = SchemaV1.canonical_head_root()
     canonical_head_root = Root(Hash32(self.db[canonical_head_root_key]))
     return self.get_block_by_root(canonical_head_root, block_class)