Beispiel #1
0
    def _format_call(self, sender='', to='', value=0, data='',
                     startgas=default_startgas, gasprice=default_gasprice):
        """ Helper to format the transaction data. """

        json_data = dict()

        if sender is not None:
            json_data['from'] = address_encoder(sender)

        if to is not None:
            json_data['to'] = data_encoder(to)

        if value is not None:
            json_data['value'] = quantity_encoder(value)

        if gasprice is not None:
            json_data['gasPrice'] = quantity_encoder(gasprice)

        if startgas is not None:
            json_data['gas'] = quantity_encoder(startgas)

        if data is not None:
            json_data['data'] = data_encoder(data)

        return json_data
Beispiel #2
0
    def eth_sendTransaction(self, nonce=None, sender='', to='', value=0, data='',
                            gasPrice=default_gasprice, gas=default_startgas,
                            v=None, r=None, s=None):
        """ Creates new message call transaction or a contract creation, if the
        data field contains code.

        Note:
            The support for local signing through the variables v,r,s is not
            part of the standard spec, a extended server is required.

        Args:
            from (address): The 20 bytes address the transaction is send from.
            to (address): DATA, 20 Bytes - (optional when creating new
                contract) The address the transaction is directed to.
            gas (int): Gas provided for the transaction execution. It will
                return unused gas.
            gasPrice (int): gasPrice used for each paid gas.
            value (int): Value send with this transaction.
            data (bin): The compiled code of a contract OR the hash of the
                invoked method signature and encoded parameters.
            nonce (int): This allows to overwrite your own pending transactions
                that use the same nonce.
        """

        if to == '' and data.isalnum():
            warnings.warn(
                'Verify that the data parameter is _not_ hex encoded, if this is the case '
                'the data will be double encoded and result in unexpected '
                'behavior.'
            )

        if to == '0' * 40:
            warnings.warn('For contract creating the empty string must be used.')

        json_data = {
            'to': data_encoder(normalize_address(to, allow_blank=True)),
            'value': quantity_encoder(value),
            'gasPrice': quantity_encoder(gasPrice),
            'gas': quantity_encoder(gas),
            'data': data_encoder(data),
        }

        if not sender and not (v and r and s):
            raise ValueError('Either sender or v, r, s needs to be informed.')

        if sender is not None:
            json_data['from'] = address_encoder(sender)

        if v and r and s:
            json_data['v'] = quantity_encoder(v)
            json_data['r'] = quantity_encoder(r)
            json_data['s'] = quantity_encoder(s)

        if nonce is not None:
            json_data['nonce'] = quantity_encoder(nonce)

        res = self.call('eth_sendTransaction', json_data)

        return data_decoder(res)
Beispiel #3
0
def test_new_block_filter(test_app):
    filter_id = test_app.rpc_request('eth_newBlockFilter')
    assert test_app.rpc_request('eth_getFilterChanges', filter_id) == []
    h = test_app.mine_next_block().hash
    assert test_app.rpc_request('eth_getFilterChanges', filter_id) == [data_encoder(h)]
    assert test_app.rpc_request('eth_getFilterChanges', filter_id) == []
    hashes = [data_encoder(test_app.mine_next_block().hash) for i in range(3)]
    assert test_app.rpc_request('eth_getFilterChanges', filter_id) == hashes
    assert test_app.rpc_request('eth_getFilterChanges', filter_id) == []
    assert test_app.rpc_request('eth_getFilterChanges', filter_id) == []
Beispiel #4
0
def test_new_block_filter(test_app):
    filter_id = test_app.rpc_request("eth_newBlockFilter")
    assert test_app.rpc_request("eth_getFilterChanges", filter_id) == []
    h = test_app.mine_next_block().hash
    assert test_app.rpc_request("eth_getFilterChanges", filter_id) == [data_encoder(h)]
    assert test_app.rpc_request("eth_getFilterChanges", filter_id) == []
    hashes = [data_encoder(test_app.mine_next_block().hash) for i in range(3)]
    assert test_app.rpc_request("eth_getFilterChanges", filter_id) == hashes
    assert test_app.rpc_request("eth_getFilterChanges", filter_id) == []
    assert test_app.rpc_request("eth_getFilterChanges", filter_id) == []
Beispiel #5
0
    def eth_call(self,
                 sender='',
                 to='',
                 value=0,
                 data='',
                 startgas=default_startgas,
                 gasprice=default_gasprice,
                 block_number='latest'):
        """ Executes a new message call immediately without creating a
        transaction on the block chain.

        Args:
            from: The address the transaction is send from.
            to: The address the transaction is directed to.
            gas (int): Gas provided for the transaction execution. eth_call
                consumes zero gas, but this parameter may be needed by some
                executions.
            gasPrice (int): gasPrice used for each paid gas.
            value (int): Integer of the value send with this transaction.
            data (bin): Hash of the method signature and encoded parameters.
                For details see Ethereum Contract ABI.
            block_number: Determines the state of ethereum used in the
                call.
        """

        json_data = dict()

        if sender is not None:
            json_data['from'] = address_encoder(sender)

        if to is not None:
            json_data['to'] = data_encoder(to)

        if value is not None:
            json_data['value'] = quantity_encoder(value)

        if gasprice is not None:
            json_data['gasPrice'] = quantity_encoder(gasprice)

        if startgas is not None:
            json_data['gas'] = quantity_encoder(startgas)

        if data is not None:
            json_data['data'] = data_encoder(data)

        res = self.call('eth_call', json_data, block_number)

        return data_decoder(res)
Beispiel #6
0
    def send_transaction(sender,
                         to,
                         value=0,
                         data='',
                         startgas=GAS_LIMIT,
                         gasprice=GAS_PRICE,
                         nonce=None):
        """Custom implementation for `pyethapp.rpc_client.JSONRPCClient.send_transaction`.
        This is necessary to support other remotes that don't support pyethapp's extended specs.
        @see https://github.com/ethereum/pyethapp/blob/develop/pyethapp/rpc_client.py#L359
        """
        pending_transactions_hex = client.call(
            'eth_getTransactionCount',
            address_encoder(sender),
            'pending',
        )
        pending_transactions = int(pending_transactions_hex, 16)
        nonce = pending_transactions + nonce_offset

        tx = Transaction(nonce, gasprice, startgas, to, value, data)
        assert hasattr(client, 'privkey') and client.privkey
        tx.sign(client.privkey)
        result = client.call(
            'eth_sendRawTransaction',
            data_encoder(rlp.encode(tx)),
        )
        return result[2 if result.startswith('0x') else 0:]
Beispiel #7
0
def test_compileSolidity():
    from pyethapp.jsonrpc import Compilers, data_encoder
    import ethereum._solidity

    s = ethereum._solidity.get_solidity()
    if s == None:
        pytest.xfail("solidity not installed, not tested")
    else:
        c = Compilers()
        bc = s.compile(solidity_code)
        abi = s.mk_full_signature(solidity_code)
        A = dict(
            test=dict(
                code=data_encoder(bc),
                info=dict(
                    source=solidity_code,
                    language="Solidity",
                    languageVersion="0",
                    compilerVersion="0",
                    abiDefinition=abi,
                    userDoc=dict(methods=dict()),
                    developerDoc=dict(methods=dict()),
                ),
            )
        )
        B = c.compileSolidity(solidity_code)
        assert A.keys() == B.keys()
        At = A["test"]
        Bt = B["test"]
        assert At["code"] == Bt["code"]
        for k, Av in At["info"].items():
            if k == "compilerVersion":
                continue
            assert Av == Bt["info"][k]
Beispiel #8
0
def test_send_raw_transaction_with_contract(test_app):
    serpent_code = '''
def main(a,b):
    return(a ^ b)
'''
    tx_to = b''
    evm_code = serpent.compile(serpent_code)
    chain = test_app.services.chain.chain
    assert chain.head_candidate.get_balance(tx_to) == 0
    sender = test_app.services.accounts.unlocked_accounts[0].address
    assert chain.head_candidate.get_balance(sender) > 0
    nonce = chain.head_candidate.get_nonce(sender)
    tx = ethereum.transactions.Transaction(nonce, default_gasprice, default_startgas, tx_to, 0, evm_code, 0, 0, 0)
    test_app.services.accounts.sign_tx(sender, tx)
    raw_transaction = data_encoder(rlp.codec.encode(tx, ethereum.transactions.Transaction))
    data_decoder(test_app.client.call('eth_sendRawTransaction', raw_transaction))
    creates = chain.head_candidate.get_transaction(0).creates

    code = chain.head_candidate.account_to_dict(creates)['code']
    assert len(code) > 2
    assert code != '0x'

    test_app.mine_next_block()

    creates = chain.head.get_transaction(0).creates
    code = chain.head.account_to_dict(creates)['code']
    assert len(code) > 2
    assert code != '0x'
def test_compileSolidity():
    from pyethapp.jsonrpc import Compilers, data_encoder
    import ethereum._solidity
    s = ethereum._solidity.get_solidity()
    if s == None:
        pytest.xfail("solidity not installed, not tested")
    else:
        c = Compilers()
        bc = s.compile(solidity_code)
        abi = s.mk_full_signature(solidity_code)
        A = dict(test=dict(code=data_encoder(bc),
                           info=dict(
                               source=solidity_code,
                               language='Solidity',
                               languageVersion='0',
                               compilerVersion='0',
                               abiDefinition=abi,
                               userDoc=dict(methods=dict()),
                               developerDoc=dict(methods=dict()),
                           )))
        B = c.compileSolidity(solidity_code)
        assert A.keys() == B.keys()
        At = A['test']
        Bt = B['test']
        assert At['code'] == Bt['code']
        for k, Av in At['info'].items():
            if k == 'compilerVersion':
                continue
            assert Av == Bt['info'][k]
Beispiel #10
0
def block_tag_encoder(val):
    if isinstance(val, int):
        return quantity_encoder(val)
    elif val and isinstance(val, bytes):
        assert val in ('latest', 'pending')
        return data_encoder(val)
    else:
        assert not val
Beispiel #11
0
def block_tag_encoder(val):
    if isinstance(val, int):
        return quantity_encoder(val)
    elif val and isinstance(val, bytes):
        assert val in ('latest', 'pending')
        return data_encoder(val)
    else:
        assert not val
Beispiel #12
0
    def send_transaction(sender, to, value=0, data='', startgas=GAS_LIMIT,
                         gasprice=GAS_PRICE, nonce=None):
        """Custom implementation for `pyethapp.rpc_client.JSONRPCClient.send_transaction`.
        This is necessary to support other remotes that don't support pyethapp's extended specs.
        @see https://github.com/ethereum/pyethapp/blob/develop/pyethapp/rpc_client.py#L359
        """
        def get_nonce():
            """Eventually syncing nonce counter.
            This will keep a local nonce counter that is only syncing against
            the remote every `UPDATE_INTERVAL`.

            If the remote counter is lower than the current local counter,
            it will wait for the remote to catch up.
            """
            with client.nonce_lock:
                UPDATE_INTERVAL = 5.
                query_time = now()
                needs_update = abs(query_time - client.last_nonce_update) > UPDATE_INTERVAL
                not_initialized = client.current_nonce is None
                if needs_update or not_initialized:
                    nonce = _query_nonce()
                    # we may have hammered the server and not all tx are
                    # registered as `pending` yet
                    while nonce < client.current_nonce:
                        log.debug(
                            "nonce on server too low; retrying",
                            server=nonce,
                            local=client.current_nonce
                        )
                        nonce = _query_nonce()
                        query_time = now()
                    client.current_nonce = nonce
                    client.last_nonce_update = query_time
                else:
                    client.current_nonce += 1
                return client.current_nonce

        def _query_nonce():
            pending_transactions_hex = client.call(
                'eth_getTransactionCount',
                address_encoder(sender),
                'pending',
            )
            pending_transactions = int(pending_transactions_hex, 16)
            nonce = pending_transactions + nonce_offset
            return nonce

        nonce = get_nonce()

        tx = Transaction(nonce, gasprice, startgas, to, value, data)
        assert hasattr(client, 'privkey') and client.privkey
        tx.sign(client.privkey)
        result = client.call(
            'eth_sendRawTransaction',
            data_encoder(rlp.encode(tx)),
        )
        return result[2 if result.startswith('0x') else 0:]
Beispiel #13
0
def check_transaction_threw(client, transaction_hash):
    """Check if the transaction threw or if it executed properly"""
    encoded_transaction = data_encoder(transaction_hash.decode('hex'))
    transaction = client.call('eth_getTransactionByHash', encoded_transaction)
    receipt = client.call('eth_getTransactionReceipt', encoded_transaction)
    if int(transaction['gas'], 0) != int(receipt['gasUsed'], 0):
        return None
    else:
        return receipt
Beispiel #14
0
def test_compile_solidity():
    with open(path.join(path.dirname(__file__), 'contracts',
                        'multiply.sol')) as handler:
        solidity_code = handler.read()

    solidity = ethereum.tools._solidity.get_solidity()  # pylint: disable=protected-access

    abi = solidity.mk_full_signature(solidity_code)
    code = data_encoder(solidity.compile(solidity_code))

    info = {
        'abiDefinition': abi,
        'compilerVersion': '0',
        'developerDoc': {
            'methods': None,
        },
        'language': 'Solidity',
        'languageVersion': '0',
        'source': solidity_code,
        'userDoc': {
            'methods': None,
        },
    }
    test_result = {
        'test': {
            'code': code,
            'info': info,
        }
    }
    compiler_result = Compilers().compileSolidity(solidity_code)

    assert set(compiler_result.keys()) == {
        'test',
    }
    assert set(compiler_result['test'].keys()) == {
        'info',
        'code',
    }
    assert set(compiler_result['test']['info']) == {
        'abiDefinition',
        'compilerVersion',
        'developerDoc',
        'language',
        'languageVersion',
        'source',
        'userDoc',
    }

    assert test_result['test']['code'] == compiler_result['test']['code']

    compiler_info = dict(compiler_result['test']['info'])

    compiler_info.pop('compilerVersion')
    info.pop('compilerVersion')

    assert compiler_info['abiDefinition'] == info['abiDefinition']
Beispiel #15
0
def check_transaction_threw(client, transaction_hash):
    """Check if the transaction threw or if it executed properly"""
    encoded_transaction = data_encoder(transaction_hash.decode('hex'))
    debug = client.call('debug_traceTransaction', encoded_transaction)

    # struct_logs will be empty if it's a call to a contract that previously
    # self destructed:
    # https://github.com/ethereum/go-ethereum/issues/2542
    struct_logs = debug['structLogs']
    if not struct_logs or struct_logs[-1]['op'] not in ('RETURN', 'STOP'):
        return debug
Beispiel #16
0
    def poll(self, transaction_hash, confirmations=None, timeout=None):
        """ Wait until the `transaction_hash` is applied or rejected.
        If timeout is None, this could wait indefinitely!

        Args:
            transaction_hash (hash): Transaction hash that we are waiting for.
            confirmations (int): Number of block confirmations that we will
                wait for.
            timeout (float): Timeout in seconds, raise an Excpetion on
                timeout.
        """
        if transaction_hash.startswith('0x'):
            warnings.warn(
                'transaction_hash seems to be already encoded, this will result '
                'in unexpected behavior')

        if len(transaction_hash) != 32:
            raise ValueError(
                'transaction_hash length must be 32 (it might be hex encode)')

        deadline = None
        if timeout:
            deadline = time.time() + timeout

        transaction_hash = data_encoder(transaction_hash)

        transaction = self.call('eth_getTransactionByHash', transaction_hash)
        while transaction is None or transaction["blockNumber"] is None:
            if deadline and time.time() > deadline:
                raise Exception('timeout when polling for transaction')

            gevent.sleep(.5)
            transaction = self.call('eth_getTransactionByHash',
                                    transaction_hash)

        if confirmations is None:
            return

        # this will wait for both APPLIED and REVERTED transactions
        transaction_block = quantity_decoder(transaction['blockNumber'])
        confirmation_block = transaction_block + confirmations

        block_number = self.blocknumber()
        while confirmation_block > block_number:
            if deadline and time.time() > deadline:
                raise Exception('timeout when waiting for confirmation')

            gevent.sleep(.5)
            block_number = self.blocknumber()
Beispiel #17
0
    def eth_getTransactionByHash(self, transaction_hash):
        """ Returns the information about a transaction requested by
        transaction hash.
        """

        if transaction_hash.startswith('0x'):
            warnings.warn(
                'transaction_hash seems to be already encoded, this will'
                ' result in unexpected behavior'
            )

        if len(transaction_hash) != 32:
            raise ValueError(
                'transaction_hash length must be 32 (it might be hex encode)'
            )

        transaction_hash = data_encoder(transaction_hash)
        return self.call('eth_getTransactionByHash', transaction_hash)
Beispiel #18
0
def test_compileSolidity():
    from pyethapp.jsonrpc import Compilers, data_encoder
    import ethereum._solidity
    s = ethereum._solidity.get_solidity()
    c = Compilers()
    assert 'solidity' in c.getCompilers()
    bc = s.compile(solidity_code)
    abi = s.mk_full_signature(solidity_code)
    r = dict(code=data_encoder(bc),
             info=dict(source=solidity_code,
                       language='Solidity',
                       languageVersion='0',
                       compilerVersion='0',
                       abiDefinition=abi,
                       userDoc=dict(methods=dict()),
                       developerDoc=dict(methods=dict()),
                       )
             )
    assert r == c.compileSolidity(solidity_code)
Beispiel #19
0
def test_compileSolidity():
    from pyethapp.jsonrpc import Compilers, data_encoder
    import ethereum._solidity
    s = ethereum._solidity.get_solidity()
    if s == None:
        pytest.xfail("solidity not installed, not tested")
    else:
        c = Compilers()
        bc = s.compile(solidity_code)
        abi = s.mk_full_signature(solidity_code)
        r = dict(code=data_encoder(bc),
             info=dict(source=solidity_code,
                       language='Solidity',
                       languageVersion='0',
                       compilerVersion='0',
                       abiDefinition=abi,
                       userDoc=dict(methods=dict()),
                       developerDoc=dict(methods=dict()),
                       )
             )
        assert r == c.compileSolidity(solidity_code)
Beispiel #20
0
def test_compileSolidity():
    from pyethapp.jsonrpc import Compilers, data_encoder
    import ethereum._solidity
    s = ethereum._solidity.get_solidity()
    if s == None:
        pytest.xfail("solidity not installed, not tested")
    else:
        c = Compilers()
        bc = s.compile(solidity_code)
        abi = s.mk_full_signature(solidity_code)
        r = dict(code=data_encoder(bc),
                 info=dict(
                     source=solidity_code,
                     language='Solidity',
                     languageVersion='0',
                     compilerVersion='0',
                     abiDefinition=abi,
                     userDoc=dict(methods=dict()),
                     developerDoc=dict(methods=dict()),
                 ))
        assert r == c.compileSolidity(solidity_code)
Beispiel #21
0
    def eth_getTransactionReceipt(self, transaction_hash):
        """ Returns the receipt of a transaction by transaction hash.

        Args:
            transaction_hash: Hash of a transaction.

        Returns:
            A dict representing the transaction receipt object, or null when no
            receipt was found.
        """
        if transaction_hash.startswith('0x'):
            warnings.warn(
                'transaction_hash seems to be already encoded, this will'
                ' result in unexpected behavior'
            )

        if len(transaction_hash) != 32:
            raise ValueError(
                'transaction_hash length must be 32 (it might be hex encode)'
            )

        transaction_hash = data_encoder(transaction_hash)
        return self.call('eth_getTransactionReceipt', transaction_hash)
Beispiel #22
0
def test_get_logs(test_app):
    test_app.mine_next_block()  # start with a fresh block
    n0 = test_app.services.chain.chain.head.number
    sender = address_encoder(test_app.services.accounts.unlocked_accounts()[0].address)
    contract_creation = {
        'from': sender,
        'data': data_encoder(LOG_EVM)
    }
    tx_hash = test_app.rpc_request('eth_sendTransaction', contract_creation)
    test_app.mine_next_block()
    receipt = test_app.rpc_request('eth_getTransactionReceipt', tx_hash)
    contract_address = receipt['contractAddress']
    tx = {
        'from': sender,
        'to': contract_address
    }

    # single log in pending block
    test_app.rpc_request('eth_sendTransaction', tx)
    logs1 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': 'pending',
        'toBlock': 'pending'
    });
    assert len(logs1) == 1
    assert logs1[0]['type'] == 'pending'
    assert logs1[0]['logIndex'] == None
    assert logs1[0]['transactionIndex'] == None
    assert logs1[0]['transactionHash'] == None
    assert logs1[0]['blockHash'] == None
    assert logs1[0]['blockNumber'] == None
    assert logs1[0]['address'] == contract_address

    logs2 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': 'pending',
        'toBlock': 'pending'
    });
    assert logs2 == logs1

    # same log, but now mined in head
    test_app.mine_next_block()
    logs3 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': 'latest',
        'toBlock': 'latest'
    });
    assert len(logs3) == 1
    assert logs3[0]['type'] == 'mined'
    assert logs3[0]['logIndex'] == '0x0'
    assert logs3[0]['transactionIndex'] == '0x0'
    assert logs3[0]['blockHash'] == data_encoder(test_app.services.chain.chain.head.hash)
    assert logs3[0]['blockNumber'] == quantity_encoder(test_app.services.chain.chain.head.number)
    assert logs3[0]['address'] == contract_address

    # another log in pending block
    test_app.rpc_request('eth_sendTransaction', tx)
    logs4 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': 'latest',
        'toBlock': 'pending'
    })
    assert logs4 == [logs1[0], logs3[0]] or logs4 == [logs3[0], logs1[0]]

    # two logs in pending block
    test_app.rpc_request('eth_sendTransaction', tx)
    logs5 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': 'pending',
        'toBlock': 'pending'
    })
    assert len(logs5) == 2
    assert logs5[0] == logs5[1] == logs1[0]

    # two logs in head
    test_app.mine_next_block()
    logs6 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': 'latest',
        'toBlock': 'pending'
    })
    for log in logs6:
        assert log['type'] == 'mined'
        assert log['logIndex'] == '0x0'
        assert log['blockHash'] == data_encoder(test_app.services.chain.chain.head.hash)
        assert log['blockNumber'] == quantity_encoder(test_app.services.chain.chain.head.number)
        assert log['address'] == contract_address
    assert sorted([log['transactionIndex'] for log in logs6]) == ['0x0', '0x1']

    # everything together with another log in pending block
    test_app.rpc_request('eth_sendTransaction', tx)
    logs7 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': quantity_encoder(n0),
        'toBlock': 'pending'
    })
    assert sorted(logs7) == sorted(logs3 + logs6 + logs1)
Beispiel #23
0
def test_get_filter_changes(test_app):
    test_app.mine_next_block()  # start with a fresh block
    n0 = test_app.services.chain.chain.head.number
    sender = address_encoder(test_app.services.accounts.unlocked_accounts()[0].address)
    contract_creation = {"from": sender, "data": data_encoder(LOG_EVM)}
    tx_hash = test_app.rpc_request("eth_sendTransaction", contract_creation)
    test_app.mine_next_block()
    receipt = test_app.rpc_request("eth_getTransactionReceipt", tx_hash)
    contract_address = receipt["contractAddress"]
    tx = {"from": sender, "to": contract_address}

    pending_filter_id = test_app.rpc_request("eth_newFilter", {"fromBlock": "pending", "toBlock": "pending"})
    latest_filter_id = test_app.rpc_request("eth_newFilter", {"fromBlock": "latest", "toBlock": "latest"})
    tx_hashes = []
    logs = []

    # tx in pending block
    tx_hashes.append(test_app.rpc_request("eth_sendTransaction", tx))
    logs.append(test_app.rpc_request("eth_getFilterChanges", pending_filter_id))
    assert len(logs[-1]) == 1
    assert logs[-1][0]["type"] == "pending"
    assert logs[-1][0]["logIndex"] == None
    assert logs[-1][0]["transactionIndex"] == None
    assert logs[-1][0]["transactionHash"] == None
    assert logs[-1][0]["blockHash"] == None
    assert logs[-1][0]["blockNumber"] == None
    assert logs[-1][0]["address"] == contract_address
    pending_log = logs[-1][0]

    logs.append(test_app.rpc_request("eth_getFilterChanges", pending_filter_id))
    assert logs[-1] == []

    logs.append(test_app.rpc_request("eth_getFilterChanges", latest_filter_id))
    assert logs[-1] == []

    test_app.mine_next_block()
    logs.append(test_app.rpc_request("eth_getFilterChanges", latest_filter_id))
    assert len(logs[-1]) == 1  # log from before, but now mined
    assert logs[-1][0]["type"] == "mined"
    assert logs[-1][0]["logIndex"] == "0x0"
    assert logs[-1][0]["transactionIndex"] == "0x0"
    assert logs[-1][0]["transactionHash"] == tx_hashes[-1]
    assert logs[-1][0]["blockHash"] == data_encoder(test_app.services.chain.chain.head.hash)
    assert logs[-1][0]["blockNumber"] == quantity_encoder(test_app.services.chain.chain.head.number)
    assert logs[-1][0]["address"] == contract_address
    logs_in_range = [logs[-1][0]]

    # send tx and mine block
    tx_hashes.append(test_app.rpc_request("eth_sendTransaction", tx))
    test_app.mine_next_block()
    logs.append(test_app.rpc_request("eth_getFilterChanges", pending_filter_id))
    assert len(logs[-1]) == 1
    assert logs[-1][0]["type"] == "mined"
    assert logs[-1][0]["logIndex"] == "0x0"
    assert logs[-1][0]["transactionIndex"] == "0x0"
    assert logs[-1][0]["transactionHash"] == tx_hashes[-1]
    assert logs[-1][0]["blockHash"] == data_encoder(test_app.services.chain.chain.head.hash)
    assert logs[-1][0]["blockNumber"] == quantity_encoder(test_app.services.chain.chain.head.number)
    assert logs[-1][0]["address"] == contract_address
    logs_in_range.append(logs[-1][0])

    logs.append(test_app.rpc_request("eth_getFilterChanges", latest_filter_id))
    assert logs[-1] == logs[-2]  # latest and pending filter see same (mined) log

    logs.append(test_app.rpc_request("eth_getFilterChanges", latest_filter_id))
    assert logs[-1] == []

    test_app.mine_next_block()
    logs.append(test_app.rpc_request("eth_getFilterChanges", pending_filter_id))
    assert logs[-1] == []

    range_filter_id = test_app.rpc_request(
        "eth_newFilter",
        {"fromBlock": quantity_encoder(test_app.services.chain.chain.head.number - 3), "toBlock": "pending"},
    )
    tx_hashes.append(test_app.rpc_request("eth_sendTransaction", tx))
    logs.append(test_app.rpc_request("eth_getFilterChanges", range_filter_id))
    assert sorted(logs[-1]) == sorted(logs_in_range + [pending_log])
Beispiel #24
0
def test_get_logs(test_app):
    test_app.mine_next_block()  # start with a fresh block
    n0 = test_app.services.chain.chain.head.number
    sender = address_encoder(test_app.services.accounts.unlocked_accounts()[0].address)
    contract_creation = {"from": sender, "data": data_encoder(LOG_EVM)}
    tx_hash = test_app.rpc_request("eth_sendTransaction", contract_creation)
    test_app.mine_next_block()
    receipt = test_app.rpc_request("eth_getTransactionReceipt", tx_hash)
    contract_address = receipt["contractAddress"]
    tx = {"from": sender, "to": contract_address}

    # single log in pending block
    test_app.rpc_request("eth_sendTransaction", tx)
    logs1 = test_app.rpc_request("eth_getLogs", {"fromBlock": "pending", "toBlock": "pending"})
    assert len(logs1) == 1
    assert logs1[0]["type"] == "pending"
    assert logs1[0]["logIndex"] == None
    assert logs1[0]["transactionIndex"] == None
    assert logs1[0]["transactionHash"] == None
    assert logs1[0]["blockHash"] == None
    assert logs1[0]["blockNumber"] == None
    assert logs1[0]["address"] == contract_address

    logs2 = test_app.rpc_request("eth_getLogs", {"fromBlock": "pending", "toBlock": "pending"})
    assert logs2 == logs1

    # same log, but now mined in head
    test_app.mine_next_block()
    logs3 = test_app.rpc_request("eth_getLogs", {"fromBlock": "latest", "toBlock": "latest"})
    assert len(logs3) == 1
    assert logs3[0]["type"] == "mined"
    assert logs3[0]["logIndex"] == "0x0"
    assert logs3[0]["transactionIndex"] == "0x0"
    assert logs3[0]["blockHash"] == data_encoder(test_app.services.chain.chain.head.hash)
    assert logs3[0]["blockNumber"] == quantity_encoder(test_app.services.chain.chain.head.number)
    assert logs3[0]["address"] == contract_address

    # another log in pending block
    test_app.rpc_request("eth_sendTransaction", tx)
    logs4 = test_app.rpc_request("eth_getLogs", {"fromBlock": "latest", "toBlock": "pending"})
    assert logs4 == [logs1[0], logs3[0]] or logs4 == [logs3[0], logs1[0]]

    # two logs in pending block
    test_app.rpc_request("eth_sendTransaction", tx)
    logs5 = test_app.rpc_request("eth_getLogs", {"fromBlock": "pending", "toBlock": "pending"})
    assert len(logs5) == 2
    assert logs5[0] == logs5[1] == logs1[0]

    # two logs in head
    test_app.mine_next_block()
    logs6 = test_app.rpc_request("eth_getLogs", {"fromBlock": "latest", "toBlock": "pending"})
    for log in logs6:
        assert log["type"] == "mined"
        assert log["logIndex"] == "0x0"
        assert log["blockHash"] == data_encoder(test_app.services.chain.chain.head.hash)
        assert log["blockNumber"] == quantity_encoder(test_app.services.chain.chain.head.number)
        assert log["address"] == contract_address
    assert sorted([log["transactionIndex"] for log in logs6]) == ["0x0", "0x1"]

    # everything together with another log in pending block
    test_app.rpc_request("eth_sendTransaction", tx)
    logs7 = test_app.rpc_request("eth_getLogs", {"fromBlock": quantity_encoder(n0), "toBlock": "pending"})
    assert sorted(logs7) == sorted(logs3 + logs6 + logs1)
Beispiel #25
0
    def poll(self, transaction_hash, confirmations=None, timeout=None):
        """ Wait until the `transaction_hash` is applied or rejected.
        If timeout is None, this could wait indefinitely!

        Args:
            transaction_hash (hash): Transaction hash that we are waiting for.
            confirmations (int): Number of block confirmations that we will
                wait for.
            timeout (float): Timeout in seconds, raise an Excpetion on
                timeout.
        """
        if transaction_hash.startswith('0x'):
            warnings.warn(
                'transaction_hash seems to be already encoded, this will'
                ' result in unexpected behavior'
            )

        if len(transaction_hash) != 32:
            raise ValueError(
                'transaction_hash length must be 32 (it might be hex encode)'
            )

        transaction_hash = data_encoder(transaction_hash)

        deadline = None
        if timeout:
            deadline = gevent.Timeout(timeout)
            deadline.start()

        try:
            # used to check if the transaction was removed, this could happen
            # if gas price is to low:
            #
            # > Transaction (acbca3d6) below gas price (tx=1 Wei ask=18
            # > Shannon). All sequential txs from this address(7d0eae79)
            # > will be ignored
            #
            last_result = None

            while True:
                # Could return None for a short period of time, until the
                # transaction is added to the pool
                transaction = self.call('eth_getTransactionByHash', transaction_hash)

                # if the transaction was added to the pool and then removed
                if transaction is None and last_result is not None:
                    raise Exception('invalid transaction, check gas price')

                # the transaction was added to the pool and mined
                if transaction and transaction['blockNumber'] is not None:
                    break

                last_result = transaction

                gevent.sleep(.5)

            if confirmations:
                # this will wait for both APPLIED and REVERTED transactions
                transaction_block = quantity_decoder(transaction['blockNumber'])
                confirmation_block = transaction_block + confirmations

                block_number = self.blocknumber()

                while block_number < confirmation_block:
                    gevent.sleep(.5)
                    block_number = self.blocknumber()

        except gevent.Timeout:
            raise Exception('timeout when polling for transaction')

        finally:
            if deadline:
                deadline.cancel()
Beispiel #26
0
def topic_encoder(t):
    assert isinstance(t, (int, long))
    return data_encoder(int_to_big_endian(t))
Beispiel #27
0
def topic_encoder(topic):
    assert isinstance(topic, int)
    return data_encoder(int_to_big_endian(topic))
def test_get_filter_changes(test_app):
    test_app.mine_next_block()  # start with a fresh block
    n0 = test_app.services.chain.chain.head.number
    sender = address_encoder(
        test_app.services.accounts.unlocked_accounts()[0].address)
    contract_creation = {'from': sender, 'data': data_encoder(LOG_EVM)}
    tx_hash = test_app.rpc_request('eth_sendTransaction', contract_creation)
    test_app.mine_next_block()
    receipt = test_app.rpc_request('eth_getTransactionReceipt', tx_hash)
    contract_address = receipt['contractAddress']
    tx = {'from': sender, 'to': contract_address}

    pending_filter_id = test_app.rpc_request('eth_newFilter', {
        'fromBlock': 'pending',
        'toBlock': 'pending'
    })
    latest_filter_id = test_app.rpc_request('eth_newFilter', {
        'fromBlock': 'latest',
        'toBlock': 'latest'
    })
    tx_hashes = []
    logs = []

    # tx in pending block
    tx_hashes.append(test_app.rpc_request('eth_sendTransaction', tx))
    logs.append(test_app.rpc_request('eth_getFilterChanges',
                                     pending_filter_id))
    assert len(logs[-1]) == 1
    assert logs[-1][0]['type'] == 'pending'
    assert logs[-1][0]['logIndex'] == None
    assert logs[-1][0]['transactionIndex'] == None
    assert logs[-1][0]['transactionHash'] == None
    assert logs[-1][0]['blockHash'] == None
    assert logs[-1][0]['blockNumber'] == None
    assert logs[-1][0]['address'] == contract_address
    pending_log = logs[-1][0]

    logs.append(test_app.rpc_request('eth_getFilterChanges',
                                     pending_filter_id))
    assert logs[-1] == []

    logs.append(test_app.rpc_request('eth_getFilterChanges', latest_filter_id))
    assert logs[-1] == []

    test_app.mine_next_block()
    logs.append(test_app.rpc_request('eth_getFilterChanges', latest_filter_id))
    assert len(logs[-1]) == 1  # log from before, but now mined
    assert logs[-1][0]['type'] == 'mined'
    assert logs[-1][0]['logIndex'] == '0x0'
    assert logs[-1][0]['transactionIndex'] == '0x0'
    assert logs[-1][0]['transactionHash'] == tx_hashes[-1]
    assert logs[-1][0]['blockHash'] == data_encoder(
        test_app.services.chain.chain.head.hash)
    assert logs[-1][0]['blockNumber'] == quantity_encoder(
        test_app.services.chain.chain.head.number)
    assert logs[-1][0]['address'] == contract_address
    logs_in_range = [logs[-1][0]]

    # send tx and mine block
    tx_hashes.append(test_app.rpc_request('eth_sendTransaction', tx))
    test_app.mine_next_block()
    logs.append(test_app.rpc_request('eth_getFilterChanges',
                                     pending_filter_id))
    assert len(logs[-1]) == 1
    assert logs[-1][0]['type'] == 'mined'
    assert logs[-1][0]['logIndex'] == '0x0'
    assert logs[-1][0]['transactionIndex'] == '0x0'
    assert logs[-1][0]['transactionHash'] == tx_hashes[-1]
    assert logs[-1][0]['blockHash'] == data_encoder(
        test_app.services.chain.chain.head.hash)
    assert logs[-1][0]['blockNumber'] == quantity_encoder(
        test_app.services.chain.chain.head.number)
    assert logs[-1][0]['address'] == contract_address
    logs_in_range.append(logs[-1][0])

    logs.append(test_app.rpc_request('eth_getFilterChanges', latest_filter_id))
    assert logs[-1] == logs[
        -2]  # latest and pending filter see same (mined) log

    logs.append(test_app.rpc_request('eth_getFilterChanges', latest_filter_id))
    assert logs[-1] == []

    test_app.mine_next_block()
    logs.append(test_app.rpc_request('eth_getFilterChanges',
                                     pending_filter_id))
    assert logs[-1] == []

    range_filter_id = test_app.rpc_request(
        'eth_newFilter', {
            'fromBlock':
            quantity_encoder(test_app.services.chain.chain.head.number - 3),
            'toBlock':
            'pending'
        })
    tx_hashes.append(test_app.rpc_request('eth_sendTransaction', tx))
    logs.append(test_app.rpc_request('eth_getFilterChanges', range_filter_id))
    assert sorted(logs[-1]) == sorted(logs_in_range + [pending_log])
Beispiel #29
0
def topic_encoder(t):
    assert isinstance(t, (int, long))
    return data_encoder(int_to_big_endian(t))
Beispiel #30
0
def test_get_filter_changes(test_app):
    test_app.mine_next_block()  # start with a fresh block
    n0 = test_app.services.chain.chain.head.number
    sender = address_encoder(test_app.services.accounts.unlocked_accounts()[0].address)
    contract_creation = {
        'from': sender,
        'data': data_encoder(LOG_EVM)
    }
    tx_hash = test_app.rpc_request('eth_sendTransaction', contract_creation)
    test_app.mine_next_block()
    receipt = test_app.rpc_request('eth_getTransactionReceipt', tx_hash)
    contract_address = receipt['contractAddress']
    tx = {
        'from': sender,
        'to': contract_address
    }

    pending_filter_id = test_app.rpc_request('eth_newFilter', {
        'fromBlock': 'pending',
        'toBlock': 'pending'
    });
    latest_filter_id = test_app.rpc_request('eth_newFilter', {
        'fromBlock': 'latest',
        'toBlock': 'latest'
    });
    tx_hashes = []
    logs = []

    # tx in pending block
    tx_hashes.append(test_app.rpc_request('eth_sendTransaction', tx))
    logs.append(test_app.rpc_request('eth_getFilterChanges', pending_filter_id))
    assert len(logs[-1]) == 1
    assert logs[-1][0]['type'] == 'pending'
    assert logs[-1][0]['logIndex'] == None
    assert logs[-1][0]['transactionIndex'] == None
    assert logs[-1][0]['transactionHash'] == None
    assert logs[-1][0]['blockHash'] == None
    assert logs[-1][0]['blockNumber'] == None
    assert logs[-1][0]['address'] == contract_address
    pending_log = logs[-1][0]

    logs.append(test_app.rpc_request('eth_getFilterChanges', pending_filter_id))
    assert logs[-1] == []

    logs.append(test_app.rpc_request('eth_getFilterChanges', latest_filter_id))
    assert logs[-1] == []

    test_app.mine_next_block()
    logs.append(test_app.rpc_request('eth_getFilterChanges', latest_filter_id))
    assert len(logs[-1]) == 1  # log from before, but now mined
    assert logs[-1][0]['type'] == 'mined'
    assert logs[-1][0]['logIndex'] == '0x0'
    assert logs[-1][0]['transactionIndex'] == '0x0'
    assert logs[-1][0]['transactionHash'] == tx_hashes[-1]
    assert logs[-1][0]['blockHash'] == data_encoder(test_app.services.chain.chain.head.hash)
    assert logs[-1][0]['blockNumber'] == quantity_encoder(test_app.services.chain.chain.head.number)
    assert logs[-1][0]['address'] == contract_address
    logs_in_range = [logs[-1][0]]

    # send tx and mine block
    tx_hashes.append(test_app.rpc_request('eth_sendTransaction', tx))
    test_app.mine_next_block()
    logs.append(test_app.rpc_request('eth_getFilterChanges', pending_filter_id))
    assert len(logs[-1]) == 1
    assert logs[-1][0]['type'] == 'mined'
    assert logs[-1][0]['logIndex'] == '0x0'
    assert logs[-1][0]['transactionIndex'] == '0x0'
    assert logs[-1][0]['transactionHash'] == tx_hashes[-1]
    assert logs[-1][0]['blockHash'] == data_encoder(test_app.services.chain.chain.head.hash)
    assert logs[-1][0]['blockNumber'] == quantity_encoder(test_app.services.chain.chain.head.number)
    assert logs[-1][0]['address'] == contract_address
    logs_in_range.append(logs[-1][0])

    logs.append(test_app.rpc_request('eth_getFilterChanges', latest_filter_id))
    assert logs[-1] == logs[-2]  # latest and pending filter see same (mined) log

    logs.append(test_app.rpc_request('eth_getFilterChanges', latest_filter_id))
    assert logs[-1] == []

    test_app.mine_next_block()
    logs.append(test_app.rpc_request('eth_getFilterChanges', pending_filter_id))
    assert logs[-1] == []

    range_filter_id = test_app.rpc_request('eth_newFilter', {
        'fromBlock': quantity_encoder(test_app.services.chain.chain.head.number - 3),
        'toBlock': 'pending'
    })
    tx_hashes.append(test_app.rpc_request('eth_sendTransaction', tx))
    logs.append(test_app.rpc_request('eth_getFilterChanges', range_filter_id))
    assert sorted(logs[-1]) == sorted(logs_in_range + [pending_log])
Beispiel #31
0
 def _serialize(self, value, attr, obj):
     return data_encoder(value)
def test_get_logs(test_app):
    test_app.mine_next_block()  # start with a fresh block
    n0 = test_app.services.chain.chain.head.number
    sender = address_encoder(
        test_app.services.accounts.unlocked_accounts()[0].address)
    contract_creation = {'from': sender, 'data': data_encoder(LOG_EVM)}
    tx_hash = test_app.rpc_request('eth_sendTransaction', contract_creation)
    test_app.mine_next_block()
    receipt = test_app.rpc_request('eth_getTransactionReceipt', tx_hash)
    contract_address = receipt['contractAddress']
    tx = {'from': sender, 'to': contract_address}

    # single log in pending block
    test_app.rpc_request('eth_sendTransaction', tx)
    logs1 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': 'pending',
        'toBlock': 'pending'
    })
    assert len(logs1) == 1
    assert logs1[0]['type'] == 'pending'
    assert logs1[0]['logIndex'] == None
    assert logs1[0]['transactionIndex'] == None
    assert logs1[0]['transactionHash'] == None
    assert logs1[0]['blockHash'] == None
    assert logs1[0]['blockNumber'] == None
    assert logs1[0]['address'] == contract_address

    logs2 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': 'pending',
        'toBlock': 'pending'
    })
    assert logs2 == logs1

    # same log, but now mined in head
    test_app.mine_next_block()
    logs3 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': 'latest',
        'toBlock': 'latest'
    })
    assert len(logs3) == 1
    assert logs3[0]['type'] == 'mined'
    assert logs3[0]['logIndex'] == '0x0'
    assert logs3[0]['transactionIndex'] == '0x0'
    assert logs3[0]['blockHash'] == data_encoder(
        test_app.services.chain.chain.head.hash)
    assert logs3[0]['blockNumber'] == quantity_encoder(
        test_app.services.chain.chain.head.number)
    assert logs3[0]['address'] == contract_address

    # another log in pending block
    test_app.rpc_request('eth_sendTransaction', tx)
    logs4 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': 'latest',
        'toBlock': 'pending'
    })
    assert logs4 == [logs1[0], logs3[0]] or logs4 == [logs3[0], logs1[0]]

    # two logs in pending block
    test_app.rpc_request('eth_sendTransaction', tx)
    logs5 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': 'pending',
        'toBlock': 'pending'
    })
    assert len(logs5) == 2
    assert logs5[0] == logs5[1] == logs1[0]

    # two logs in head
    test_app.mine_next_block()
    logs6 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': 'latest',
        'toBlock': 'pending'
    })
    for log in logs6:
        assert log['type'] == 'mined'
        assert log['logIndex'] == '0x0'
        assert log['blockHash'] == data_encoder(
            test_app.services.chain.chain.head.hash)
        assert log['blockNumber'] == quantity_encoder(
            test_app.services.chain.chain.head.number)
        assert log['address'] == contract_address
    assert sorted([log['transactionIndex'] for log in logs6]) == ['0x0', '0x1']

    # everything together with another log in pending block
    test_app.rpc_request('eth_sendTransaction', tx)
    logs7 = test_app.rpc_request('eth_getLogs', {
        'fromBlock': quantity_encoder(n0),
        'toBlock': 'pending'
    })
    assert sorted(logs7) == sorted(logs3 + logs6 + logs1)