Esempio n. 1
0
def sstore_eip2200(computation: BaseComputation) -> None:
    gas_remaining = computation.get_gas_remaining()
    if gas_remaining <= 2300:
        raise OutOfGas(
            "Net-metered SSTORE always fails below 2300 gas, per EIP-2200",
            gas_remaining,
        )
    else:
        return net_sstore(GAS_SCHEDULE_EIP2200, computation)
Esempio n. 2
0
def compute_eip150_msg_gas(*, computation: ComputationAPI, gas: int,
                           extra_gas: int, value: int, mnemonic: str,
                           callstipend: int) -> Tuple[int, int]:
    if computation.get_gas_remaining() < extra_gas:
        # It feels wrong to raise an OutOfGas exception outside of GasMeter,
        # but I don't see an easy way around it.
        raise OutOfGas(f"Out of gas: Needed {extra_gas}"
                       f" - Remaining {computation.get_gas_remaining()}"
                       f" - Reason: {mnemonic}")
    gas = min(
        gas, max_child_gas_eip150(computation.get_gas_remaining() - extra_gas))
    total_fee = gas + extra_gas
    child_msg_gas = gas + (callstipend if value else 0)
    return child_msg_gas, total_fee
Esempio n. 3
0
    def apply_create_message(self):
        snapshot = self.state.snapshot()

        # EIP161 nonce incrementation
        self.state.account_db.increment_nonce(self.msg.storage_address)

        computation = self.apply_message()

        if computation.is_error:
            self.state.revert(snapshot)
            return computation
        else:
            contract_code = computation.output

            if contract_code and len(contract_code) >= EIP170_CODE_SIZE_LIMIT:
                computation._error = OutOfGas(
                    "Contract code size exceeds EIP170 limit of {0}.  Got code of "
                    "size: {1}".format(
                        EIP170_CODE_SIZE_LIMIT,
                        len(contract_code),
                    ))
                self.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
                    self.state.revert(snapshot)
                else:
                    if self.logger:
                        self.logger.trace(
                            "SETTING CODE: %s -> length: %s | hash: %s",
                            encode_hex(self.msg.storage_address),
                            len(contract_code),
                            encode_hex(keccak(contract_code)))

                    self.state.account_db.set_code(self.msg.storage_address,
                                                   contract_code)
                    self.state.commit(snapshot)
            else:
                self.state.commit(snapshot)
            return computation
Esempio n. 4
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
Esempio n. 5
0
def compute_eip150_msg_gas(computation, gas, extra_gas, value, mnemonic,
                           callstipend):
    if computation.get_gas_remaining() < extra_gas:
        # It feels wrong to raise an OutOfGas exception outside of GasMeter,
        # but I don't see an easy way around it.
        raise OutOfGas(
            "Out of gas: Needed {0} - Remaining {1} - Reason: {2}".format(
                extra_gas,
                computation.get_gas_remaining(),
                mnemonic,
            ))
    gas = min(
        gas, max_child_gas_eip150(computation.get_gas_remaining() - extra_gas))
    total_fee = gas + extra_gas
    child_msg_gas = gas + (callstipend if value else 0)
    return child_msg_gas, total_fee
Esempio n. 6
0
    def consume_gas(self, amount: int, reason: str) -> None:
        if amount < 0:
            raise ValidationError("Gas consumption amount must be positive")

        if amount > self.gas_remaining:
            raise OutOfGas(f"Out of gas: Needed {amount} "
                           f"- Remaining {self.gas_remaining} "
                           f"- Reason: {reason}")

        self.gas_remaining -= amount

        if self.logger.show_debug2:
            self.logger.debug2(
                'GAS CONSUMPTION: %s - %s -> %s (%s)',
                self.gas_remaining + amount,
                amount,
                self.gas_remaining,
                reason,
            )
Esempio n. 7
0
    def consume_gas(self, amount: int, reason: str) -> None:
        if amount < 0:
            raise ValidationError("Gas consumption amount must be positive")

        if amount > self.gas_remaining:
            raise OutOfGas("Out of gas: Needed {0} - Remaining {1} - Reason: {2}".format(
                amount,
                self.gas_remaining,
                reason,
            ))

        self.gas_remaining -= amount

        self.logger.trace(
            'GAS CONSUMPTION: %s - %s -> %s (%s)',
            self.gas_remaining + amount,
            amount,
            self.gas_remaining,
            reason,
        )
Esempio n. 8
0
 def validate_contract_code(cls, contract_code: bytes) -> None:
     if len(contract_code) >= EIP170_CODE_SIZE_LIMIT:
         raise OutOfGas(
             f"Contract code size exceeds EIP170 limit of {EIP170_CODE_SIZE_LIMIT}."
             f"  Got code of size: {len(contract_code)}")