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
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)
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
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)
def find_block(self, condition): """Query all blocks one by one and return the first one for which `condition(block)` evaluates to `True`. """ i = 0 while True: block = self.call('eth_getBlockByNumber', quantity_encoder(i), True) if condition(block) or not block: return block i += 1
def find_block(self, condition): """Query all blocks one by one and return the first one for which `condition(block)` evaluates to `True`. """ i = 0 while True: block = self.call("eth_getBlockByNumber", quantity_encoder(i), True, print_comm=False) if condition(block): return block i += 1
def filter_changes(self, fid): changes = self.call('eth_getFilterChanges', quantity_encoder(fid)) if not changes: return None elif isinstance(changes, bytes): return data_decoder(changes) else: decoders = dict(blockHash=data_decoder, transactionHash=data_decoder, data=data_decoder, address=address_decoder, topics=lambda x: [topic_decoder(t) for t in x], blockNumber=quantity_decoder, logIndex=quantity_decoder, transactionIndex=quantity_decoder) return [{k: decoders[k](v) for k, v in c.items() if v is not None} for c in changes]
def filter_changes(self, fid): changes = self.call('eth_getFilterChanges', quantity_encoder(fid)) if not changes: return None elif isinstance(changes, bytes): return data_decoder(changes) else: decoders = dict(blockHash=data_decoder, transactionHash=data_decoder, data=data_decoder, address=address_decoder, topics=lambda x: [topic_decoder(t) for t in x], blockNumber=quantity_decoder, logIndex=quantity_decoder, transactionIndex=quantity_decoder) return [{k: decoders[k](v) for k, v in list(c.items()) if v is not None} for c in changes]
def test_send_transaction(test_app): chain = test_app.services.chain.chain assert chain.head_candidate.get_balance('\xff' * 20) == 0 tx = { 'from': address_encoder(test_app.services.accounts.unlocked_accounts()[0].address), 'to': address_encoder('\xff' * 20), 'value': quantity_encoder(1) } tx_hash = data_decoder(test_app.rpc_request('eth_sendTransaction', tx)) assert tx_hash == chain.head_candidate.get_transaction(0).hash assert chain.head_candidate.get_balance('\xff' * 20) == 1 test_app.mine_next_block() assert tx_hash == chain.head.get_transaction(0).hash assert chain.head.get_balance('\xff' * 20) == 1 # send transactions from account which can't pay gas tx['from'] = address_encoder(test_app.services.accounts.unlocked_accounts()[1].address) tx_hash = data_decoder(test_app.rpc_request('eth_sendTransaction', tx)) assert chain.head_candidate.get_transactions() == []
def test_send_transaction(test_app): chainservice = test_app.services.chain chain = chainservice.chain hc = chainservice.head_candidate state = State(hc.state_root, chain.env) assert state.get_balance(b'\xff' * 20) == 0 sender = test_app.services.accounts.unlocked_accounts[0].address assert state.get_balance(sender) > 0 tx = { 'from': address_encoder(sender), 'to': address_encoder(b'\xff' * 20), 'value': quantity_encoder(1) } tx_hash = data_decoder(test_app.client.call('eth_sendTransaction', tx)) test_app.mine_next_block() assert len(chain.head.transactions) == 1 assert tx_hash == chain.head.transactions[0].hash assert chain.state.get_balance(b'\xff' * 20) == 1 # send transactions from account which can't pay gas tx['from'] = address_encoder( test_app.services.accounts.unlocked_accounts[1].address) tx_hash = data_decoder(test_app.client.call('eth_sendTransaction', tx)) assert chainservice.head_candidate.transactions == []
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])
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)
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])
def block_gas_limit(self, blocknumber): block = self.client.call('eth_getBlockByNumber', quantity_encoder(blocknumber), False) return int(block['gasLimit'], 0)
def test_send_transaction(test_app): chain = test_app.services.chain.chain assert chain.head_candidate.get_balance("\xff" * 20) == 0 sender = test_app.services.accounts.unlocked_accounts()[0].address assert chain.head_candidate.get_balance(sender) > 0 tx = {"from": address_encoder(sender), "to": address_encoder("\xff" * 20), "value": quantity_encoder(1)} tx_hash = data_decoder(test_app.rpc_request("eth_sendTransaction", tx)) assert tx_hash == chain.head_candidate.get_transaction(0).hash assert chain.head_candidate.get_balance("\xff" * 20) == 1 test_app.mine_next_block() assert tx_hash == chain.head.get_transaction(0).hash assert chain.head.get_balance("\xff" * 20) == 1 # send transactions from account which can't pay gas tx["from"] = address_encoder(test_app.services.accounts.unlocked_accounts()[1].address) tx_hash = data_decoder(test_app.rpc_request("eth_sendTransaction", tx)) assert chain.head_candidate.get_transactions() == []
def test_logfilters_topics(test_app): sample_compiled = _solidity.compile_code( sample_sol_code, combined='bin,abi', ) filepath = None contract_data = _solidity.solidity_get_contract_data( sample_compiled, filepath, 'SampleContract') theabi = contract_data['abi'] theevm = contract_data['bin_hex'] sender_address = test_app.services.accounts.unlocked_accounts[0].address sender = address_encoder(sender_address) event1 = get_event(theabi, 'Event1') event2 = get_event(theabi, 'Event2') event3 = get_event(theabi, 'Event3') event1_id = event_id(*get_eventname_types(event1)) event2_id = event_id(*get_eventname_types(event2)) event3_id = event_id(*get_eventname_types(event3)) test_app.mine_next_block() # start with a fresh block n0 = test_app.services.chain.chain.head.number assert n0 == 1 contract_creation = { 'from': sender, 'data': '0x' + theevm, 'gas': quantity_encoder(1000000) } tx_hash = test_app.client.call('eth_sendTransaction', contract_creation) test_app.mine_next_block() receipt = test_app.client.call('eth_getTransactionReceipt', tx_hash) contract_address = receipt['contractAddress'] sample_contract = ContractProxy(sender_address, theabi, contract_address, test_app.client.call, test_app.client.send_transaction) topic1 = hex(event1_id).rstrip("L") topic2 = hex(event2_id).rstrip("L") topic3 = hex(event3_id).rstrip("L") topica, topicb, topicc = \ '0x0000000000000000000000000000000000000000000000000000000000000001',\ '0x0000000000000000000000000000000000000000000000000000000000000064',\ '0x00000000000000000000000000000000000000000000000000000000000003e8' topic_filter_1 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topic1] }) topic_filter_2 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topic2] }) topic_filter_3 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topic3] }) topic_filter_4 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topic1, topica] }) topic_filter_5 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topic2, topica, topicb] }) topic_filter_6 = test_app.client.call( 'eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topic3, topica, topicb, topicc] }) topic_filter_7 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topica, topicb, topicc] }) topic_filter_8 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topic3, topica, topicb] }) topic_filter_9 = test_app.client.call( 'eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topicc, topicb, topica, topic3] }) topic_filter_10 = test_app.client.call( 'eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topicb, topicc, topica, topic3] }) topic_filter_11 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topic2, topica] }) topic_filter_12 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topic3, topica] }) topic_filter_13 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topica, topicb] }) topic_filter_14 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topic2, [topica, topicb]] }) topic_filter_15 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [[topic1, topic2], topica] }) topic_filter_16 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [[topic1, topic2, topic3]] }) topic_filter_17 = test_app.client.call( 'eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [[topic1, topic2, topic3, topica, topicb, topicc]] }) topic_filter_18 = test_app.client.call( 'eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topic2, topica, topicb, [topic2, topica, topicb]] }) topic_filter_19 = test_app.client.call('eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [topic1, topica, topicb] }) topic_filter_20 = test_app.client.call( 'eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [[topic1, topic2], [topica, topicb], [topica, topicb]] }) topic_filter_21 = test_app.client.call( 'eth_newFilter', { 'fromBlock': 0, 'toBlock': 'pending', 'topics': [[topic2, topic3], [topica, topicb], [topica, topicb]] }) thecode = test_app.client.call('eth_getCode', address_encoder(sample_contract.address)) assert len(thecode) > 2 sample_contract.trigger1(1) test_app.mine_next_block() sample_contract.trigger2(100) test_app.mine_next_block() sample_contract.trigger3(1000) test_app.mine_next_block() tl1 = test_app.client.call('eth_getFilterChanges', topic_filter_1) assert len(tl1) == 1 tl2 = test_app.client.call('eth_getFilterChanges', topic_filter_2) assert len(tl2) == 1 tl3 = test_app.client.call('eth_getFilterChanges', topic_filter_3) assert len(tl3) == 1 tl4 = test_app.client.call('eth_getFilterChanges', topic_filter_4) assert len(tl4) == 1 tl5 = test_app.client.call('eth_getFilterChanges', topic_filter_5) assert len(tl5) == 1 tl6 = test_app.client.call('eth_getFilterChanges', topic_filter_6) assert len(tl6) == 1 tl7 = test_app.client.call('eth_getFilterChanges', topic_filter_7) assert len(tl7) == 0 tl8 = test_app.client.call('eth_getFilterChanges', topic_filter_8) assert len(tl8) == 1 tl9 = test_app.client.call('eth_getFilterChanges', topic_filter_9) assert len(tl9) == 0 tl10 = test_app.client.call('eth_getFilterChanges', topic_filter_10) assert len(tl10) == 0 tl11 = test_app.client.call('eth_getFilterChanges', topic_filter_11) assert len(tl11) == 1 tl12 = test_app.client.call('eth_getFilterChanges', topic_filter_12) assert len(tl12) == 1 tl13 = test_app.client.call('eth_getFilterChanges', topic_filter_13) assert len(tl13) == 0 tl14 = test_app.client.call('eth_getFilterChanges', topic_filter_14) assert len(tl14) == 1 tl15 = test_app.client.call('eth_getFilterChanges', topic_filter_15) assert len(tl15) == 2 tl16 = test_app.client.call('eth_getFilterChanges', topic_filter_16) assert len(tl16) == 3 tl17 = test_app.client.call('eth_getFilterChanges', topic_filter_17) assert len(tl17) == 3 tl18 = test_app.client.call('eth_getFilterChanges', topic_filter_18) assert len(tl18) == 0 tl19 = test_app.client.call('eth_getFilterChanges', topic_filter_19) assert len(tl19) == 0 tl20 = test_app.client.call('eth_getFilterChanges', topic_filter_20) assert len(tl20) == 1 tl21 = test_app.client.call('eth_getFilterChanges', topic_filter_21) assert len(tl21) == 2
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])
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)
def get_block(self, num): return self.client.call( 'eth_getBlockByNumber', quantity_encoder(num), True )
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)