Exemplo n.º 1
0
    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
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
    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