def beacon_block_validator(msg_forwarder: ID, msg: rpc_pb2.Message) -> bool: try: block = ssz.decode(msg.data, BeaconBlock) except (TypeError, ssz.DeserializationError) as error: logger.debug( bold_red("Failed to validate block=%s, error=%s"), encode_hex(block.signing_root), str(error), ) return False state_machine = chain.get_state_machine(block.slot - 1) state_transition = state_machine.state_transition state = chain.get_head_state() # Fast forward to state in future slot in order to pass # block.slot validity check state = state_transition.apply_state_transition( state, future_slot=block.slot, ) try: validate_proposer_signature(state, block, CommitteeConfig(state_machine.config)) except ValidationError as error: logger.debug( bold_red("Failed to validate block=%s, error=%s"), encode_hex(block.signing_root), str(error), ) return False else: return True
def run_validate_block_proposer_signature( state: BeaconState, state_machine: BaseBeaconStateMachine, block: BaseBeaconBlock) -> None: # Fast forward to state in future slot in order to pass # block.slot validity check try: future_state = state_machine.state_transition.apply_state_transition( state, future_slot=block.slot, ) except ValidationError as error: raise InvalidGossipMessage( "Failed to fast forward to state at slot=%d, error=%s", block.slot, str(error), ) try: validate_proposer_signature(future_state, block, CommitteeConfig(state_machine.config)) except ValidationError as error: logger.debug( "Failed to validate block=%s, error=%s", encode_hex(block.signing_root), str(error), )
def test_validate_proposer_signature( slots_per_epoch, shard_count, proposer_privkey, proposer_pubkey, is_valid_signature, sample_beacon_block_params, sample_beacon_state_params, target_committee_size, max_effective_balance, config): state = BeaconState(**sample_beacon_state_params).copy( validators=tuple( create_mock_validator(proposer_pubkey, config) for _ in range(10) ), balances=(max_effective_balance,) * 10, ) block = BeaconBlock(**sample_beacon_block_params) header = block.header proposed_block = block.copy( signature=bls.sign( message_hash=header.signing_root, privkey=proposer_privkey, domain=get_domain( state, SignatureDomain.DOMAIN_BEACON_PROPOSER, slots_per_epoch, ), ), ) if is_valid_signature: validate_proposer_signature( state, proposed_block, CommitteeConfig(config), ) else: with pytest.raises(ValidationError): validate_proposer_signature( state, proposed_block, CommitteeConfig(config), )
def test_validate_proposer_signature( epoch_length, shard_count, proposer_privkey, proposer_pubkey, is_valid_signature, sample_beacon_block_params, sample_beacon_state_params, beacon_chain_shard_number, genesis_epoch, target_committee_size, max_deposit_amount): state = BeaconState(**sample_beacon_state_params).copy( validator_registry=tuple( mock_validator_record(proposer_pubkey) for _ in range(10)), validator_balances=(max_deposit_amount, ) * 10, ) default_block = BeaconBlock(**sample_beacon_block_params) empty_signature_block_root = default_block.block_without_signature_root proposal_root = ProposalSignedData( state.slot, beacon_chain_shard_number, empty_signature_block_root, ).root proposed_block = BeaconBlock(**sample_beacon_block_params).copy( signature=bls.sign( message=proposal_root, privkey=proposer_privkey, domain=SignatureDomain.DOMAIN_PROPOSAL, ), ) if is_valid_signature: validate_proposer_signature( state, proposed_block, beacon_chain_shard_number, genesis_epoch, epoch_length, target_committee_size, shard_count, ) else: with pytest.raises(ValidationError): validate_proposer_signature(state, proposed_block, beacon_chain_shard_number, genesis_epoch, epoch_length, target_committee_size, shard_count)
def test_validate_proposer_signature( slots_per_epoch, shard_count, proposer_privkey, proposer_pubkey, is_valid_signature, sample_beacon_block_params, sample_beacon_state_params, target_committee_size, max_deposit_amount, config): state = BeaconState(**sample_beacon_state_params).copy( validator_registry=tuple( mock_validator(proposer_pubkey, config) for _ in range(10)), validator_balances=(max_deposit_amount, ) * 10, ) block = BeaconBlock(**sample_beacon_block_params) header = block.header proposed_block = block.copy(signature=bls.sign( message_hash=header.signing_root, privkey=proposer_privkey, domain=get_domain( Fork( config.GENESIS_FORK_VERSION.to_bytes(4, 'little'), config.GENESIS_FORK_VERSION.to_bytes(4, 'little'), config.GENESIS_EPOCH, ), slot_to_epoch(state.slot, slots_per_epoch), SignatureDomain.DOMAIN_BEACON_BLOCK, ), ), ) if is_valid_signature: validate_proposer_signature( state, proposed_block, CommitteeConfig(config), ) else: with pytest.raises(ValidationError): validate_proposer_signature( state, proposed_block, CommitteeConfig(config), )
def test_validate_proposer_signature( slots_per_epoch, max_committees_per_slot, proposer_privkey, proposer_pubkey, is_valid_signature, sample_beacon_block_params, sample_beacon_state_params, target_committee_size, max_effective_balance, config, ): state = BeaconState.create(**sample_beacon_state_params).mset( "validators", tuple( create_mock_validator(proposer_pubkey, config) for _ in range(10)), "balances", (max_effective_balance, ) * 10, ) block = BeaconBlock.create(**sample_beacon_block_params) proposed_block = SignedBeaconBlock.create( message=block, signature=bls.sign( message_hash=block.hash_tree_root, privkey=proposer_privkey, domain=get_domain(state, SignatureDomain.DOMAIN_BEACON_PROPOSER, slots_per_epoch), ), ) if is_valid_signature: validate_proposer_signature(state, proposed_block, CommitteeConfig(config)) else: with pytest.raises(ValidationError): validate_proposer_signature(state, proposed_block, CommitteeConfig(config))
def run_validate_block_proposer_signature( state: BeaconState, state_machine: BaseBeaconStateMachine, block: BaseSignedBeaconBlock) -> None: # Fast forward to state in future slot in order to pass # block.slot validity check try: future_state, _ = state_machine.apply_state_transition( state, future_slot=block.slot, ) except ValidationError as error: raise InvalidGossipMessage( f"Failed to fast forward to state at slot={block.slot}", error, ) try: validate_proposer_signature(future_state, block, state_machine.config) except ValidationError as error: raise InvalidGossipMessage( f"Failed to validate block={encode_hex(block.message.hash_tree_root)}", error, )
def apply_fast_state_transition( epochs_ctx: EpochsContext, config: Eth2Config, state: BeaconState, signed_block: BaseSignedBeaconBlock = None, future_slot: Slot = None, check_proposer_signature: bool = True, ) -> BeaconState: """ Callers should request a transition to some slot past the ``state.slot``. This can be done by providing either a ``block`` *or* a ``future_slot``. We enforce this invariant with the assertion on ``target_slot``. """ target_slot = signed_block.message.slot if signed_block else future_slot assert target_slot is not None state = process_slots(epochs_ctx, state, target_slot, config) if signed_block: if check_proposer_signature: validate_proposer_signature(state, signed_block, config) state = process_block(epochs_ctx, state, signed_block.message, config) return state