def validate_header(cls, header: BlockHeader, parent_header: BlockHeader) -> None: """ :raise evm.exceptions.ValidationError: if the header is not valid """ if parent_header is None: # to validate genesis header, check if it equals canonical header at block number 0 raise ValidationError("Must have access to parent header to validate current header") else: validate_length_lte(header.extra_data, 32, title="BlockHeader.extra_data") validate_gas_limit(header.gas_limit, parent_header.gas_limit) # timestamp if header.timestamp <= parent_header.timestamp: raise ValidationError( "timestamp must be strictly later than parent, but is {} seconds before.\n" "- child : {}\n" "- parent : {}. ".format( parent_header.timestamp - header.timestamp, header.timestamp, parent_header.timestamp, ) ) cls.validate_seal(header)
def validate(self): if not self.is_genesis: parent_header = self.get_parent_header() self.validate_gas_limit() validate_length_lte(self.header.extra_data, 32, title="BlockHeader.extra_data") # timestamp if self.header.timestamp < parent_header.timestamp: raise ValidationError( "`timestamp` is before the parent block's timestamp.\n" "- block : {0}\n" "- parent : {1}. ".format( self.header.timestamp, parent_header.timestamp, ) ) elif self.header.timestamp == parent_header.timestamp: raise ValidationError( "`timestamp` is equal to the parent block's timestamp\n" "- block : {0}\n" "- parent: {1}. ".format( self.header.timestamp, parent_header.timestamp, ) ) # XXX: Should these and some other checks be moved into # VM.validate_block(), as they apply to all block flavours? if len(self.uncles) > MAX_UNCLES: raise ValidationError( "Blocks may have a maximum of {0} uncles. Found " "{1}.".format(MAX_UNCLES, len(self.uncles)) ) for uncle in self.uncles: self.validate_uncle(uncle) if not self.chaindb.exists(self.header.state_root): raise ValidationError( "`state_root` was not found in the db.\n" "- state_root: {0}".format( self.header.state_root, ) ) local_uncle_hash = keccak(rlp.encode(self.uncles)) if local_uncle_hash != self.header.uncles_hash: raise ValidationError( "`uncles_hash` and block `uncles` do not match.\n" " - num_uncles : {0}\n" " - block uncle_hash : {1}\n" " - header uncle_hash: {2}".format( len(self.uncles), local_uncle_hash, self.header.uncle_hash, ) ) super(FrontierBlock, self).validate()
def validate_block(self, block): if not block.is_genesis: parent_header = get_parent_header(block.header, self.chaindb) validate_gas_limit(block.header.gas_limit, parent_header.gas_limit) validate_length_lte(block.header.extra_data, 32, title="BlockHeader.extra_data") # timestamp if block.header.timestamp < parent_header.timestamp: raise ValidationError( "`timestamp` is before the parent block's timestamp.\n" "- block : {0}\n" "- parent : {1}. ".format( block.header.timestamp, parent_header.timestamp, )) elif block.header.timestamp == parent_header.timestamp: raise ValidationError( "`timestamp` is equal to the parent block's timestamp\n" "- block : {0}\n" "- parent: {1}. ".format( block.header.timestamp, parent_header.timestamp, )) tx_root_hash, _ = make_trie_root_and_nodes(block.transactions) if tx_root_hash != block.header.transaction_root: raise ValidationError( "Block's transaction_root ({0}) does not match expected value: {1}" .format(block.header.transaction_root, tx_root_hash)) if len(block.uncles) > MAX_UNCLES: raise ValidationError( "Blocks may have a maximum of {0} uncles. Found " "{1}.".format(MAX_UNCLES, len(block.uncles))) for uncle in block.uncles: self.validate_uncle(block, uncle) if not self.state.is_key_exists(block.header.state_root): raise ValidationError("`state_root` was not found in the db.\n" "- state_root: {0}".format( block.header.state_root, )) local_uncle_hash = keccak(rlp.encode(block.uncles)) if local_uncle_hash != block.header.uncles_hash: raise ValidationError( "`uncles_hash` and block `uncles` do not match.\n" " - num_uncles : {0}\n" " - block uncle_hash : {1}\n" " - header uncle_hash: {2}".format( len(block.uncles), local_uncle_hash, block.header.uncle_hash, ))
def generate_CREATE2_contract_address(salt, code): """ If contract is created by transaction, `salt` is specified by `transaction.salt`. If contract is created by contract, `salt` is set by the creator contract. """ validate_length_lte(salt, 32, title="Salt") validate_is_bytes(salt) validate_is_bytes(code) return keccak(salt.rjust(32, b'\x00') + code)[-20:]
def validate_block(self, block): if not block.is_genesis: parent_header = get_parent_header(block.header, self.chaindb) validate_gas_limit(block.header.gas_limit, parent_header.gas_limit) validate_length_lte(block.header.extra_data, 32, title="BlockHeader.extra_data") # timestamp if block.header.timestamp < parent_header.timestamp: raise ValidationError( "`timestamp` is before the parent block's timestamp.\n" "- block : {0}\n" "- parent : {1}. ".format( block.header.timestamp, parent_header.timestamp, ) ) elif block.header.timestamp == parent_header.timestamp: raise ValidationError( "`timestamp` is equal to the parent block's timestamp\n" "- block : {0}\n" "- parent: {1}. ".format( block.header.timestamp, parent_header.timestamp, ) ) if len(block.uncles) > MAX_UNCLES: raise ValidationError( "Blocks may have a maximum of {0} uncles. Found " "{1}.".format(MAX_UNCLES, len(block.uncles)) ) for uncle in block.uncles: self.validate_uncle(block, uncle) if not self.state.is_key_exists(block.header.state_root): raise ValidationError( "`state_root` was not found in the db.\n" "- state_root: {0}".format( block.header.state_root, ) ) local_uncle_hash = keccak(rlp.encode(block.uncles)) if local_uncle_hash != block.header.uncles_hash: raise ValidationError( "`uncles_hash` and block `uncles` do not match.\n" " - num_uncles : {0}\n" " - block uncle_hash : {1}\n" " - header uncle_hash: {2}".format( len(block.uncles), local_uncle_hash, block.header.uncle_hash, ) )
def validate_block(self, block): """ Validate the the given block. """ if not isinstance(block, self.get_block_class()): raise ValidationError( "This vm ({0!r}) is not equipped to validate a block of type {1!r}".format( self, block, ) ) if block.is_genesis: validate_length_lte(block.header.extra_data, 32, title="BlockHeader.extra_data") else: parent_header = get_parent_header(block.header, self.chaindb) self.validate_header(block.header, parent_header) tx_root_hash, _ = make_trie_root_and_nodes(block.transactions) if tx_root_hash != block.header.transaction_root: raise ValidationError( "Block's transaction_root ({0}) does not match expected value: {1}".format( block.header.transaction_root, tx_root_hash)) if len(block.uncles) > MAX_UNCLES: raise ValidationError( "Blocks may have a maximum of {0} uncles. Found " "{1}.".format(MAX_UNCLES, len(block.uncles)) ) if not self.chaindb.exists(block.header.state_root): raise ValidationError( "`state_root` was not found in the db.\n" "- state_root: {0}".format( block.header.state_root, ) ) local_uncle_hash = keccak(rlp.encode(block.uncles)) if local_uncle_hash != block.header.uncles_hash: raise ValidationError( "`uncles_hash` and block `uncles` do not match.\n" " - num_uncles : {0}\n" " - block uncle_hash : {1}\n" " - header uncle_hash: {2}".format( len(block.uncles), local_uncle_hash, block.header.uncle_hash, ) )
def test_validate_length_lte(value, maximum_length, is_valid): if is_valid: validate_length_lte(value, maximum_length) else: with pytest.raises(ValidationError): validate_length_lte(value, maximum_length)