def test_configure_duplicate_block_numbers_in_vm_configuration():
    with pytest.raises(ValidationError):
        Chain.configure('TestChain',
                        vm_configuration=[
                            (0, FrontierVM),
                            (0, HomesteadVM),
                        ])
Esempio n. 2
0
def test_vm_not_found_if_no_matching_block_number():
    chain_class = Chain.configure('TestChain', vm_configuration=(
        (10, FrontierVM),
    ))
    chain = chain_class(get_db_backend(), BlockHeader(1, 0, 100))
    with pytest.raises(VMNotFound):
        chain.get_vm_class_for_block_number(9)
Esempio n. 3
0
def chain_without_block_validation():
    """
    Return a Chain object containing just the genesis block.

    This Chain does not perform any validation when importing new blocks.

    The Chain's state includes one funded account and a private key for it, which can be found in
    the funded_address and private_keys variables in the chain itself.
    """
    # Disable block validation so that we don't need to construct finalized blocks.
    overrides = {
        'ensure_blocks_are_equal': lambda self, b1, b2: None,
        'validate_block': lambda self, block: None,
    }
    klass = Chain.configure(
        name='TestChainWithoutBlockValidation',
        vm_configuration=((constants.GENESIS_BLOCK_NUMBER, FrontierVM), ),
        **overrides,
    )
    private_key = decode_hex(
        '0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8')
    funded_addr = private_key_to_address(private_key)
    initial_balance = 100000000
    genesis_params = {
        'block_number':
        constants.GENESIS_BLOCK_NUMBER,
        'difficulty':
        constants.GENESIS_DIFFICULTY,
        'gas_limit':
        constants.GENESIS_GAS_LIMIT,
        'parent_hash':
        constants.GENESIS_PARENT_HASH,
        'coinbase':
        constants.GENESIS_COINBASE,
        'nonce':
        constants.GENESIS_NONCE,
        'mix_hash':
        constants.GENESIS_MIX_HASH,
        'extra_data':
        constants.GENESIS_EXTRA_DATA,
        'timestamp':
        1501851927,
        'state_root':
        decode_hex(
            '0x9d354f9b5ba851a35eced279ef377111387197581429cfcc7f744ef89a30b5d4'
        )
    }
    genesis_state = {
        funded_addr: {
            'balance': initial_balance,
            'nonce': 0,
            'code': b'',
            'storage': {},
        }
    }
    chain = klass.from_genesis(get_db_backend(), genesis_params, genesis_state)
    chain.funded_address = funded_addr
    chain.funded_address_initial_balance = initial_balance
    chain.funded_address_private_key = private_key
    return chain
def test_vm_not_found_if_no_matching_block_number():
    chain_class = Chain.configure('TestChain', vm_configuration=(
        (10, FrontierVM),
    ))
    chain = chain_class(get_db_backend(), BlockHeader(1, 0, 100))
    with pytest.raises(VMNotFound):
        chain.get_vm_class_for_block_number(9)
Esempio n. 5
0
def chain_without_pow(base_db: MemoryDB, vm: Type[BaseVM], genesis_params: Any,
                      genesis_state: Any) -> Chain:

    vm_without_pow = vm.configure(validate_seal=lambda block: None)

    klass = Chain.configure(__name__='TestChain',
                            vm_configuration=((constants.GENESIS_BLOCK_NUMBER,
                                               vm_without_pow), ))
    chain = klass.from_genesis(base_db, genesis_params, genesis_state)
    return chain
Esempio n. 6
0
def test_get_vm_class_for_block_number():
    chain_class = Chain.configure(vm_configuration=(
        (constants.GENESIS_BLOCK_NUMBER, FrontierVM),
        (constants.HOMESTEAD_MAINNET_BLOCK, HomesteadVM),
    ), )
    chain = chain_class(get_db_backend(), BlockHeader(1, 0, 100))
    assert chain.get_vm_class_for_block_number(
        constants.GENESIS_BLOCK_NUMBER, ) == FrontierVM
    assert chain.get_vm_class_for_block_number(
        constants.HOMESTEAD_MAINNET_BLOCK - 1) == FrontierVM
    assert chain.get_vm_class_for_block_number(
        constants.HOMESTEAD_MAINNET_BLOCK) == HomesteadVM
    assert chain.get_vm_class_for_block_number(
        constants.HOMESTEAD_MAINNET_BLOCK + 1) == HomesteadVM
def test_get_vm_class_for_block_number():
    chain_class = Chain.configure(
        name='TestChain',
        vm_configuration=(
            (constants.GENESIS_BLOCK_NUMBER, FrontierVM),
            (HOMESTEAD_MAINNET_BLOCK, HomesteadVM),
        ),
    )
    chain = chain_class(get_db_backend(), BlockHeader(1, 0, 100))
    assert chain.get_vm_class_for_block_number(
        constants.GENESIS_BLOCK_NUMBER,) == FrontierVM
    assert chain.get_vm_class_for_block_number(
        HOMESTEAD_MAINNET_BLOCK - 1) == FrontierVM
    assert chain.get_vm_class_for_block_number(
        HOMESTEAD_MAINNET_BLOCK) == HomesteadVM
    assert chain.get_vm_class_for_block_number(
        HOMESTEAD_MAINNET_BLOCK + 1) == HomesteadVM
Esempio n. 8
0
def chain_without_block_validation(base_db, funded_address,
                                   funded_address_initial_balance):
    """
    Return a Chain object containing just the genesis block.

    This Chain does not perform any validation when importing new blocks.

    The Chain's state includes one funded account and a private key for it,
    which can be found in the funded_address and private_keys variables in the
    chain itself.
    """
    # Disable block validation so that we don't need to construct finalized blocks.
    overrides = {
        'import_block': import_block_without_validation,
        'validate_block': lambda self, block: None,
    }
    SpuriousDragonVMForTesting = SpuriousDragonVM.configure(
        validate_seal=lambda self, block: None)
    klass = Chain.configure(
        __name__='TestChainWithoutBlockValidation',
        vm_configuration=((constants.GENESIS_BLOCK_NUMBER,
                           SpuriousDragonVMForTesting), ),
        **overrides,
    )
    genesis_params = {
        'block_number': constants.GENESIS_BLOCK_NUMBER,
        'difficulty': constants.GENESIS_DIFFICULTY,
        'gas_limit': constants.GENESIS_GAS_LIMIT,
        'parent_hash': constants.GENESIS_PARENT_HASH,
        'coinbase': constants.GENESIS_COINBASE,
        'nonce': constants.GENESIS_NONCE,
        'mix_hash': constants.GENESIS_MIX_HASH,
        'extra_data': constants.GENESIS_EXTRA_DATA,
        'timestamp': 1501851927,
    }
    genesis_state = {
        funded_address: {
            'balance': funded_address_initial_balance,
            'nonce': 0,
            'code': b'',
            'storage': {},
        }
    }
    chain = klass.from_genesis(base_db, genesis_params, genesis_state)
    return chain
Esempio n. 9
0
def chain_with_block_validation(base_db, funded_address, funded_address_initial_balance):
    """
    Return a Chain object containing just the genesis block.

    The Chain's state includes one funded account, which can be found in the
    funded_address in the chain itself.

    This Chain will perform all validations when importing new blocks, so only
    valid and finalized blocks can be used with it. If you want to test
    importing arbitrarily constructe, not finalized blocks, use the
    chain_without_block_validation fixture instead.
    """
    genesis_params = {
        "bloom": 0,
        "coinbase": to_canonical_address("8888f1f195afa192cfee860698584c030f4c9db1"),
        "difficulty": 131072,
        "extra_data": b"B",
        "gas_limit": 3141592,
        "gas_used": 0,
        "mix_hash": decode_hex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),  # noqa: E501
        "nonce": decode_hex("0102030405060708"),
        "block_number": 0,
        "parent_hash": decode_hex("0000000000000000000000000000000000000000000000000000000000000000"),  # noqa: E501
        "receipt_root": decode_hex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),  # noqa: E501
        "timestamp": 1422494849,
        "transaction_root": decode_hex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),  # noqa: E501
        "uncles_hash": decode_hex("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")  # noqa: E501
    }
    genesis_state = {
        funded_address: {
            "balance": funded_address_initial_balance,
            "nonce": 0,
            "code": b"",
            "storage": {}
        }
    }
    klass = Chain.configure(
        __name__='TestChain',
        vm_configuration=(
            (constants.GENESIS_BLOCK_NUMBER, SpuriousDragonVM),
        ),
        network_id=1337,
    )
    chain = klass.from_genesis(base_db, genesis_params, genesis_state)
    return chain
def test_configure_duplicate_block_numbers_in_vm_configuration():
    with pytest.raises(ValidationError):
        Chain.configure('TestChain', vm_configuration=[
            (0, FrontierVM),
            (0, HomesteadVM),
        ])
def test_header_chain_invalid_if_no_vm_configuration(base_db, genesis_header):
    chain_class = Chain.configure('ChainNoEmptyConfiguration', vm_configuration=())
    with pytest.raises(ValueError):
        chain_class(base_db, genesis_header)
Esempio n. 12
0
def chain():
    """
    Return a Chain object containing just the genesis block.

    The Chain's state includes one funded account, which can be found in the funded_address in the
    chain itself.

    This Chain will perform all validations when importing new blocks, so only valid and finalized
    blocks can be used with it. If you want to test importing arbitrarily constructe, not
    finalized blocks, use the chain_without_block_validation fixture instead.
    """
    genesis_params = {
        "bloom":
        0,
        "coinbase":
        to_canonical_address("8888f1f195afa192cfee860698584c030f4c9db1"),
        "difficulty":
        131072,
        "extra_data":
        b"B",
        "gas_limit":
        3141592,
        "gas_used":
        0,
        "mix_hash":
        decode_hex(
            "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
        ),
        "nonce":
        decode_hex("0102030405060708"),
        "block_number":
        0,
        "parent_hash":
        decode_hex(
            "0000000000000000000000000000000000000000000000000000000000000000"
        ),
        "receipt_root":
        decode_hex(
            "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
        ),
        "state_root":
        decode_hex(
            "cafd881ab193703b83816c49ff6c2bf6ba6f464a1be560c42106128c8dbc35e7"
        ),
        "timestamp":
        1422494849,
        "transaction_root":
        decode_hex(
            "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
        ),
        "uncles_hash":
        decode_hex(
            "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
    }
    funded_addr = to_canonical_address(
        "a94f5374fce5edbc8e2a8697c15331677e6ebf0b")
    initial_balance = 10000000000
    genesis_state = {
        funded_addr: {
            "balance": initial_balance,
            "nonce": 0,
            "code": b"",
            "storage": {}
        }
    }
    klass = Chain.configure(name='TestChain',
                            vm_configuration=((constants.GENESIS_BLOCK_NUMBER,
                                               FrontierVM), ))
    chain = klass.from_genesis(ChainDB(get_db_backend()), genesis_params,
                               genesis_state)
    chain.funded_address = funded_addr
    chain.funded_address_initial_balance = initial_balance
    return chain
Esempio n. 13
0
def test_blockchain_fixtures(fixture_name, fixture):
    genesis_params = {
        'parent_hash': fixture['genesisBlockHeader']['parentHash'],
        'uncles_hash': fixture['genesisBlockHeader']['uncleHash'],
        'coinbase': fixture['genesisBlockHeader']['coinbase'],
        'state_root': fixture['genesisBlockHeader']['stateRoot'],
        'transaction_root': fixture['genesisBlockHeader']['transactionsTrie'],
        'receipt_root': fixture['genesisBlockHeader']['receiptTrie'],
        'bloom': fixture['genesisBlockHeader']['bloom'],
        'difficulty': fixture['genesisBlockHeader']['difficulty'],
        'block_number': fixture['genesisBlockHeader']['number'],
        'gas_limit': fixture['genesisBlockHeader']['gasLimit'],
        'gas_used': fixture['genesisBlockHeader']['gasUsed'],
        'timestamp': fixture['genesisBlockHeader']['timestamp'],
        'extra_data': fixture['genesisBlockHeader']['extraData'],
        'mix_hash': fixture['genesisBlockHeader']['mixHash'],
        'nonce': fixture['genesisBlockHeader']['nonce'],
    }
    expected_genesis_header = BlockHeader(**genesis_params)

    # TODO: find out if this is supposed to pass?
    # if 'genesisRLP' in fixture:
    #     assert rlp.encode(genesis_header) == fixture['genesisRLP']

    db = get_db_backend()
    chain = MainnetChain
    # TODO: It would be great if we can figure out an API for re-configuring
    # start block numbers that was more elegant.
    if fixture_name.startswith('Homestead'):
        chain = Chain.configure('HomesteadChain',
                                vm_configuration=[(0, HomesteadVM)])
    elif fixture_name.startswith('EIP150'):
        chain = Chain.configure('EIP150VM', vm_configuration=[(0, EIP150VM)])
    elif fixture_name.startswith('TestNetwork'):
        homestead_vm = HomesteadVM.configure(dao_fork_block_number=8)
        chain = Chain.configure('TestNetworkChain',
                                vm_configuration=[
                                    (0, FrontierVM),
                                    (5, homestead_vm),
                                    (10, EIP150VM),
                                ])

    chain = chain.from_genesis(
        db,
        genesis_params=genesis_params,
        genesis_state=fixture['pre'],
    )

    genesis_block = chain.get_canonical_block_by_number(0)
    genesis_header = genesis_block.header

    assert_rlp_equal(genesis_header, expected_genesis_header)

    # 1 - mine the genesis block
    # 2 - loop over blocks:
    #     - apply transactions
    #     - mine block
    # 4 - profit!!

    for block_data in fixture['blocks']:
        should_be_good_block = 'blockHeader' in block_data

        if 'rlp_error' in block_data:
            assert not should_be_good_block
            continue

        # The block to import may be in a different block-class-range than the
        # chain's current one, so we use the block number specified in the
        # fixture to look up the correct block class.
        if should_be_good_block:
            block_number = block_data['blockHeader']['number']
            block_class = chain.get_vm_class_for_block_number(
                block_number).get_block_class()
        else:
            block_class = chain.get_vm().get_block_class()

        try:
            block = rlp.decode(block_data['rlp'], sedes=block_class, db=db)
        except (TypeError, rlp.DecodingError, rlp.DeserializationError) as err:
            assert not should_be_good_block, "Block should be good: {0}".format(
                err)
            continue

        try:
            mined_block = chain.import_block(block)
        except ValidationError as err:
            assert not should_be_good_block, "Block should be good: {0}".format(
                err)
            continue
        else:
            assert_rlp_equal(mined_block, block)
            assert should_be_good_block, "Block should have caused a validation error"

    latest_block_hash = chain.get_canonical_block_by_number(
        chain.get_block().number - 1).hash
    assert latest_block_hash == fixture['lastblockhash']

    verify_state_db(fixture['postState'], chain.get_state_db())
Esempio n. 14
0
from evm import constants
from evm import Chain

from evm.vm.flavors import (
    EIP150VM,
    FrontierVM,
    HomesteadVM,
)

MainnetChain = Chain.configure(
    'MainnetChain',
    vm_configuration=((0, FrontierVM), (constants.HOMESTEAD_MAINNET_BLOCK,
                                        HomesteadVM),
                      (constants.EIP150_MAINNET_BLOCK, EIP150VM)))
def test_vm_not_found_if_no_matching_block_number(genesis_header):
    chain_class = Chain.configure('ChainStartsAtBlock10', vm_configuration=(
        (10, VM_A),
    ))
    with pytest.raises(VMNotFound):
        chain_class.get_vm_class_for_block_number(9)
def test_configure_invalid_block_number_in_vm_configuration():
    with pytest.raises(ValidationError):
        Chain.configure('TestChain', vm_configuration=[(-1, FrontierVM)])
def test_invalid_if_no_vm_configuration():
    chain_class = Chain.configure('TestChain', vm_configuration=())
    with pytest.raises(ValueError):
        chain_class(get_db_backend(), BlockHeader(1, 0, 100))
Esempio n. 18
0
    name='HomesteadVMForTesting',
    apply_message=apply_create_message_for_testing,
    apply_create_message=apply_create_message_for_testing,
    get_ancestor_hash=get_block_hash_for_testing,
)
EIP150VMForTesting = EIP150VM.configure(
    name='EIP150VMForTesting',
    apply_message=apply_create_message_for_testing,
    apply_create_message=apply_create_message_for_testing,
    get_ancestor_hash=get_block_hash_for_testing,
)

ChainForTesting = Chain.configure(
    name='ChainForTesting',
    vm_configuration=(
        (constants.GENESIS_BLOCK_NUMBER, FrontierVMForTesting),
        (constants.HOMESTEAD_MAINNET_BLOCK, HomesteadVMForTesting),
        (constants.EIP150_MAINNET_BLOCK, EIP150VMForTesting),
    ),
)


@pytest.mark.parametrize(
    'fixture_name,fixture',
    FIXTURES,
)
def test_vm_fixtures(fixture_name, fixture):
    db = get_db_backend()
    header = BlockHeader(
        coinbase=fixture['env']['currentCoinbase'],
        difficulty=fixture['env']['currentDifficulty'],
        block_number=fixture['env']['currentNumber'],
def test_configure_invalid_block_number_in_vm_configuration():
    with pytest.raises(ValidationError):
        Chain.configure('TestChain', vm_configuration=[(-1, FrontierVM)])
def test_invalid_if_no_vm_configuration():
    chain_class = Chain.configure('TestChain', vm_configuration=())
    with pytest.raises(ValueError):
        chain_class(get_db_backend(), BlockHeader(1, 0, 100))