def _get_computation_error(state: StateAPI, transaction: SignedTransactionAPI) -> Optional[VMError]: snapshot = state.snapshot() try: computation = state.apply_transaction(transaction) if computation.is_error: return computation.error else: return None finally: state.revert(snapshot)
def apply_create_message( cls, state: StateAPI, message: MessageAPI, transaction_context: TransactionContextAPI) -> ComputationAPI: snapshot = state.snapshot() # EIP161 nonce incrementation state.increment_nonce(message.storage_address) computation = cls.apply_message(state, message, transaction_context) if computation.is_error: state.revert(snapshot) return computation else: contract_code = computation.output if contract_code and len(contract_code) >= EIP170_CODE_SIZE_LIMIT: computation.error = OutOfGas( f"Contract code size exceeds EIP170 limit of {EIP170_CODE_SIZE_LIMIT}." f" Got code of size: {len(contract_code)}") state.revert(snapshot) elif contract_code: contract_code_gas_cost = len( contract_code) * constants.GAS_CODEDEPOSIT try: computation.consume_gas( contract_code_gas_cost, reason="Write contract code for CREATE", ) except OutOfGas as err: # Different from Frontier: reverts state on gas failure while # writing contract code. computation.error = err state.revert(snapshot) else: if cls.logger: cls.logger.debug2( "SETTING CODE: %s -> length: %s | hash: %s", encode_hex(message.storage_address), len(contract_code), encode_hex(keccak(contract_code))) state.set_code(message.storage_address, contract_code) state.commit(snapshot) else: state.commit(snapshot) return computation
def apply_create_message( cls, state: StateAPI, message: MessageAPI, transaction_context: TransactionContextAPI) -> ComputationAPI: snapshot = state.snapshot() # EIP161 nonce incrementation state.increment_nonce(message.storage_address) computation = cls.apply_message(state, message, transaction_context) if computation.is_error: state.revert(snapshot) return computation else: contract_code = computation.output if contract_code: try: cls.validate_contract_code(contract_code) contract_code_gas_cost = len( contract_code) * constants.GAS_CODEDEPOSIT computation.consume_gas( contract_code_gas_cost, reason="Write contract code for CREATE", ) except VMError as err: # Different from Frontier: reverts state on gas failure while # writing contract code. computation.error = err state.revert(snapshot) cls.logger.debug2(f"VMError setting contract code: {err}") else: if cls.logger: cls.logger.debug2( "SETTING CODE: %s -> length: %s | hash: %s", encode_hex(message.storage_address), len(contract_code), encode_hex(keccak(contract_code))) state.set_code(message.storage_address, contract_code) state.commit(snapshot) else: state.commit(snapshot) return computation
def apply_message( cls, state: StateAPI, message: MessageAPI, transaction_context: TransactionContextAPI) -> ComputationAPI: snapshot = state.snapshot() if message.depth > STACK_DEPTH_LIMIT: raise StackDepthLimit("Stack depth limit reached") if message.should_transfer_value and message.value: sender_balance = state.get_balance(message.sender) if sender_balance < message.value: raise InsufficientFunds( f"Insufficient funds: {sender_balance} < {message.value}") state.delta_balance(message.sender, -1 * message.value) state.delta_balance(message.storage_address, message.value) cls.logger.debug2( "TRANSFERRED: %s from %s -> %s", message.value, encode_hex(message.sender), encode_hex(message.storage_address), ) state.touch_account(message.storage_address) computation = cls.apply_computation( state, message, transaction_context, ) if computation.is_error: state.revert(snapshot) else: state.commit(snapshot) return computation