Esempio n. 1
0
    def get_call_params(self, computation: BaseComputation) -> CallParams:
        gas = computation.stack_pop(type_hint=constants.UINT256)
        code_address = force_bytes_to_address(
            computation.stack_pop(type_hint=constants.BYTES))

        (
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
        ) = computation.stack_pop(num_items=4, type_hint=constants.UINT256)

        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,
        )
Esempio n. 2
0
def mine_blocks_with_access_list_receipts(
        chain,
        num_blocks,
        num_tx_per_block,
        funded_address,
        funded_address_private_key):

    current_vm = chain.get_vm()
    if not isinstance(current_vm, BerlinVM):
        pytest.skip("{current_vm} does not support typed transactions")

    for _ in range(num_blocks):
        block_receipts = []
        for _ in range(num_tx_per_block):
            tx = new_access_list_transaction(
                chain.get_vm(),
                from_=funded_address,
                to=force_bytes_to_address(b'\x10\x10'),
                private_key=funded_address_private_key,
            )
            new_block, tx_receipt, computation = chain.apply_transaction(tx)
            block_receipts.append(tx_receipt)
            computation.raise_if_error()

        yield chain.mine_block(), block_receipts
Esempio n. 3
0
    def get_call_params(self, computation: BaseComputation) -> CallParams:
        gas = computation.stack_pop(type_hint=constants.UINT256)
        to = force_bytes_to_address(
            computation.stack_pop(type_hint=constants.BYTES))

        (
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
        ) = computation.stack_pop(num_items=4, type_hint=constants.UINT256)

        return (
            gas,
            0,  # value
            to,
            None,  # sender
            None,  # code_address
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
            False,  # should_transfer_value,
            True,  # is_static
        )
Esempio n. 4
0
    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,
        )
def extcodecopy(computation: BaseComputation) -> None:
    account = force_bytes_to_address(
        computation.stack_pop(type_hint=constants.BYTES))
    (
        mem_start_position,
        code_start_position,
        size,
    ) = computation.stack_pop(num_items=3, type_hint=constants.UINT256)

    computation.extend_memory(mem_start_position, size)

    word_count = ceil32(size) // 32
    copy_gas_cost = constants.GAS_COPY * word_count

    computation.consume_gas(
        copy_gas_cost,
        reason='EXTCODECOPY: word gas cost',
    )

    code = computation.state.account_db.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)
Esempio n. 6
0
    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,
        )
Esempio n. 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)
Esempio n. 8
0
def fuzz_extcodesize_opcode_fn(computation, opcode_fn) -> None:
    to = computation.stack_pop1_bytes()
    _to = to_normalized_address(to_hex(force_bytes_to_address(to)))
    if settings.ENVIRONMENTAL_INSTRUMENTATION and hasattr(computation.state, "fuzzed_extcodesize") and computation.state.fuzzed_extcodesize is not None\
            and _to in computation.state.fuzzed_extcodesize and computation.state.fuzzed_extcodesize[_to] is not None:
        computation.stack_push_int(computation.state.fuzzed_extcodesize[_to])
    else:
        computation.stack_push_bytes(to)
        opcode_fn(computation=computation)
Esempio n. 9
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)
Esempio n. 10
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)
Esempio n. 11
0
def create_random_tx(chain, private_key, is_valid=True):
    return chain.create_unsigned_transaction(
        nonce=0,
        gas_price=1,
        gas=2100000000000 if is_valid else 0,
        # For simplicity, both peers create tx with the same private key.
        # We rely on unique data to create truly unique txs
        data=uuid.uuid4().bytes,
        to=force_bytes_to_address(b'\x10\x10'),
        value=1,
    ).as_signed_transaction(private_key, chain_id=chain.chain_id)
Esempio n. 12
0
def extcodehash(computation: BaseComputation) -> None:
    """
    Return the code hash for a given address.
    EIP: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1052.md
    """
    account = force_bytes_to_address(computation.stack_pop1_bytes())
    state = computation.state

    if state.account_is_empty(account):
        computation.stack_push_bytes(constants.NULL_BYTE)
    else:
        computation.stack_push_bytes(state.get_code_hash(account))
Esempio n. 13
0
def extcodehash(computation: BaseComputation) -> None:
    """
    Return the code hash for a given address.
    EIP: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1052.md
    """
    account = force_bytes_to_address(computation.stack_pop(type_hint=constants.BYTES))
    account_db = computation.state.account_db

    if not account_db.account_exists(account):
        computation.stack_push(constants.NULL_BYTE)
    else:
        computation.stack_push(account_db.get_code_hash(account))
Esempio n. 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))
Esempio n. 15
0
def mine_blocks_with_receipts(chain, num_blocks, num_tx_per_block,
                              funded_address, funded_address_private_key):

    for _ in range(num_blocks):
        block_receipts = []
        for _ in range(num_tx_per_block):
            tx = new_transaction(
                chain.get_vm(),
                from_=funded_address,
                to=force_bytes_to_address(b'\x10\x10'),
                private_key=funded_address_private_key,
            )
            new_block, tx_receipt, computation = chain.apply_transaction(tx)
            block_receipts.append(tx_receipt)
            computation.raise_if_error()

        yield chain.mine_block(), block_receipts
Esempio n. 16
0
def test_blake2b_f_compression(vm_class, input_hex, output_hex,
                               expect_exception):
    comp = run_computation(
        setup_vm(vm_class),
        CANONICAL_ADDRESS_B,
        code=b'',
        gas=2**32 - 1,
        to=force_bytes_to_address(b'\x09'),
        data=to_bytes(hexstr=input_hex),
    )

    if expect_exception:
        assert isinstance(comp.error, expect_exception)
    else:
        comp.raise_if_error()
        result = comp.output
        assert result.hex() == output_hex
Esempio n. 17
0
def test_chaindb_get_receipt_by_index(
        chain,
        funded_address,
        funded_address_private_key):
    NUMBER_BLOCKS_IN_CHAIN = 5
    TRANSACTIONS_IN_BLOCK = 10
    REQUIRED_BLOCK_NUMBER = 2
    REQUIRED_RECEIPT_INDEX = 3

    for block_number in range(NUMBER_BLOCKS_IN_CHAIN):
        for tx_index in range(TRANSACTIONS_IN_BLOCK):
            tx = new_transaction(
                chain.get_vm(),
                from_=funded_address,
                to=force_bytes_to_address(b'\x10\x10'),
                private_key=funded_address_private_key,
            )
            new_block, tx_receipt, computation = chain.apply_transaction(tx)
            computation.raise_if_error()

            if (block_number + 1) == REQUIRED_BLOCK_NUMBER and tx_index == REQUIRED_RECEIPT_INDEX:
                actual_receipt = tx_receipt

        chain.mine_block()

    # Check that the receipt retrieved is indeed the actual one
    chaindb_retrieved_receipt = chain.chaindb.get_receipt_by_index(
        REQUIRED_BLOCK_NUMBER,
        REQUIRED_RECEIPT_INDEX,
    )
    assert chaindb_retrieved_receipt == actual_receipt

    # Raise error if block number is not found
    with pytest.raises(ReceiptNotFound):
        chain.chaindb.get_receipt_by_index(
            NUMBER_BLOCKS_IN_CHAIN + 1,
            REQUIRED_RECEIPT_INDEX,
        )

    # Raise error if receipt index is out of range
    with pytest.raises(ReceiptNotFound):
        chain.chaindb.get_receipt_by_index(
            NUMBER_BLOCKS_IN_CHAIN,
            TRANSACTIONS_IN_BLOCK + 1,
        )
Esempio n. 18
0
def fuzz_call_opcode_fn(computation, opcode_fn) -> None:
    gas = computation.stack_pop1_int()
    to = computation.stack_pop1_bytes()
    _to = to_normalized_address(to_hex(force_bytes_to_address(to)))
    if settings.ENVIRONMENTAL_INSTRUMENTATION and hasattr(computation.state, "fuzzed_call_return") and computation.state.fuzzed_call_return is not None\
            and _to in computation.state.fuzzed_call_return and computation.state.fuzzed_call_return[_to] is not None:
        (
            value,
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
        ) = computation.stack_pop_ints(5)
        computation.stack_push_int(computation.state.fuzzed_call_return[_to])
    else:
        computation.stack_push_bytes(to)
        computation.stack_push_int(gas)
        opcode_fn(computation=computation)
    return _to
Esempio n. 19
0
def test_blake2b_f_compression(vm_class, input_hex, output_hex,
                               expect_exception):
    computation = setup_computation(
        vm_class,
        CANONICAL_ADDRESS_B,
        code=b'',
        gas=2**32 - 1,
        to=force_bytes_to_address(b'\x09'),
        data=to_bytes(hexstr=input_hex),
    )

    comp = computation.apply_message(
        computation.state,
        computation.msg,
        computation.transaction_context,
    )
    if expect_exception:
        assert isinstance(comp.error, expect_exception)
    else:
        comp.raise_if_error()
        result = comp.output
        assert result.hex() == output_hex
Esempio n. 20
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
Esempio n. 21
0
async def test_get_balance_works_for_block_number(
        chain_without_block_validation, ipc_request, funded_address,
        funded_address_initial_balance, funded_address_private_key):
    block_no_before_transfer = (await ipc_request('eth_blockNumber',
                                                  []))['result']
    transfer_eth(chain=chain_without_block_validation,
                 sender_private_key=funded_address_private_key,
                 value=1,
                 to=force_bytes_to_address(b'\x10\x10'))
    balance_before = (await ipc_request(
        'eth_getBalance',
        [funded_address.hex(),
         to_int(hexstr=block_no_before_transfer)]))['result']
    assert balance_before == hex(funded_address_initial_balance)

    block_no_after_transfer = (await ipc_request('eth_blockNumber',
                                                 []))['result']
    balance_after = (await ipc_request(
        'eth_getBalance',
        [funded_address.hex(),
         to_int(hexstr=block_no_after_transfer)]))['result']

    assert to_int(hexstr=balance_after) < to_int(hexstr=balance_before)
Esempio n. 22
0
    def get_call_params(self, computation: BaseComputation) -> CallParams:
        gas = computation.stack_pop1_int()
        to = 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)

        return (
            gas,
            0,  # value
            to,
            None,  # sender
            None,  # code_address
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
            False,  # should_transfer_value,
            True,  # is_static
        )
Esempio n. 23
0
            assemble(
                opcode_values.PUSH20,
                CANONICAL_ADDRESS_C,
                opcode_values.BALANCE,
                opcode_values.PUSH20,
                CANONICAL_ADDRESS_A,
                opcode_values.BALANCE,
            ),
            3 + 2600 + 3 + 2600,
        ),
        # precompiles are exempt from cold cost
        (
            BerlinVM,
            assemble(
                opcode_values.PUSH20,
                force_bytes_to_address(b'\x05'),
                opcode_values.BALANCE,
            ),
            3 + 100,
        ),
    ))
def test_gas_costs(vm_class, code, expect_gas_used):
    comp = run_computation(setup_vm(vm_class), CANONICAL_ADDRESS_B, code)
    assert comp.is_success
    assert comp.get_gas_used() == expect_gas_used


@pytest.mark.parametrize(
    'vm_class, code, expect_gas_used, access_list',
    (
        # Empty access list does not affect account cache warmth
Esempio n. 24
0
def extcodesize_eip2929(computation: ComputationAPI) -> None:
    address = force_bytes_to_address(computation.stack_pop1_bytes())
    _consume_gas_for_account_load(computation, address, mnemonics.EXTCODEHASH)

    code_size = len(computation.state.get_code(address))
    computation.stack_push_int(code_size)
Esempio n. 25
0
def selfdestruct(computation: BaseComputation) -> None:
    beneficiary = force_bytes_to_address(
        computation.stack_pop(type_hint=constants.BYTES))
    _selfdestruct(computation, beneficiary)
Esempio n. 26
0
from typing import Iterable

from eth_typing import Address

from eth_utils import to_set

from eth import constants

from eth._utils.address import (
    force_bytes_to_address, )

from eth.vm.computation import BaseComputation

THREE = force_bytes_to_address(b'\x03')


@to_set
def collect_touched_accounts(
        computation: BaseComputation) -> Iterable[Address]:
    """
    Collect all of the accounts that *may* need to be deleted based on
    `EIP-161 <https://eips.ethereum.org/EIPS/eip-161>`_.

    Checking whether they *do* need to be deleted happens in the caller.

    See also: https://github.com/ethereum/EIPs/issues/716
    """
    # collect the coinbase account if it was touched via zero-fee transfer
    if computation.is_origin_computation and computation.transaction_context.gas_price == 0:
        yield computation.state.coinbase
Esempio n. 27
0
    ComputationAPI,
)
from eth.exceptions import (
    OutOfGas,
    InsufficientFunds,
    StackDepthLimit,
)
from eth.vm.computation import (
    BaseComputation,
)

from .opcodes import FRONTIER_OPCODES


FRONTIER_PRECOMPILES = {
    force_bytes_to_address(b'\x01'): precompiles.ecrecover,
    force_bytes_to_address(b'\x02'): precompiles.sha256,
    force_bytes_to_address(b'\x03'): precompiles.ripemd160,
    force_bytes_to_address(b'\x04'): precompiles.identity,
}


class FrontierComputation(BaseComputation):
    """
    A class for all execution computations in the ``Frontier`` fork.
    Inherits from :class:`~eth.vm.computation.BaseComputation`
    """
    # Override
    opcodes = FRONTIER_OPCODES
    _precompiles = FRONTIER_PRECOMPILES     # type: ignore # https://github.com/python/mypy/issues/708 # noqa: E501
Esempio n. 28
0
def selfdestruct(computation: ComputationAPI) -> None:
    beneficiary = force_bytes_to_address(computation.stack_pop1_bytes())
    _selfdestruct(computation, beneficiary)
Esempio n. 29
0
import pytest

from eth.estimators.gas import binary_gas_search_1000_tolerance
from eth._utils.address import force_bytes_to_address

from tests.core.helpers import (
    fill_block,
    new_transaction,
)

ADDRESS_2 = b'\0' * 19 + b'\x02'

ADDR_1010 = force_bytes_to_address(b'\x10\x10')


@pytest.fixture
def chain(chain_without_block_validation):
    return chain_without_block_validation


@pytest.mark.parametrize(
    'should_sign_tx',
    (True, False),
)
@pytest.mark.parametrize(
    'data, gas_estimator, to, on_pending, expected',
    (
        (b'', None, ADDR_1010, True, 21000),
        (b'', None, ADDR_1010, False, 21000),
        (b'\xff' * 10, None, ADDR_1010, True, 21680),
        (b'\xff' * 10, None, ADDR_1010, False, 21680),
Esempio n. 30
0
    merge,
)

from eth import precompiles
from eth._utils.address import (
    force_bytes_to_address,
)
from eth.vm.forks.frontier.computation import FRONTIER_PRECOMPILES
from eth.vm.forks.spurious_dragon.computation import SpuriousDragonComputation

from .opcodes import BYZANTIUM_OPCODES

BYZANTIUM_PRECOMPILES = merge(
    FRONTIER_PRECOMPILES,
    {
        force_bytes_to_address(b'\x05'): precompiles.modexp,
        force_bytes_to_address(b'\x06'): precompiles.ecadd,
        force_bytes_to_address(b'\x07'): precompiles.ecmul,
        force_bytes_to_address(b'\x08'): precompiles.ecpairing,
    },
)


class ByzantiumComputation(SpuriousDragonComputation):
    """
    A class for all execution computations in the ``Byzantium`` fork.
    Inherits from :class:`~eth.vm.forks.spurious_dragon.computation.SpuriousDragonComputation`
    """
    # Override
    opcodes = BYZANTIUM_OPCODES
    _precompiles = BYZANTIUM_PRECOMPILES