コード例 #1
0
def revert(computation: ComputationAPI) -> None:
    start_position, size = computation.stack_pop_ints(2)

    computation.extend_memory(start_position, size)

    computation.output = computation.memory_read_bytes(start_position, size)
    raise Revert(computation.output)
コード例 #2
0
def return_op(computation: ComputationAPI) -> None:
    start_position, size = computation.stack_pop_ints(2)

    computation.extend_memory(start_position, size)

    computation.output = computation.memory_read_bytes(start_position, size)
    raise Halt('RETURN')
コード例 #3
0
ファイル: __init__.py プロジェクト: youngqqcn/py-evm
def make_frontier_receipt(base_header: BlockHeaderAPI,
                          transaction: SignedTransactionAPI,
                          computation: ComputationAPI) -> ReceiptAPI:
    # Reusable for other forks
    # This skips setting the state root (set to 0 instead). The logic for making a state root
    # lives in the FrontierVM, so that state merkelization at each receipt is skipped at Byzantium+.

    logs = [
        Log(address, topics, data)
        for address, topics, data in computation.get_log_entries()
    ]

    gas_remaining = computation.get_gas_remaining()
    gas_refund = computation.get_gas_refund()
    tx_gas_used = (transaction.gas - gas_remaining) - min(
        gas_refund,
        (transaction.gas - gas_remaining) // 2,
    )
    gas_used = base_header.gas_used + tx_gas_used

    receipt = Receipt(
        state_root=ZERO_HASH32,
        gas_used=gas_used,
        logs=logs,
    )

    return receipt
コード例 #4
0
ファイル: call.py プロジェクト: ygdmxy/py-evm
    def get_call_params(self, computation: ComputationAPI) -> CallParams:
        gas = computation.stack_pop1_int()
        to = force_bytes_to_address(computation.stack_pop1_bytes())

        (
            value,
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
        ) = computation.stack_pop_ints(5)

        return (
            gas,
            value,
            to,
            None,  # sender
            None,  # code_address
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
            True,  # should_transfer_value,
            computation.msg.is_static,
        )
コード例 #5
0
ファイル: call.py プロジェクト: ygdmxy/py-evm
    def get_call_params(self, computation: ComputationAPI) -> CallParams:
        gas = computation.stack_pop1_int()
        code_address = force_bytes_to_address(computation.stack_pop1_bytes())

        (
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
        ) = computation.stack_pop_ints(4)

        to = computation.msg.storage_address
        sender = computation.msg.sender
        value = computation.msg.value

        return (
            gas,
            value,
            to,
            sender,
            code_address,
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
            False,  # should_transfer_value,
            computation.msg.is_static,
        )
コード例 #6
0
def consume_extcodecopy_word_cost(computation: ComputationAPI,
                                  size: int) -> None:
    word_count = ceil32(size) // 32
    copy_gas_cost = constants.GAS_COPY * word_count
    computation.consume_gas(
        copy_gas_cost,
        reason='EXTCODECOPY: word gas cost',
    )
コード例 #7
0
def selfdestruct_eip150(computation: ComputationAPI) -> None:
    beneficiary = force_bytes_to_address(computation.stack_pop1_bytes())
    if not computation.state.account_exists(beneficiary):
        computation.consume_gas(
            constants.GAS_SELFDESTRUCT_NEWACCOUNT,
            reason=mnemonics.SELFDESTRUCT,
        )
    _selfdestruct(computation, beneficiary)
コード例 #8
0
 def wrapped_logic_fn(computation: ComputationAPI) -> Any:
     """
     Wrapper functionf or the logic function which consumes the base
     opcode gas cost prior to execution.
     """
     computation.consume_gas(
         gas_cost,
         mnemonic,
     )
     return logic_fn(computation)
コード例 #9
0
def sstore_eip2929_generic(gas_schedule: NetSStoreGasSchedule,
                           computation: ComputationAPI) -> int:
    slot = sstore_eip2200_generic(gas_schedule, computation)

    if _mark_storage_warm(computation, slot):
        gas_cost = berlin_constants.COLD_SLOAD_COST
        computation.consume_gas(
            gas_cost, reason=f"Implicit SLOAD during {mnemonics.SSTORE}")

    return slot
コード例 #10
0
    def finalize_gas_used(cls, transaction: SignedTransactionAPI,
                          computation: ComputationAPI) -> int:

        gas_remaining = computation.get_gas_remaining()
        consumed_gas = transaction.gas - gas_remaining

        gross_refund = computation.get_gas_refund()
        net_refund = cls.calculate_net_gas_refund(consumed_gas, gross_refund)

        return consumed_gas - net_refund
コード例 #11
0
def selfdestruct_eip161(computation: ComputationAPI) -> None:
    beneficiary = force_bytes_to_address(computation.stack_pop1_bytes())
    is_dead = (not computation.state.account_exists(beneficiary)
               or computation.state.account_is_empty(beneficiary))
    if is_dead and computation.state.get_balance(
            computation.msg.storage_address):
        computation.consume_gas(
            constants.GAS_SELFDESTRUCT_NEWACCOUNT,
            reason=mnemonics.SELFDESTRUCT,
        )
    _selfdestruct(computation, beneficiary)
コード例 #12
0
def selfdestruct_eip2929(computation: ComputationAPI) -> None:
    beneficiary = force_bytes_to_address(computation.stack_pop1_bytes())

    if _mark_address_warm(computation, beneficiary):
        gas_cost = berlin_constants.COLD_ACCOUNT_ACCESS_COST
        computation.consume_gas(
            gas_cost,
            reason=f"Implicit account load during {mnemonics.SELFDESTRUCT}",
        )

    selfdestruct_eip161_on_address(computation, beneficiary)
コード例 #13
0
ファイル: state.py プロジェクト: marcgarreau/py-evm
    def calculate_gas_refund(cls,
                             computation: ComputationAPI,
                             gas_used: int) -> int:
        # Self Destruct Refunds
        num_deletions = len(computation.get_accounts_for_deletion())
        if num_deletions:
            computation.refund_gas(REFUND_SELFDESTRUCT * num_deletions)

        # Gas Refunds
        gas_refunded = computation.get_gas_refund()

        return min(gas_refunded, gas_used // MAX_REFUND_QUOTIENT)
コード例 #14
0
def extcodehash_eip2929(computation: ComputationAPI) -> None:
    """
    Return the code hash for a given address.
    EIP: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1052.md
    """
    address = force_bytes_to_address(computation.stack_pop1_bytes())
    state = computation.state

    _consume_gas_for_account_load(computation, address, mnemonics.EXTCODEHASH)

    if state.account_is_empty(address):
        computation.stack_push_bytes(constants.NULL_BYTE)
    else:
        computation.stack_push_bytes(state.get_code_hash(address))
コード例 #15
0
def sload_eip2929(computation: ComputationAPI) -> None:
    slot = computation.stack_pop1_int()

    if _mark_storage_warm(computation, slot):
        gas_cost = berlin_constants.COLD_SLOAD_COST
    else:
        gas_cost = berlin_constants.WARM_STORAGE_READ_COST
    computation.consume_gas(gas_cost, reason=mnemonics.SLOAD)

    value = computation.state.get_storage(
        address=computation.msg.storage_address,
        slot=slot,
    )
    computation.stack_push_int(value)
コード例 #16
0
ファイル: call.py プロジェクト: ygdmxy/py-evm
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
コード例 #17
0
ファイル: state.py プロジェクト: marcgarreau/py-evm
    def calculate_gas_refund(cls, computation: ComputationAPI,
                             gas_used: int) -> int:
        # Self destruct refunds were added in Frontier
        # London removes them in EIP-3529
        gas_refunded = computation.get_gas_refund()

        return min(gas_refunded, gas_used // EIP3529_MAX_REFUND_QUOTIENT)
コード例 #18
0
ファイル: transactions.py プロジェクト: yylluu/py-evm
 def gas_used_by(self, computation: ComputationAPI) -> int:
     """
     Return the gas used by the given computation. In Frontier,
     for example, this is sum of the intrinsic cost and the gas used
     during computation.
     """
     return self.get_intrinsic_gas() + computation.get_gas_used()
コード例 #19
0
    def get_stack_data(self,
                       computation: ComputationAPI) -> CreateOpcodeStackData:
        endowment, memory_start, memory_length, salt = computation.stack_pop_ints(
            4)

        return CreateOpcodeStackData(endowment, memory_start, memory_length,
                                     salt)
コード例 #20
0
ファイル: system.py プロジェクト: marcgarreau/py-evm
    def apply_create_message(self, computation: ComputationAPI, child_msg: MessageAPI) -> None:
        child_computation = computation.apply_child_computation(child_msg)

        if child_computation.is_error:
            computation.stack_push_int(0)
        else:
            computation.stack_push_bytes(child_msg.storage_address)

        computation.return_gas(child_computation.get_gas_remaining())
コード例 #21
0
ファイル: state.py プロジェクト: marcgarreau/py-evm
    def finalize_computation(self,
                             transaction: SignedTransactionAPI,
                             computation: ComputationAPI) -> ComputationAPI:
        transaction_context = self.vm_state.get_transaction_context(transaction)

        gas_remaining = computation.get_gas_remaining()
        gas_used = transaction.gas - gas_remaining
        gas_refund = self.calculate_gas_refund(computation, gas_used)
        gas_refund_amount = (gas_refund + gas_remaining) * transaction_context.gas_price

        if gas_refund_amount:
            self.vm_state.logger.debug2(
                'TRANSACTION REFUND: %s -> %s',
                gas_refund_amount,
                encode_hex(computation.msg.sender),
            )

            self.vm_state.delta_balance(computation.msg.sender, gas_refund_amount)

        # Miner Fees
        gas_used = transaction.gas - gas_remaining - gas_refund
        transaction_fee = gas_used * self.vm_state.get_tip(transaction)
        self.vm_state.logger.debug2(
            'TRANSACTION FEE: %s -> %s',
            transaction_fee,
            encode_hex(self.vm_state.coinbase),
        )
        self.vm_state.delta_balance(self.vm_state.coinbase, transaction_fee)

        # Process Self Destructs
        for account, _ in computation.get_accounts_for_deletion():
            # TODO: need to figure out how we prevent multiple selfdestructs from
            # the same account and if this is the right place to put this.
            self.vm_state.logger.debug2('DELETING ACCOUNT: %s', encode_hex(account))

            # TODO: this balance setting is likely superflous and can be
            # removed since `delete_account` does this.
            self.vm_state.set_balance(account, 0)
            self.vm_state.delete_account(account)

        return computation
コード例 #22
0
ファイル: system.py プロジェクト: marcgarreau/py-evm
def _selfdestruct(computation: ComputationAPI, beneficiary: Address) -> None:
    local_balance = computation.state.get_balance(computation.msg.storage_address)
    beneficiary_balance = computation.state.get_balance(beneficiary)

    # 1st: Transfer to beneficiary
    computation.state.set_balance(beneficiary, local_balance + beneficiary_balance)
    # 2nd: Zero the balance of the address being deleted (must come after
    # sending to beneficiary in case the contract named itself as the
    # beneficiary.
    computation.state.set_balance(computation.msg.storage_address, 0)

    computation.logger.debug2(
        "SELFDESTRUCT: %s (%s) -> %s",
        encode_hex(computation.msg.storage_address),
        local_balance,
        encode_hex(beneficiary),
    )

    # 3rd: Register the account to be deleted
    computation.register_account_for_deletion(beneficiary)
    raise Halt('SELFDESTRUCT')
コード例 #23
0
ファイル: __init__.py プロジェクト: marcgarreau/py-evm
    def make_receipt(cls, base_header: BlockHeaderAPI,
                     transaction: SignedTransactionAPI,
                     computation: ComputationAPI,
                     state: StateAPI) -> ReceiptAPI:

        gas_used = base_header.gas_used + cls.finalize_gas_used(
            transaction, computation)

        if computation.is_error:
            status_code = EIP658_TRANSACTION_STATUS_CODE_FAILURE
        else:
            status_code = EIP658_TRANSACTION_STATUS_CODE_SUCCESS

        return transaction.make_receipt(status_code, gas_used,
                                        computation.get_log_entries())
コード例 #24
0
def make_frontier_receipt(computation: ComputationAPI,
                          new_cumulative_gas_used: int) -> ReceiptAPI:
    # Reusable for other forks
    # This skips setting the state root (set to 0 instead). The logic for making a state root
    # lives in the FrontierVM, so that state merkelization at each receipt is skipped at Byzantium+.

    logs = [
        Log(address, topics, data)
        for address, topics, data in computation.get_log_entries()
    ]

    receipt = Receipt(
        state_root=ZERO_HASH32,
        gas_used=new_cumulative_gas_used,
        logs=logs,
    )

    return receipt
コード例 #25
0
ファイル: state.py プロジェクト: ggs134/py-evm
    def finalize_computation(self, transaction: SignedTransactionAPI,
                             computation: ComputationAPI) -> ComputationAPI:

        # Self Destruct Refunds
        num_deletions = len(computation.get_accounts_for_deletion())
        if num_deletions:
            computation.refund_gas(REFUND_SELFDESTRUCT * num_deletions)

        # Gas Refunds
        gas_remaining = computation.get_gas_remaining()
        gas_refunded = computation.get_gas_refund()
        gas_used = transaction.gas - gas_remaining
        gas_refund = min(gas_refunded, gas_used // 2)
        gas_refund_amount = (gas_refund +
                             gas_remaining) * transaction.gas_price

        if gas_refund_amount:
            self.vm_state.logger.debug2(
                'TRANSACTION REFUND: %s -> %s',
                gas_refund_amount,
                encode_hex(computation.msg.sender),
            )

            # self.vm_state.delta_balance(computation.msg.sender, gas_refund_amount)

        ### DAEJUN changed ###
        # Miner Fees
        # transaction_fee = \
        #     (transaction.gas - gas_remaining - gas_refund) * transaction.gas_price
        transaction_fee = 0
        self.vm_state.logger.debug2(
            'TRANSACTION FEE: %s -> %s',
            transaction_fee,
            encode_hex(self.vm_state.coinbase),
        )
        self.vm_state.delta_balance(self.vm_state.coinbase, transaction_fee)

        # Process Self Destructs
        for account, _ in computation.get_accounts_for_deletion():
            # TODO: need to figure out how we prevent multiple selfdestructs from
            # the same account and if this is the right place to put this.
            self.vm_state.logger.debug2('DELETING ACCOUNT: %s',
                                        encode_hex(account))

            # TODO: this balance setting is likely superflous and can be
            # removed since `delete_account` does this.
            self.vm_state.set_balance(account, 0)
            self.vm_state.delete_account(account)

        return computation
コード例 #26
0
ファイル: system.py プロジェクト: marcgarreau/py-evm
    def apply_create_message(self, computation: ComputationAPI, child_msg: MessageAPI) -> None:
        # We need to ensure that creation operates on empty storage **and**
        # that if the initialization code fails that we revert the account back
        # to its original state root.
        snapshot = computation.state.snapshot()

        computation.state.delete_storage(child_msg.storage_address)

        child_computation = computation.apply_child_computation(child_msg)

        if child_computation.is_error:
            computation.state.revert(snapshot)
            computation.stack_push_int(0)
        else:
            computation.state.commit(snapshot)
            computation.stack_push_bytes(child_msg.storage_address)

        computation.return_gas(child_computation.get_gas_remaining())
コード例 #27
0
def extcodecopy_execute(computation: ComputationAPI) -> Tuple[Address, int]:
    """
    Runs the logical component of extcodecopy, without charging gas.

    :return (target_address, copy_size): useful for the caller to determine gas costs
    """
    account = force_bytes_to_address(computation.stack_pop1_bytes())
    (
        mem_start_position,
        code_start_position,
        size,
    ) = computation.stack_pop_ints(3)

    computation.extend_memory(mem_start_position, size)

    code = computation.state.get_code(account)

    code_bytes = code[code_start_position:code_start_position + size]
    padded_code_bytes = code_bytes.ljust(size, b'\x00')

    computation.memory_write(mem_start_position, size, padded_code_bytes)

    return account, size
コード例 #28
0
def selfdestruct(computation: ComputationAPI) -> None:
    beneficiary = force_bytes_to_address(computation.stack_pop1_bytes())
    _selfdestruct(computation, beneficiary)
コード例 #29
0
    def __call__(self, computation: ComputationAPI) -> None:

        stack_data = self.get_stack_data(computation)

        gas_cost = self.get_gas_cost(stack_data)
        computation.consume_gas(gas_cost, reason=self.mnemonic)

        computation.extend_memory(stack_data.memory_start,
                                  stack_data.memory_length)

        insufficient_funds = computation.state.get_balance(
            computation.msg.storage_address) < stack_data.endowment
        stack_too_deep = computation.msg.depth + 1 > constants.STACK_DEPTH_LIMIT

        if insufficient_funds or stack_too_deep:
            computation.stack_push_int(0)
            return

        call_data = computation.memory_read_bytes(stack_data.memory_start,
                                                  stack_data.memory_length)

        create_msg_gas = self.max_child_gas_modifier(
            computation.get_gas_remaining())
        computation.consume_gas(create_msg_gas, reason=self.mnemonic)

        contract_address = self.generate_contract_address(
            stack_data, call_data, computation)

        is_collision = computation.state.has_code_or_nonce(contract_address)

        if is_collision:
            self.logger.debug2(
                "Address collision while creating contract: %s",
                encode_hex(contract_address),
            )
            computation.stack_push_int(0)
            return

        child_msg = computation.prepare_child_message(
            gas=create_msg_gas,
            to=constants.CREATE_CONTRACT_ADDRESS,
            value=stack_data.endowment,
            data=b'',
            code=call_data,
            create_address=contract_address,
        )
        self.apply_create_message(computation, child_msg)
コード例 #30
0
ファイル: call.py プロジェクト: ygdmxy/py-evm
    def __call__(self, computation: ComputationAPI) -> None:
        computation.consume_gas(
            self.gas_cost,
            reason=self.mnemonic,
        )

        (
            gas,
            value,
            to,
            sender,
            code_address,
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
            should_transfer_value,
            is_static,
        ) = self.get_call_params(computation)

        computation.extend_memory(memory_input_start_position,
                                  memory_input_size)
        computation.extend_memory(memory_output_start_position,
                                  memory_output_size)

        call_data = computation.memory_read(memory_input_start_position,
                                            memory_input_size)

        #
        # Message gas allocation and fees
        #
        child_msg_gas, child_msg_gas_fee = self.compute_msg_gas(
            computation, gas, to, value)
        computation.consume_gas(child_msg_gas_fee, reason=self.mnemonic)

        # Pre-call checks
        sender_balance = computation.state.get_balance(
            computation.msg.storage_address)

        insufficient_funds = should_transfer_value and sender_balance < value
        stack_too_deep = computation.msg.depth + 1 > constants.STACK_DEPTH_LIMIT

        if insufficient_funds or stack_too_deep:
            computation.return_data = b''
            if insufficient_funds:
                err_message = f"Insufficient Funds: have: {sender_balance} | need: {value}"
            elif stack_too_deep:
                err_message = "Stack Limit Reached"
            else:
                raise Exception("Invariant: Unreachable code path")

            self.logger.debug2(
                "%s failure: %s",
                self.mnemonic,
                err_message,
            )
            computation.return_gas(child_msg_gas)
            computation.stack_push_int(0)
        else:
            if code_address:
                code = computation.state.get_code(code_address)
            else:
                code = computation.state.get_code(to)

            child_msg_kwargs = {
                'gas': child_msg_gas,
                'value': value,
                'to': to,
                'data': call_data,
                'code': code,
                'code_address': code_address,
                'should_transfer_value': should_transfer_value,
                'is_static': is_static,
            }
            if sender is not None:
                child_msg_kwargs['sender'] = sender

            # TODO: after upgrade to py3.6, use a TypedDict and try again
            child_msg = computation.prepare_child_message(
                **child_msg_kwargs)  # type: ignore

            child_computation = computation.apply_child_computation(child_msg)

            if child_computation.is_error:
                computation.stack_push_int(0)
            else:
                computation.stack_push_int(1)

            if not child_computation.should_erase_return_data:
                actual_output_size = min(memory_output_size,
                                         len(child_computation.output))
                computation.memory_write(
                    memory_output_start_position,
                    actual_output_size,
                    child_computation.output[:actual_output_size],
                )

            if child_computation.should_return_gas:
                computation.return_gas(child_computation.get_gas_remaining())