async def test_send_multiple_blocks(request, event_loop): alice, msg_buffer = await get_command_setup(request, event_loop) request_id = 5 blocks = tuple( BeaconBlock( slot=slot, previous_block_root=ZERO_HASH32, state_root=ZERO_HASH32, signature=EMPTY_SIGNATURE, body=BeaconBlockBody.create_empty_body(), ) for slot in range(3) ) alice.sub_proto.send_blocks(blocks, request_id=request_id) message = await msg_buffer.msg_queue.get() assert isinstance(message.command, BeaconBlocks) assert message.payload == { "request_id": request_id, "encoded_blocks": tuple(ssz.encode(block) for block in blocks), }
def create_mock_genesis_validator_deposits_and_root( num_validators: int, config: Eth2Config, pubkeys: Sequence[BLSPubkey], keymap: Dict[BLSPubkey, int]) -> Tuple[Tuple[Deposit, ...], Hash32]: # Mock data withdrawal_credentials = Hash32(b'\x22' * 32) fork = Fork( previous_version=config.GENESIS_FORK_VERSION.to_bytes(4, 'little'), current_version=config.GENESIS_FORK_VERSION.to_bytes(4, 'little'), epoch=config.GENESIS_EPOCH, ) deposit_data_array = tuple() # type: Tuple[DepositData, ...] deposit_data_leaves = tuple() # type: Tuple[Hash32, ...] for i in range(num_validators): deposit_data = create_mock_deposit_data( config=config, pubkeys=pubkeys, keymap=keymap, validator_index=ValidatorIndex(i), withdrawal_credentials=withdrawal_credentials, fork=fork, ) item = hash_eth2(ssz.encode(deposit_data)) deposit_data_leaves += (item, ) deposit_data_array += (deposit_data, ) tree = calc_merkle_tree_from_leaves(deposit_data_leaves) root = get_merkle_root(deposit_data_leaves) genesis_validator_deposits = tuple( Deposit( proof=get_merkle_proof(tree, item_index=i), index=i, deposit_data=deposit_data_array[i], ) for i in range(num_validators)) return genesis_validator_deposits, root
async def test_send_single_attestation(request, event_loop): alice, msg_buffer = await get_command_setup(request, event_loop) attestation = Attestation( aggregation_bitfield=b"\x00\x00\x00", data=AttestationData( slot=0, beacon_block_root=ZERO_HASH32, source_epoch=SERENITY_CONFIG.GENESIS_EPOCH, target_root=ZERO_HASH32, source_root=ZERO_HASH32, shard=1, previous_crosslink=Crosslink(SERENITY_CONFIG.GENESIS_EPOCH, ZERO_HASH32), crosslink_data_root=ZERO_HASH32, ), custody_bitfield=b"\x00\x00\x00", ) alice.sub_proto.send_attestation_records((attestation,)) message = await msg_buffer.msg_queue.get() assert isinstance(message.command, Attestations) assert message.payload["encoded_attestations"] == (ssz.encode(attestation),)
async def test_send_single_attestation(request, event_loop): alice, msg_buffer = await get_command_setup(request, event_loop) attestation = Attestation( data=AttestationData( slot=0, shard=1, beacon_block_root=ZERO_HASH32, epoch_boundary_root=ZERO_HASH32, shard_block_root=ZERO_HASH32, latest_crosslink_root=ZERO_HASH32, justified_epoch=SERENITY_CONFIG.GENESIS_EPOCH, justified_block_root=ZERO_HASH32, ), aggregation_bitfield=b"\x00\x00\x00", custody_bitfield=b"\x00\x00\x00", ) alice.sub_proto.send_attestation_records((attestation,)) message = await msg_buffer.msg_queue.get() assert isinstance(message.command, AttestationRecords) assert message.payload == (ssz.encode(attestation),)
def create_mock_deposit(config, sample_beacon_state_params, keymap, pubkeys, withdrawal_credentials, validator_index): state = BeaconState(**sample_beacon_state_params).copy( slot=1, validator_registry=(), ) fork = Fork( previous_version=config.GENESIS_FORK_VERSION.to_bytes(4, 'little'), current_version=config.GENESIS_FORK_VERSION.to_bytes(4, 'little'), epoch=config.GENESIS_EPOCH, ) deposit_data = create_mock_deposit_data( config=config, pubkeys=pubkeys, keymap=keymap, validator_index=validator_index, withdrawal_credentials=withdrawal_credentials, fork=fork, ) item = hash_eth2(ssz.encode(deposit_data)) test_deposit_data_leaves = (item, ) tree = calc_merkle_tree_from_leaves(test_deposit_data_leaves) root = get_merkle_root(test_deposit_data_leaves) proof = list(get_merkle_proof(tree, item_index=validator_index)) state = state.copy(latest_eth1_data=state.latest_eth1_data.copy( deposit_root=root, ), ) deposit = Deposit( proof=proof, index=validator_index, deposit_data=deposit_data, ) return state, deposit
def FuzzerRunOne(input_data: bytes) -> typing.Optional[bytes]: test_case = ssz.decode(input_data, BlockTestCase) try: post = st_instance.apply_state_transition( state=test_case.pre, block=test_case.block, check_proposer_signature=True, ) if VALIDATE_STATE_ROOT: # NOTE trinity performs state root validation at a higher level # so we perform it here if needed. # See https://github.com/ethereum/trinity/issues/1340 # https://github.com/ethereum/trinity/blob/0d53ef2cf57458d11c5a5b0e5546b026f2fce3f9/eth2/beacon/chains/base.py#L413-L415 # TODO when updating spec versions, ensure this matches the relevant # Trinity code post_block = test_case.block.copy(state_root=post.hash_tree_root) # Raises a ValidationError if state_roots are different validate_imported_block_unchanged(test_case.block, post_block) except ValidationError as e: return None # NOTE - signature verification should do nothing with bls disabled return ssz.encode(post)
def send_new_block(self, block: BaseBeaconBlock) -> None: cmd = NewBeaconBlock(self.cmd_id_offset, self.snappy_support) header, body = cmd.encode( NewBeaconBlockMessage(encoded_block=ssz.encode(block), )) self.transport.send(header, body)
def signed_root(self) -> Hash32: # Use SSZ built-in function if self._signed_root is None: self._signed_root = hash_eth2( ssz.encode(self.copy(signature=EMPTY_SIGNATURE))) return self._signed_root
def _serialize_ssz_msg(msg: MsgType) -> bytes: try: msg_bytes = ssz.encode(msg) return _serialize_bytes(msg_bytes) except ssz.SerializationError as error: raise WriteMessageFailure(f"failed to serialize msg={msg}") from error
def _serialize_uint(item: int) -> bytes: return ssz.encode(item, sedes=ssz.sedes.uint64)
def test_round_trip_codec(value, sedes): if isinstance(sedes, str): sedes_obj = eval(sedes) else: sedes_obj = sedes assert decode(encode(value, sedes), sedes_obj) == value
def slot_to_state_root(slot: Slot) -> bytes: return b"v1:beacon:slot-to-state-root:" + ssz.encode(slot, ssz.uint64)
def _persist_block_chain( cls, db: BaseDB, blocks: Iterable[BaseBeaconBlock], block_class: Type[BaseBeaconBlock] ) -> Tuple[Tuple[BaseBeaconBlock, ...], Tuple[BaseBeaconBlock, ...]]: blocks_iterator = iter(blocks) try: first_block = first(blocks_iterator) except StopIteration: return tuple(), tuple() try: previous_canonical_head = cls._get_canonical_head( db, block_class).signed_root head_score = cls._get_score(db, previous_canonical_head) except CanonicalHeadNotFound: no_canonical_head = True else: no_canonical_head = False is_genesis = first_block.previous_block_root == GENESIS_PARENT_HASH if not is_genesis and not cls._block_exists( db, first_block.previous_block_root): raise ParentNotFound( "Cannot persist block ({}) with unknown parent ({})".format( encode_hex(first_block.signed_root), encode_hex(first_block.previous_block_root), )) if is_genesis: score = 0 # TODO: this should probably be done as part of the fork choice rule processing db.set( SchemaV1.make_finalized_head_root_lookup_key(), first_block.signed_root, ) else: score = first_block.slot curr_block_head = first_block db.set( curr_block_head.signed_root, ssz.encode(curr_block_head), ) cls._add_block_root_to_slot_lookup(db, curr_block_head) cls._set_block_scores_to_db(db, curr_block_head) orig_blocks_seq = concat([(first_block, ), blocks_iterator]) for parent, child in sliding_window(2, orig_blocks_seq): if parent.signed_root != child.previous_block_root: raise ValidationError( "Non-contiguous chain. Expected {} to have {} as parent but was {}" .format( encode_hex(child.signed_root), encode_hex(parent.signed_root), encode_hex(child.previous_block_root), )) curr_block_head = child db.set( curr_block_head.signed_root, ssz.encode(curr_block_head), ) cls._add_block_root_to_slot_lookup(db, curr_block_head) score = cls._set_block_scores_to_db(db, curr_block_head) if no_canonical_head: return cls._set_as_canonical_chain_head( db, curr_block_head.signed_root, block_class) if score > head_score: return cls._set_as_canonical_chain_head( db, curr_block_head.signed_root, block_class) else: return tuple(), tuple()
async def broadcast_attestation(self, attestation: Attestation) -> None: await self._broadcast_data(PUBSUB_TOPIC_BEACON_ATTESTATION, ssz.encode(attestation))
async def broadcast_beacon_block(self, block: BaseBeaconBlock) -> None: await self._broadcast_data(PUBSUB_TOPIC_BEACON_BLOCK, ssz.encode(block))
def test_metadata_roundtrip(): meta = MetaData.create(seq_number=2000, attnets=(True, False) * 32) meta_encoded = ssz.encode(meta) meta_recovered = ssz.decode(meta_encoded, MetaData) assert meta_recovered == meta
def slot_to_block_root(slot: Slot) -> bytes: return b"v1:beacon:slot-to-block-root:" + ssz.encode(slot, ssz.uint64)
def _persist_state(cls, db: BaseDB, state: BeaconState) -> None: db.set( state.root, ssz.encode(state), )
def slot_to_randao_mix(slot: Slot) -> bytes: return b"v1:beacon:slot-to-randao-mix:" + ssz.encode(slot, ssz.uint64)
def test_defaults(sample_voluntary_exit_params): exit = VoluntaryExit(**sample_voluntary_exit_params) assert exit.signature[0] == sample_voluntary_exit_params["signature"][0] assert ssz.encode(exit)
def _set_deposit_data( db: DatabaseAPI, index: int, deposit_data: DepositData ) -> None: db[SchemaV1.make_deposit_data_lookup_key(index)] = ssz.encode(deposit_data)
def test_uint(bit_length, value, serialized): uint = UInt(bit_length) assert encode_hex(ssz.encode(value, uint)) == serialized assert ssz.decode(decode_hex(serialized), uint) == value
def test_defaults(sample_fork_params): fork = Fork(**sample_fork_params) assert fork.previous_version == sample_fork_params["previous_version"] assert fork.current_version == sample_fork_params["current_version"] assert fork.epoch == sample_fork_params["epoch"] assert ssz.encode(fork)
def test_boolean(value, serialized): assert encode_hex(ssz.encode(value, boolean)) == serialized assert ssz.decode(decode_hex(serialized), boolean) == value
def hash(self) -> Hash32: if self._hash is None: self._hash = hash_eth2(ssz.encode(self)) return self._hash
def send_attestation_records(self, attestations: Tuple[Attestation, ...]) -> None: cmd = Attestations(self.cmd_id_offset, self.snappy_support) header, body = cmd.encode(AttestationsMessage( encoded_attestations=tuple(ssz.encode(attestation) for attestation in attestations)), ) self.transport.send(header, body)
def _persist_block_chain( cls, db: DatabaseAPI, blocks: Iterable[BaseBeaconBlock], block_class: Type[BaseBeaconBlock], fork_choice_scorings: Iterable[ForkChoiceScoringFn], ) -> Tuple[Tuple[BaseBeaconBlock, ...], Tuple[BaseBeaconBlock, ...]]: blocks_iterator = iter(blocks) scorings_iterator = iter(fork_choice_scorings) try: first_block = first(blocks_iterator) first_scoring = first(scorings_iterator) except StopIteration: return tuple(), tuple() try: previous_canonical_head = cls._get_canonical_head( db, block_class).signing_root head_score = cls._get_score(db, previous_canonical_head) except CanonicalHeadNotFound: no_canonical_head = True else: no_canonical_head = False is_genesis = first_block.is_genesis if not is_genesis and not cls._block_exists(db, first_block.parent_root): raise ParentNotFound( "Cannot persist block ({}) with unknown parent ({})".format( encode_hex(first_block.signing_root), encode_hex(first_block.parent_root), )) score = first_scoring(first_block) curr_block_head = first_block db.set(curr_block_head.signing_root, ssz.encode(curr_block_head)) cls._add_block_root_to_slot_lookup(db, curr_block_head) cls._set_block_score_to_db(db, curr_block_head, score) cls._add_attestations_root_to_block_lookup(db, curr_block_head) orig_blocks_seq = concat([(first_block, ), blocks_iterator]) for parent, child in sliding_window(2, orig_blocks_seq): if parent.signing_root != child.parent_root: raise ValidationError( "Non-contiguous chain. Expected {} to have {} as parent but was {}" .format( encode_hex(child.signing_root), encode_hex(parent.signing_root), encode_hex(child.parent_root), )) curr_block_head = child db.set(curr_block_head.signing_root, ssz.encode(curr_block_head)) cls._add_block_root_to_slot_lookup(db, curr_block_head) cls._add_attestations_root_to_block_lookup(db, curr_block_head) # NOTE: len(scorings_iterator) should equal len(blocks_iterator) try: next_scoring = next(scorings_iterator) except StopIteration: raise MissingForkChoiceScoringFns score = next_scoring(curr_block_head) cls._set_block_score_to_db(db, curr_block_head, score) if no_canonical_head: return cls._set_as_canonical_chain_head( db, curr_block_head.signing_root, block_class) if score > head_score: return cls._set_as_canonical_chain_head( db, curr_block_head.signing_root, block_class) else: return tuple(), tuple()
def test_list_serialize_values_no_element_sedes(value, expected): assert encode(value) == expected
def test_uint(uint_and_value): uint, value = uint_and_value assert ssz.hash_tree_root(value, uint) == ssz.encode(value, uint).ljust( CHUNK_SIZE, b"\x00")
def test_defaults(sample_transfer_params): transfer = Transfer(**sample_transfer_params) assert transfer.recipient == sample_transfer_params['recipient'] assert ssz.encode(transfer)