def create_block_on_state( *, state: BeaconState, config: BeaconConfig, state_machine: BaseBeaconStateMachine, block_class: BaseBeaconBlock, parent_block: BaseBeaconBlock, slot: SlotNumber, validator_index: ValidatorIndex, privkey: int, attestations: Sequence[Attestation], check_proposer_index: bool = True) -> BaseBeaconBlock: """ Create a beacon block with the given parameters. """ # Check proposer if check_proposer_index: validate_proposer_index(state, config, slot, validator_index) # Prepare block: slot and parent_root block = block_class.from_parent( parent_block=parent_block, block_params=FromBlockParams(slot=slot), ) # TODO: Add more operations randao_reveal = ZERO_HASH32 eth1_data = Eth1Data.create_empty_data() body = BeaconBlockBody.create_empty_body().copy( attestations=attestations, ) block = block.copy( randao_reveal=randao_reveal, eth1_data=eth1_data, body=body, ) # Apply state transition to get state root state, block = state_machine.import_block(block, check_proposer_signature=True) # Sign empty_signature_block_root = block.block_without_signature_root proposal_root = ProposalSignedData( slot, config.BEACON_CHAIN_SHARD_NUMBER, empty_signature_block_root, ).root domain = get_domain( state.fork, slot_to_epoch(slot, config.EPOCH_LENGTH), SignatureDomain.DOMAIN_PROPOSAL, ) block = block.copy(signature=bls.sign( message=proposal_root, privkey=privkey, domain=domain, ), ) return block
def create_block_on_state(state: BeaconState, config: BeaconConfig, block_class: BaseBeaconBlock, parent_block: BaseBeaconBlock, slot: SlotNumber, validator_index: int, privkey: int, attestations: Sequence[Attestation]): """ Create a beacon block with the given parameters. """ # Check proposer beacon_proposer_index = get_beacon_proposer_index( state.copy(slot=slot, ), slot, config.EPOCH_LENGTH, config.TARGET_COMMITTEE_SIZE, config.SHARD_COUNT, ) if validator_index != beacon_proposer_index: raise ProposerIndexError # Prepare block: slot and parent_root block = block_class.from_parent( parent_block=parent_block, block_params=FromBlockParams(slot=slot), ) # TODO: Add more operations randao_reveal = ZERO_HASH32 eth1_data = Eth1Data.create_empty_data() body = BeaconBlockBody.create_empty_body().copy( attestations=attestations, ) block = block.copy( randao_reveal=randao_reveal, eth1_data=eth1_data, body=body, ) # Sign empty_signature_block_root = block.block_without_signature_root proposal_root = ProposalSignedData( slot, config.BEACON_CHAIN_SHARD_NUMBER, empty_signature_block_root, ).root domain = get_domain( state.fork, slot, SignatureDomain.DOMAIN_PROPOSAL, ) block = block.copy(signature=bls.sign( message=proposal_root, privkey=privkey, domain=domain, ), ) return block
def create_block_on_state( *, state: BeaconState, config: Eth2Config, state_machine: BaseBeaconStateMachine, block_class: Type[BaseBeaconBlock], parent_block: BaseBeaconBlock, slot: Slot, validator_index: ValidatorIndex, privkey: int, attestations: Sequence[Attestation], check_proposer_index: bool = True) -> BaseBeaconBlock: """ Create a beacon block with the given parameters. """ # Check proposer if check_proposer_index: validate_proposer_index(state, config, slot, validator_index) # Prepare block: slot and previous_block_root block = block_class.from_parent( parent_block=parent_block, block_params=FromBlockParams(slot=slot), ) # TODO: Add more operations randao_reveal = _generate_randao_reveal(privkey, slot, state.fork, config) eth1_data = Eth1Data.create_empty_data() body = BeaconBlockBody.create_empty_body().copy( randao_reveal=randao_reveal, eth1_data=eth1_data, attestations=attestations, ) block = block.copy(body=body, ) # Apply state transition to get state root state, block = state_machine.import_block(block, check_proposer_signature=False) # Sign # TODO make sure we use the correct signed_root signature = sign_transaction( message_hash=block.signed_root, privkey=privkey, fork=state.fork, slot=slot, signature_domain=SignatureDomain.DOMAIN_BEACON_BLOCK, slots_per_epoch=config.SLOTS_PER_EPOCH, ) block = block.copy(signature=signature, ) return block
def get_genesis_block(startup_state_root: Hash32, genesis_slot: SlotNumber, block_class: Type[BaseBeaconBlock]) -> BaseBeaconBlock: return block_class( slot=genesis_slot, parent_root=ZERO_HASH32, state_root=startup_state_root, randao_reveal=ZERO_HASH32, eth1_data=Eth1Data.create_empty_data(), signature=EMPTY_SIGNATURE, body=BeaconBlockBody.create_empty_body(), )
def test_get_genesis_block(): startup_state_root = b'\x10' * 32 genesis_slot = 10 genesis_block = get_genesis_block(startup_state_root, genesis_slot, BeaconBlock) assert genesis_block.slot == genesis_slot assert genesis_block.parent_root == ZERO_HASH32 assert genesis_block.state_root == startup_state_root assert genesis_block.randao_reveal == ZERO_HASH32 assert genesis_block.eth1_data == Eth1Data.create_empty_data() assert genesis_block.signature == EMPTY_SIGNATURE assert genesis_block.body.is_empty
def create_test_block(parent=None, **kwargs): defaults = { "slot": 0, "parent_root": ZERO_HASH32, "state_root": ZERO_HASH32, # note: not the actual genesis state root "randao_reveal": EMPTY_SIGNATURE, "eth1_data": Eth1Data.create_empty_data(), "signature": EMPTY_SIGNATURE, "body": BeaconBlockBody.create_empty_body() } if parent is not None: kwargs["parent_root"] = parent.root kwargs["slot"] = parent.slot + 1 return BeaconBlock(**merge(defaults, kwargs))
def create_mock_genesis( num_validators: int, config: BeaconConfig, keymap: Dict[BLSPubkey, int], genesis_block_class: Type[BaseBeaconBlock], genesis_time: Timestamp = 0) -> Tuple[BeaconState, BaseBeaconBlock]: latest_eth1_data = Eth1Data.create_empty_data() assert num_validators <= len(keymap) pubkeys = list(keymap)[:num_validators] initial_validator_deposits = create_mock_initial_validator_deposits( num_validators=num_validators, config=config, pubkeys=pubkeys, keymap=keymap, ) state = get_initial_beacon_state( initial_validator_deposits=initial_validator_deposits, genesis_time=genesis_time, latest_eth1_data=latest_eth1_data, genesis_slot=config.GENESIS_SLOT, genesis_epoch=config.GENESIS_EPOCH, genesis_fork_version=config.GENESIS_FORK_VERSION, genesis_start_shard=config.GENESIS_START_SHARD, shard_count=config.SHARD_COUNT, seed_lookahead=config.SEED_LOOKAHEAD, latest_block_roots_length=config.LATEST_BLOCK_ROOTS_LENGTH, latest_index_roots_length=config.LATEST_INDEX_ROOTS_LENGTH, epoch_length=config.EPOCH_LENGTH, max_deposit_amount=config.MAX_DEPOSIT_AMOUNT, latest_penalized_exit_length=config.LATEST_PENALIZED_EXIT_LENGTH, latest_randao_mixes_length=config.LATEST_RANDAO_MIXES_LENGTH, entry_exit_delay=config.ENTRY_EXIT_DELAY, ) block = get_genesis_block( startup_state_root=state.root, genesis_slot=config.GENESIS_SLOT, block_class=genesis_block_class, ) assert len(state.validator_registry) == num_validators return state, block
async def test_send_single_block(request, event_loop): alice, msg_buffer = await get_command_setup(request, event_loop) request_id = 5 block = BeaconBlock( slot=1, parent_root=ZERO_HASH32, state_root=ZERO_HASH32, randao_reveal=EMPTY_SIGNATURE, eth1_data=Eth1Data.create_empty_data(), signature=EMPTY_SIGNATURE, body=BeaconBlockBody.create_empty_body(), ) alice.sub_proto.send_blocks((block,), 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": (ssz.encode(block),), }
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, parent_root=ZERO_HASH32, state_root=ZERO_HASH32, randao_reveal=ZERO_HASH32, eth1_data=Eth1Data.create_empty_data(), 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, "blocks": blocks, }
def create_block_on_state( *, state: BeaconState, config: BeaconConfig, state_machine: BaseBeaconStateMachine, block_class: Type[BaseBeaconBlock], parent_block: BaseBeaconBlock, slot: Slot, validator_index: ValidatorIndex, privkey: int, attestations: Sequence[Attestation], check_proposer_index: bool = True) -> BaseBeaconBlock: """ Create a beacon block with the given parameters. """ # Check proposer if check_proposer_index: validate_proposer_index(state, config, slot, validator_index) # Prepare block: slot and parent_root block = block_class.from_parent( parent_block=parent_block, block_params=FromBlockParams(slot=slot), ) # TODO: Add more operations randao_reveal = EMPTY_SIGNATURE eth1_data = Eth1Data.create_empty_data() body = BeaconBlockBody.create_empty_body().copy( attestations=attestations, ) block = block.copy( randao_reveal=randao_reveal, eth1_data=eth1_data, body=body, ) # Apply state transition to get state root state, block = state_machine.import_block(block, check_proposer_signature=False) # Sign empty_signature_block_root = block.block_without_signature_root proposal_root = Proposal( slot, config.BEACON_CHAIN_SHARD_NUMBER, empty_signature_block_root, ).root signature = sign_transaction( message_hash=proposal_root, privkey=privkey, fork=state.fork, slot=slot, signature_domain=SignatureDomain.DOMAIN_PROPOSAL, slots_per_epoch=config.SLOTS_PER_EPOCH, ) block = block.copy(signature=signature, ) return block