Ejemplo n.º 1
0
def setup_tester_chain(genesis_params=None, genesis_state=None, num_accounts=None):
    from eth.chains.base import MiningChain
    from eth.db import get_db_backend
    from eth.vm.forks.muir_glacier import MuirGlacierVM

    class MuirGlacierNoProofVM(MuirGlacierVM):
        """Muir Glacier VM rules, without validating any miner proof of work"""

        @classmethod
        def validate_seal(self, header):
            pass

    class MainnetTesterNoProofChain(MiningChain):
        vm_configuration = ((0, MuirGlacierNoProofVM), )

        @classmethod
        def validate_seal(cls, block):
            pass

    if genesis_params is None:
        genesis_params = get_default_genesis_params()

    if genesis_state:
        num_accounts = len(genesis_state)

    account_keys = get_default_account_keys(quantity=num_accounts)

    if genesis_state is None:
        genesis_state = generate_genesis_state_for_keys(account_keys)

    base_db = get_db_backend()

    chain = MainnetTesterNoProofChain.from_genesis(base_db, genesis_params, genesis_state)
    return account_keys, chain
Ejemplo n.º 2
0
def setup_tester_chain():
    from eth.chains.base import MiningChain
    from eth.db import get_db_backend
    from eth.vm.forks.byzantium import ByzantiumVM

    class ByzantiumNoProofVM(ByzantiumVM):
        """Byzantium VM rules, without validating any miner proof of work"""

        @classmethod
        def validate_seal(self, header):
            pass

    class MainnetTesterNoProofChain(MiningChain):
        vm_configuration = ((0, ByzantiumNoProofVM), )

        @classmethod
        def validate_seal(cls, block):
            pass

    genesis_params = get_default_genesis_params()
    account_keys = get_default_account_keys()
    genesis_state = generate_genesis_state(account_keys)

    base_db = get_db_backend()

    chain = MainnetTesterNoProofChain.from_genesis(base_db, genesis_params, genesis_state)
    return account_keys, chain
Ejemplo n.º 3
0
def setup_tester_chain(genesis_params=None,
                       genesis_state=None,
                       num_accounts=None,
                       vm_configuration=None,
                       mnemonic=None):

    from eth.chains.base import MiningChain
    from eth.consensus import (
        NoProofConsensus,
        ConsensusApplier,
    )
    from eth.db import get_db_backend

    if vm_configuration is None:
        from eth.vm.forks import LondonVM
        no_proof_vms = ((0, LondonVM.configure(
            consensus_class=NoProofConsensus)), )
    else:
        consensus_applier = ConsensusApplier(NoProofConsensus)
        no_proof_vms = consensus_applier.amend_vm_configuration(
            vm_configuration)

    class MainnetTesterNoProofChain(MiningChain):
        chain_id = 131277322940537
        vm_configuration = no_proof_vms

        def create_header_from_parent(self, parent_header, **header_params):
            # Keep the gas limit constant
            return super().create_header_from_parent(
                parent_header,
                **assoc(header_params, 'gas_limit', parent_header.gas_limit))

        def get_transaction_builder(self):
            return super().get_vm().get_transaction_builder()

    if genesis_params is None:
        genesis_params = get_default_genesis_params()

    if genesis_state:
        num_accounts = len(genesis_state)

    if mnemonic:
        account_keys = get_account_keys_from_mnemonic(mnemonic,
                                                      quantity=num_accounts)
    else:
        account_keys = get_default_account_keys(quantity=num_accounts)

    if genesis_state is None:
        genesis_state = generate_genesis_state_for_keys(account_keys)

    base_db = get_db_backend()

    chain = MainnetTesterNoProofChain.from_genesis(base_db, genesis_params,
                                                   genesis_state)
    return account_keys, chain
Ejemplo n.º 4
0
def setup_tester_chain(genesis_params=None,
                       genesis_state=None,
                       num_accounts=None,
                       vm_configuration=None):

    from eth.chains.base import MiningChain
    from eth.consensus import (
        NoProofConsensus,
        ConsensusApplier,
    )
    from eth.db import get_db_backend

    if vm_configuration is None:
        from eth.vm.forks.muir_glacier import MuirGlacierVM
        no_proof_vms = ((0,
                         MuirGlacierVM.configure(
                             consensus_class=NoProofConsensus)), )
    else:
        consensus_applier = ConsensusApplier(NoProofConsensus)
        no_proof_vms = consensus_applier.amend_vm_configuration(
            vm_configuration)

    class MainnetTesterNoProofChain(MiningChain):
        vm_configuration = no_proof_vms

        def create_header_from_parent(self, parent_header, **header_params):
            # Keep the gas limit constant
            return super().create_header_from_parent(
                parent_header,
                **assoc(header_params, 'gas_limit', parent_header.gas_limit))

    if genesis_params is None:
        genesis_params = get_default_genesis_params()

    if genesis_state:
        num_accounts = len(genesis_state)

    account_keys = get_default_account_keys(quantity=num_accounts)

    if genesis_state is None:
        genesis_state = generate_genesis_state_for_keys(account_keys)

    base_db = get_db_backend()

    chain = MainnetTesterNoProofChain.from_genesis(base_db, genesis_params,
                                                   genesis_state)
    return account_keys, chain
def _setup_tester_chain(genesis_params, genesis_state, num_accounts):
    class DebugNoProofVM(DebugVM):
        """Byzantium VM rules, without validating any miner proof of work"""
        @classmethod
        def validate_seal(self, header):
            pass

    class MainnetTesterNoProofChain(MiningChain):
        vm_configuration = ((0, DebugNoProofVM), )

    genesis_params = get_default_genesis_params()
    account_keys = get_default_account_keys(quantity=num_accounts)
    genesis_state = generate_genesis_state_for_keys(account_keys)

    base_db = get_db_backend()

    chain = MainnetTesterNoProofChain.from_genesis(base_db, genesis_params,
                                                   genesis_state)
    return account_keys, chain
Ejemplo n.º 6
0
def test_state_fixtures(fixture, fixture_vm_class):
    header = BlockHeader(
        coinbase=fixture['env']['currentCoinbase'],
        difficulty=fixture['env']['currentDifficulty'],
        block_number=fixture['env']['currentNumber'],
        gas_limit=fixture['env']['currentGasLimit'],
        timestamp=fixture['env']['currentTimestamp'],
        parent_hash=fixture['env']['previousHash'],
    )

    chaindb = ChainDB(get_db_backend())
    vm = fixture_vm_class(header=header, chaindb=chaindb)

    state = vm.state
    apply_state_dict(state.account_db, fixture['pre'])
    state.account_db.persist()

    # Update state_root manually
    vm.block = vm.block.copy(header=vm.block.header.copy(
        state_root=state.state_root))
    if 'secretKey' in fixture['transaction']:
        unsigned_transaction = vm.create_unsigned_transaction(
            nonce=fixture['transaction']['nonce'],
            gas_price=fixture['transaction']['gasPrice'],
            gas=fixture['transaction']['gasLimit'],
            to=fixture['transaction']['to'],
            value=fixture['transaction']['value'],
            data=fixture['transaction']['data'],
        )
        private_key = keys.PrivateKey(fixture['transaction']['secretKey'])
        transaction = unsigned_transaction.as_signed_transaction(
            private_key=private_key)
    elif 'vrs' in fixture['transaction']:
        v, r, s = (
            fixture['transaction']['v'],
            fixture['transaction']['r'],
            fixture['transaction']['s'],
        )
        transaction = vm.create_transaction(
            nonce=fixture['transaction']['nonce'],
            gas_price=fixture['transaction']['gasPrice'],
            gas=fixture['transaction']['gasLimit'],
            to=fixture['transaction']['to'],
            value=fixture['transaction']['value'],
            data=fixture['transaction']['data'],
            v=v,
            r=r,
            s=s,
        )

    try:
        header, receipt, computation = vm.apply_transaction(
            vm.block.header, transaction)
        transactions = vm.block.transactions + (transaction, )
        receipts = vm.block.get_receipts(chaindb) + (receipt, )
        block = vm.set_block_transactions(vm.block, header, transactions,
                                          receipts)
    except ValidationError as err:
        block = vm.block
        transaction_error = err
        logger.warn("Got transaction error", exc_info=True)
    else:
        transaction_error = False

    if not transaction_error:
        log_entries = computation.get_log_entries()
        actual_logs_hash = hash_log_entries(log_entries)
        if 'logs' in fixture['post']:
            expected_logs_hash = fixture['post']['logs']
            assert expected_logs_hash == actual_logs_hash
        elif log_entries:
            raise AssertionError("Got log {0} entries. hash:{1}".format(
                len(log_entries),
                actual_logs_hash,
            ))

        if 'out' in fixture:
            expected_output = fixture['out']
            if isinstance(expected_output, int):
                assert len(computation.output) == expected_output
            else:
                assert computation.output == expected_output

    assert block.header.state_root == fixture['post']['hash']
def test_vm_fixtures(fixture, vm_class, computation_getter):
    db = get_db_backend()
    chaindb = ChainDB(db)
    consensus_context = ConsensusContext(db)
    header = BlockHeader(
        coinbase=fixture['env']['currentCoinbase'],
        difficulty=fixture['env']['currentDifficulty'],
        block_number=fixture['env']['currentNumber'],
        gas_limit=fixture['env']['currentGasLimit'],
        timestamp=fixture['env']['currentTimestamp'],
    )

    # None of the VM tests (currently) test chain ID, so the setting doesn't matter here.
    #   When they *do* start testing ID, they will have to supply it as part of the environment.
    #   For now, just hard-code it to something not used in practice:
    chain_context = ChainContext(chain_id=0)

    vm = vm_class(header=header,
                  chaindb=chaindb,
                  chain_context=chain_context,
                  consensus_context=consensus_context)
    state = vm.state
    setup_state(fixture['pre'], state)
    code = state.get_code(fixture['exec']['address'])
    # Update state_root manually
    vm._block = vm.get_block().copy(header=vm.get_header().copy(
        state_root=state.state_root))

    message = Message(
        to=fixture['exec']['address'],
        sender=fixture['exec']['caller'],
        value=fixture['exec']['value'],
        data=fixture['exec']['data'],
        code=code,
        gas=fixture['exec']['gas'],
    )
    transaction_context = BaseTransactionContext(
        origin=fixture['exec']['origin'],
        gas_price=fixture['exec']['gasPrice'],
    )
    computation = vm.state.get_computation(
        message, transaction_context).apply_computation(
            vm.state,
            message,
            transaction_context,
        )
    # Update state_root manually
    vm._block = vm.get_block().copy(
        header=vm.get_header().copy(state_root=computation.state.state_root), )

    if 'post' in fixture:
        #
        # Success checks
        #
        assert not computation.is_error

        log_entries = computation.get_log_entries()
        if 'logs' in fixture:
            actual_logs_hash = hash_log_entries(log_entries)
            expected_logs_hash = fixture['logs']
            assert expected_logs_hash == actual_logs_hash
        elif log_entries:
            raise AssertionError(f"Got log entries: {log_entries}")

        expected_output = fixture['out']
        assert computation.output == expected_output

        gas_meter = computation._gas_meter

        expected_gas_remaining = fixture['gas']
        actual_gas_remaining = gas_meter.gas_remaining
        gas_delta = actual_gas_remaining - expected_gas_remaining
        assert gas_delta == 0, f"Gas difference: {gas_delta}"

        call_creates = fixture.get('callcreates', [])
        assert len(computation.children) == len(call_creates)

        call_creates = fixture.get('callcreates', [])
        for child_computation, created_call in zip(computation.children,
                                                   call_creates):
            to_address = created_call['destination']
            data = created_call['data']
            gas_limit = created_call['gasLimit']
            value = created_call['value']

            assert child_computation.msg.to == to_address
            assert data == child_computation.msg.data or child_computation.msg.code
            assert gas_limit == child_computation.msg.gas
            assert value == child_computation.msg.value
        expected_account_db = fixture['post']
    else:
        #
        # Error checks
        #
        assert computation.is_error
        assert isinstance(computation._error, VMError)
        expected_account_db = fixture['pre']

    verify_state(expected_account_db, vm.state)
Ejemplo n.º 8
0
def test_vm_fixtures(fixture, vm_class, computation_getter):
    chaindb = ChainDB(get_db_backend())
    header = BlockHeader(
        coinbase=fixture['env']['currentCoinbase'],
        difficulty=fixture['env']['currentDifficulty'],
        block_number=fixture['env']['currentNumber'],
        gas_limit=fixture['env']['currentGasLimit'],
        timestamp=fixture['env']['currentTimestamp'],
    )
    vm = vm_class(header=header, chaindb=chaindb)
    state = vm.state
    setup_state(fixture['pre'], state)
    code = state.get_code(fixture['exec']['address'])
    # Update state_root manually
    vm._block = vm.get_block().copy(header=vm.get_header().copy(
        state_root=state.state_root))

    message = Message(
        to=fixture['exec']['address'],
        sender=fixture['exec']['caller'],
        value=fixture['exec']['value'],
        data=fixture['exec']['data'],
        code=code,
        gas=fixture['exec']['gas'],
    )
    transaction_context = BaseTransactionContext(
        origin=fixture['exec']['origin'],
        gas_price=fixture['exec']['gasPrice'],
    )
    computation = vm.state.get_computation(
        message, transaction_context).apply_computation(
            vm.state,
            message,
            transaction_context,
        )
    # Update state_root manually
    vm._block = vm.get_block().copy(
        header=vm.get_header().copy(state_root=computation.state.state_root), )

    if 'post' in fixture:
        #
        # Success checks
        #
        assert not computation.is_error

        log_entries = computation.get_log_entries()
        if 'logs' in fixture:
            actual_logs_hash = hash_log_entries(log_entries)
            expected_logs_hash = fixture['logs']
            assert expected_logs_hash == actual_logs_hash
        elif log_entries:
            raise AssertionError("Got log entries: {0}".format(log_entries))

        expected_output = fixture['out']
        assert computation.output == expected_output

        gas_meter = computation._gas_meter

        expected_gas_remaining = fixture['gas']
        actual_gas_remaining = gas_meter.gas_remaining
        gas_delta = actual_gas_remaining - expected_gas_remaining
        assert gas_delta == 0, "Gas difference: {0}".format(gas_delta)

        call_creates = fixture.get('callcreates', [])
        assert len(computation.children) == len(call_creates)

        call_creates = fixture.get('callcreates', [])
        for child_computation, created_call in zip(computation.children,
                                                   call_creates):
            to_address = created_call['destination']
            data = created_call['data']
            gas_limit = created_call['gasLimit']
            value = created_call['value']

            assert child_computation.msg.to == to_address
            assert data == child_computation.msg.data or child_computation.msg.code
            assert gas_limit == child_computation.msg.gas
            assert value == child_computation.msg.value
        expected_account_db = fixture['post']
    else:
        #
        # Error checks
        #
        assert computation.is_error
        assert isinstance(computation._error, VMError)
        expected_account_db = fixture['pre']

    verify_state(expected_account_db, vm.state)
Ejemplo n.º 9
0
def test_raises_if_db_path_is_not_specified(config_env):
    with pytest.raises(TypeError):
        get_db_backend()
Ejemplo n.º 10
0
def level_db(config_env, tmpdir):
    level_db_path = str(tmpdir.mkdir("level_db_path"))
    return get_db_backend(db_path=level_db_path)
Ejemplo n.º 11
0
def shard_db():
    return ShardDB(get_db_backend())
Ejemplo n.º 12
0
def test_state_fixtures(fixture, fixture_vm_class):
    header = BlockHeader(
        coinbase=fixture['env']['currentCoinbase'],
        difficulty=fixture['env']['currentDifficulty'],
        block_number=fixture['env']['currentNumber'],
        gas_limit=fixture['env']['currentGasLimit'],
        timestamp=fixture['env']['currentTimestamp'],
        parent_hash=fixture['env']['previousHash'],
    )

    chaindb = ChainDB(get_db_backend())
    vm = fixture_vm_class(header=header, chaindb=chaindb)

    state = vm.state
    apply_state_dict(state.account_db, fixture['pre'])
    state.account_db.persist()

    # Update state_root manually
    vm.block = vm.block.copy(header=vm.block.header.copy(
        state_root=state.state_root))
    if 'secretKey' in fixture['transaction']:
        unsigned_transaction = vm.create_unsigned_transaction(
            nonce=fixture['transaction']['nonce'],
            gas_price=fixture['transaction']['gasPrice'],
            gas=fixture['transaction']['gasLimit'],
            to=fixture['transaction']['to'],
            value=fixture['transaction']['value'],
            data=fixture['transaction']['data'],
        )
        private_key = keys.PrivateKey(fixture['transaction']['secretKey'])
        transaction = unsigned_transaction.as_signed_transaction(
            private_key=private_key)
    elif 'vrs' in fixture['transaction']:
        v, r, s = (
            fixture['transaction']['v'],
            fixture['transaction']['r'],
            fixture['transaction']['s'],
        )
        transaction = vm.create_transaction(
            nonce=fixture['transaction']['nonce'],
            gas_price=fixture['transaction']['gasPrice'],
            gas=fixture['transaction']['gasLimit'],
            to=fixture['transaction']['to'],
            value=fixture['transaction']['value'],
            data=fixture['transaction']['data'],
            v=v,
            r=r,
            s=s,
        )
    else:
        raise Exception("Invariant: No transaction specified")

    try:
        header, receipt, computation = vm.apply_transaction(
            vm.block.header, transaction)
    except ValidationError as err:
        logger.warning("Got transaction error", exc_info=True)
        transaction_error = err
    else:
        transaction_error = False

        transactions = vm.block.transactions + (transaction, )
        receipts = vm.block.get_receipts(chaindb) + (receipt, )
        vm.block = vm.set_block_transactions(vm.block, header, transactions,
                                             receipts)
    finally:
        # This is necessary due to the manner in which the state tests are
        # generated. State tests are generated from the BlockChainTest tests
        # in which these transactions are included in the larger context of a
        # block and thus, the mechanisms which would touch/create/clear the
        # coinbase account based on the mining reward are present during test
        # generation, but not part of the execution, thus we must artificially
        # create the account in VMs prior to the state clearing rules,
        # as well as conditionally cleaning up the coinbase account when left
        # empty in VMs after the state clearing rules came into effect.
        # Related change in geth:
        # https://github.com/ethereum/go-ethereum/commit/32f28a9360d26a661d55915915f12fd3c70f012b#diff-f53696be8527ac422b8d4de7c8e945c1R149  # noqa: E501

        if isinstance(vm, PRE_STATE_CLEARING_VMS):
            state.account_db.touch_account(vm.block.header.coinbase)
            state.account_db.persist()
            vm.block = vm.block.copy(header=vm.block.header.copy(
                state_root=state.state_root))
        elif state.account_db.account_is_empty(vm.block.header.coinbase):
            state.account_db.delete_account(vm.block.header.coinbase)
            state.account_db.persist()
            vm.block = vm.block.copy(header=vm.block.header.copy(
                state_root=state.state_root))

        block = vm.block

    if not transaction_error:
        log_entries = computation.get_log_entries()
        actual_logs_hash = hash_log_entries(log_entries)
        if 'logs' in fixture['post']:
            expected_logs_hash = fixture['post']['logs']
            assert expected_logs_hash == actual_logs_hash
        elif log_entries:
            raise AssertionError("Got log {0} entries. hash:{1}".format(
                len(log_entries),
                actual_logs_hash,
            ))

        if 'out' in fixture:
            expected_output = fixture['out']
            if isinstance(expected_output, int):
                assert len(computation.output) == expected_output
            else:
                assert computation.output == expected_output

    assert block.header.state_root == fixture['post']['hash']