Example #1
0
def test_transaction_fixtures(fixture_name, fixture):
    header = BlockHeader(1, fixture.get('blocknumber', 0), 100)
    evm = MainnetEVM(MemoryDB(), header=header)
    vm = evm.get_vm()
    TransactionClass = vm.get_transaction_class()

    if 'sender' in fixture:
        transaction = rlp.decode(fixture['rlp'], sedes=TransactionClass)
        expected = normalize_signed_transaction(fixture['transaction'])

        assert transaction.nonce == expected['nonce']
        assert transaction.gas_price == expected['gasPrice']
        assert transaction.gas == expected['gasLimit']
        assert transaction.to == expected['to']
        assert transaction.value == expected['value']
        assert transaction.data == expected['data']
        assert transaction.v == expected['v']
        assert transaction.r == expected['r']
        assert transaction.s == expected['s']

        sender = to_canonical_address(fixture['sender'])

        assert transaction.sender == sender
    else:
        # check RLP correctness
        try:
            transaction = rlp.decode(fixture['rlp'], sedes=TransactionClass)
        except rlp.exceptions.ObjectDeserializationError:
            return

        # check parameter correctness
        try:
            transaction.validate()
        except ValidationError:
            return
Example #2
0
def test_trie_using_fixtures(fixture_name, fixture):

    keys_and_values = fixture['in']
    deletes = tuple(k for k, v in keys_and_values if v is None)
    remaining = {k: v for k, v in keys_and_values if k not in deletes}

    for kv_permutation in itertools.islice(
            itertools.permutations(keys_and_values), 100):
        print("in it")
        trie = Trie(db=MemoryDB())

        for key, value in kv_permutation:
            if value is None:
                del trie[key]
            else:
                trie[key] = value
        for key in deletes:
            del trie[key]

        for key, expected_value in remaining.items():
            assert key in trie
            actual_value = trie[key]
            assert actual_value == expected_value

        for key in deletes:
            assert key not in trie

        expected_root = fixture['root']
        actual_root = trie.root_hash

        assert actual_root == expected_root
Example #3
0
def test_state_fixtures(fixture_name, fixture):
    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'],
    )
    db = MemoryDB()
    meta_evm = EVMForTesting.configure(db=db)(header=header)
    evm = meta_evm.get_evm()
    block = evm.block

    setup_state_db(fixture['pre'], evm.state_db)

    Transaction = evm.get_transaction_class()

    unsigned_transaction = Transaction.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'],
    )
    transaction = unsigned_transaction.as_signed_transaction(
        private_key=fixture['transaction']['secretKey'])

    try:
        computation = evm.apply_transaction(transaction)
    except InvalidTransaction:
        transaction_error = True
    else:
        transaction_error = False

    if not transaction_error:
        expected_logs = [{
            'address': log_entry[0],
            'topics': log_entry[1],
            'data': log_entry[2],
        } for log_entry in computation.get_log_entries()]
        expected_logs == fixture['logs']

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

    verify_state_db(fixture['post'], evm.state_db)
Example #4
0
def test_get_vm_class_for_block_number():
    evm_class = EVM.configure(
        vm_configuration=(
            (constants.GENESIS_BLOCK_NUMBER, FrontierVM),
            (constants.HOMESTEAD_MAINNET_BLOCK, HomesteadVM),
        ),
    )
    evm = evm_class(MemoryDB(), BlockHeader(1, 0, 100))
    assert evm.get_vm_class_for_block_number(
        constants.GENESIS_BLOCK_NUMBER,) == FrontierVM
    assert evm.get_vm_class_for_block_number(
        constants.HOMESTEAD_MAINNET_BLOCK - 1) == FrontierVM
    assert evm.get_vm_class_for_block_number(
        constants.HOMESTEAD_MAINNET_BLOCK) == HomesteadVM
    assert evm.get_vm_class_for_block_number(
        constants.HOMESTEAD_MAINNET_BLOCK + 1) == HomesteadVM
Example #5
0
    def load_state(cls, dbfile=None):
        """ Create or load State.
        returns: (State, is_new) where 'is_new' is T|F indicating whether
        this the first run.
        """
        if not dbfile:
            return (cls(MemoryDB(), b'testchain', 0, BLANK_ROOT_HASH), True)

        # ASSSUMES THE PATH TO THE FILE EXISTS - IF NEW
        db = VanillaDB(dbfile)
        serial = db.get(CHAIN_METADATA_KEY)
        if serial:
            meta = rlp.decode(serial, sedes=chainMetaData)
            return (cls(db, meta.chainid, meta.height,
                        meta.apphash), db.is_new)

        return (cls(db, b'', 0, BLANK_ROOT_HASH), db.is_new)
Example #6
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 = MemoryDB()
    evm = MainnetEVM.from_genesis(
        db,
        genesis_params=genesis_params,
        genesis_state=fixture['pre'],
    )

    genesis_block = evm.get_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

        try:
            block = rlp.decode(
                block_data['rlp'],
                sedes=evm.get_vm().get_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 = evm.import_block(block)
            assert_rlp_equal(mined_block, block)
        except ValidationError as err:
            assert not should_be_good_block, "Block should be good: {0}".format(
                err)
            continue
        else:
            assert should_be_good_block, "Block should have caused a validation error"

    assert evm.get_block_by_number(evm.get_block().number -
                                   1).hash == fixture['lastblockhash']

    verify_state_db(fixture['postState'], evm.get_state_db())
Example #7
0
 def load_state(cls, dbfile=None):
     """ Create or load State.
     returns: State
     """
     if not dbfile:
         return (cls(MemoryDB(), 0, 0, BLANK_ROOT_HASH))
Example #8
0
def test_vm_success_using_fixture(fixture_name, fixture):
    db = MemoryDB()
    meta_evm = EVMForTesting(db=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'],
        parent_hash=fixture['env']['previousHash'],
    )
    evm = meta_evm(header=header)
    block = evm.block

    setup_state_db(fixture['pre'], block.state_db)

    Transaction = evm.get_transaction_class()

    unsigned_transaction = Transaction.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'],
    )
    transaction = unsigned_transaction.as_signed_transaction(
        private_key=fixture['transaction']['secretKey'])

    try:
        computation = evm.apply_transaction(transaction)
    except InvalidTransaction:
        transaction_error = True
    else:
        transaction_error = False

    if not transaction_error:
        expected_logs = [{
            'address': log_entry[0],
            'topics': log_entry[1],
            'data': log_entry[2],
        } for log_entry in computation.get_log_entries()]
        expected_logs == fixture['logs']

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

    for account, account_data in sorted(fixture['post'].items()):
        for slot, expected_storage_value in sorted(
                account_data['storage'].items()):
            actual_storage_value = evm.block.state_db.get_storage(
                account, slot)

            assert actual_storage_value == expected_storage_value

        expected_nonce = account_data['nonce']
        expected_code = account_data['code']
        expected_balance = account_data['balance']

        actual_nonce = evm.block.state_db.get_nonce(account)
        actual_code = evm.block.state_db.get_code(account)
        actual_balance = evm.block.state_db.get_balance(account)
        balance_delta = expected_balance - actual_balance

        assert actual_nonce == expected_nonce
        assert actual_code == expected_code
        assert balance_delta == 0, "Expected: {0} - Actual: {1} | Delta: {2}".format(
            expected_balance, actual_balance, balance_delta)

    assert evm.block.state_db.state.root_hash == fixture['postStateRoot']
Example #9
0
def test_get_vm_class_for_block_number_evm_not_found():
    evm_class = EVM.configure(vm_configuration=())
    evm = evm_class(MemoryDB(), BlockHeader(1, 0, 100))
    with pytest.raises(EVMNotFound):
        evm.get_vm_class_for_block_number(constants.GENESIS_BLOCK_NUMBER)
Example #10
0
def test_vm_fixtures(fixture_name, fixture):
    db = MemoryDB()
    header = BlockHeader(
        coinbase=fixture['env']['currentCoinbase'],
        difficulty=fixture['env']['currentDifficulty'],
        block_number=fixture['env']['currentNumber'],
        gas_limit=fixture['env']['currentGasLimit'],
        timestamp=fixture['env']['currentTimestamp'],
    )
    meta_evm = EVMForTesting.configure(db=db)(header=header)
    evm = meta_evm.get_evm()
    setup_state_db(fixture['pre'], evm.state_db)

    message = Message(
        origin=fixture['exec']['origin'],
        to=fixture['exec']['address'],
        sender=fixture['exec']['caller'],
        value=fixture['exec']['value'],
        data=fixture['exec']['data'],
        code=evm.state_db.get_code(fixture['exec']['address']),
        gas=fixture['exec']['gas'],
        gas_price=fixture['exec']['gasPrice'],
    )
    computation = evm.apply_computation(message)

    if 'post' in fixture:
        #
        # Success checks
        #
        assert computation.error is None

        expected_logs = [{
            'address': log_entry[0],
            'topics': log_entry[1],
            'data': log_entry[2],
        } for log_entry in computation.get_log_entries()]
        expected_logs == fixture['logs']

        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)

        for child_computation, created_call in zip(
                computation.children, fixture.get('callcreates', [])):
            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
        post_state = fixture['post']
    else:
        #
        # Error checks
        #
        assert computation.error
        assert isinstance(computation.error, VMError)
        post_state = fixture['pre']

    for account, account_data in post_state.items():
        for slot, expected_storage_value in account_data['storage'].items():
            actual_storage_value = evm.state_db.get_storage(account, slot)

            assert actual_storage_value == expected_storage_value

        expected_nonce = account_data['nonce']
        expected_code = account_data['code']
        expected_balance = account_data['balance']

        actual_nonce = evm.state_db.get_nonce(account)
        actual_code = evm.state_db.get_code(account)
        actual_balance = evm.state_db.get_balance(account)

        assert actual_nonce == expected_nonce
        assert actual_code == expected_code
        assert actual_balance == expected_balance