def configure_homestead_header(vm, **header_params): validate_header_params_for_configuration(header_params) with vm.block.header.build_changeset(**header_params) as changeset: if 'timestamp' in header_params and changeset.block_number > 0: parent_header = get_parent_header(changeset.build_rlp(), vm.chaindb) changeset.difficulty = compute_homestead_difficulty( parent_header, header_params['timestamp'], ) # In geth the modification of the state in the DAO fork block is performed # before any transactions are applied, so doing it here is the closest we # get to that. Another alternative would be to do it in Block.mine(), but # there we'd need to manually instantiate the State and update # header.state_root after we're done. if vm.support_dao_fork and changeset.block_number == vm.dao_fork_block_number: state = vm.state with state.mutable_state_db() as state_db: for account in dao_drain_list: account = decode_hex(account) balance = state_db.get_balance(account) state_db.delta_balance(dao_refund_contract, balance) state_db.set_balance(account, 0) # Update state_root manually changeset.state_root = state.state_root header = changeset.commit() return header
def configure_homestead_header(vm, **header_params): validate_header_params_for_configuration(header_params) for field_name, value in header_params.items(): setattr(vm.block.header, field_name, value) if 'timestamp' in header_params and vm.block.header.block_number > 0: parent_header = get_parent_header(vm.block.header, vm.chaindb) vm.block.header.difficulty = compute_homestead_difficulty( parent_header, header_params['timestamp'], ) # In geth the modification of the state in the DAO fork block is performed # before any transactions are applied, so doing it here is the closest we # get to that. Another alternative would be to do it in Block.mine(), but # there we'd need to manually instantiate the State and update # header.state_root after we're done. if vm.support_dao_fork and vm.block.header.block_number == vm.dao_fork_block_number: vm_state = vm.state with vm_state.state_db() as state_db: for account in dao_drain_list: account = decode_hex(account) balance = state_db.get_balance(account) state_db.delta_balance(dao_refund_contract, balance) state_db.set_balance(account, 0) # Update state_root manually vm.block.header.state_root = vm_state.state_root return vm.block.header
def configure_homestead_header(vm, **header_params): validate_header_params_for_configuration(header_params) for field_name, value in header_params.items(): setattr(vm.block.header, field_name, value) if 'timestamp' in header_params and vm.block.header.block_number > 0: parent_header = get_parent_header(vm.block.header, vm.chaindb) vm.block.header.difficulty = compute_homestead_difficulty( parent_header, header_params['timestamp'], ) # In geth the modification of the state in the DAO fork block is performed # before any transactions are applied, so doing it here is the closest we # get to that. Another alternative would be to do it in Block.mine(), but # there we'd need to manually instantiate the State and update # header.state_root after we're done. if vm.support_dao_fork and vm.block.header.block_number == vm.dao_fork_block_number: with vm.state.state_db() as state_db: for account in dao_drain_list: account = decode_hex(account) balance = state_db.get_balance(account) state_db.delta_balance(dao_refund_contract, balance) state_db.set_balance(account, 0) return vm.block.header
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 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 get_prev_hashes(cls, last_block_hash, db): if last_block_hash == GENESIS_PARENT_HASH: return block_header = get_block_header_by_hash(last_block_hash, db) for _ in range(MAX_PREV_HEADER_DEPTH): yield block_header.hash try: block_header = get_parent_header(block_header, db) except (IndexError, BlockNotFound): break
def configure_byzantium_header(vm, **header_params): validate_header_params_for_configuration(header_params) with vm.block.header.build_changeset(**header_params) as changeset: if 'timestamp' in header_params and changeset.block_number > 0: parent_header = get_parent_header(changeset.build_rlp(), vm.chaindb) changeset.difficulty = compute_byzantium_difficulty( parent_header, header_params['timestamp'], ) header = changeset.commit() return header
def configure_byzantium_header(vm, **header_params): validate_header_params_for_configuration(header_params) for field_name, value in header_params.items(): setattr(vm.block.header, field_name, value) if 'timestamp' in header_params and vm.block.header.block_number > 0: parent_header = get_parent_header(vm.block.header, vm.chaindb) vm.block.header.difficulty = compute_byzantium_difficulty( parent_header, header_params['timestamp'], ) return vm.block.header
def configure_frontier_header(vm, **header_params): validate_header_params_for_configuration(header_params) for field_name, value in header_params.items(): setattr(vm.block.header, field_name, value) if 'timestamp' in header_params and vm.block.header.block_number > 0: parent_header = get_parent_header(vm.block.header, vm.chaindb) vm.block.header.difficulty = compute_frontier_difficulty( parent_header, header_params['timestamp'], ) return vm.block.header
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 get_prev_headers(cls, last_block_hash, db): prev_headers = [] if last_block_hash == GENESIS_PARENT_HASH: return prev_headers block_header = get_block_header_by_hash(last_block_hash, db) for _ in range(MAX_PREV_HEADER_DEPTH): prev_headers.append(block_header) try: block_header = get_parent_header(block_header, db) except (IndexError, BlockNotFound): break return prev_headers