tests(rpc): add filter tests (#1233)

* tests(rpc): add pending transaction filter test

* tests(rpc): add block filter and event log  test

* tests(rpc): simplify to cluster instead of comparing types

* tests(rpc): wip filter by address

* tests(rpc): add get_logs test

* fix flake8 linter

* fix flake8 linter

* add caching to readme

* add caching to readme

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
Daniel Burckhardt 2022-08-12 15:57:57 +02:00 committed by GitHub
parent 94cab52ca1
commit 9bbf356c6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 206 additions and 4 deletions

View File

@ -25,13 +25,13 @@ import (
// FilterAPI gathers // FilterAPI gathers
type FilterAPI interface { type FilterAPI interface {
GetLogs(ctx context.Context, crit filters.FilterCriteria) ([]*ethtypes.Log, error) NewPendingTransactionFilter() rpc.ID
GetFilterChanges(id rpc.ID) (interface{}, error)
GetFilterLogs(ctx context.Context, id rpc.ID) ([]*ethtypes.Log, error)
NewBlockFilter() rpc.ID NewBlockFilter() rpc.ID
NewFilter(criteria filters.FilterCriteria) (rpc.ID, error) NewFilter(criteria filters.FilterCriteria) (rpc.ID, error)
NewPendingTransactionFilter() rpc.ID GetFilterChanges(id rpc.ID) (interface{}, error)
GetFilterLogs(ctx context.Context, id rpc.ID) ([]*ethtypes.Log, error)
UninstallFilter(id rpc.ID) bool UninstallFilter(id rpc.ID) bool
GetLogs(ctx context.Context, crit filters.FilterCriteria) ([]*ethtypes.Log, error)
} }
// Backend defines the methods requided by the PublicFilterAPI backend // Backend defines the methods requided by the PublicFilterAPI backend

View File

@ -0,0 +1,55 @@
# RPC Integration tests
The RPC integration test suite uses nix for reproducible and configurable
builds allowing to run integration tests using python web3 library against
different Ethermint and [Geth](https://github.com/ethereum/go-ethereum) clients with multiple configurations.
## Installation
Nix Multi-user installation:
```
sh <(curl -L https://nixos.org/nix/install) --daemon
```
Make sure the following line has been added to your shell profile (e.g. ~/.profile):
```
source ~/.nix-profile/etc/profile.d/nix.sh
```
Then re-login shell, the nix installation is completed.
For linux:
```
sh <(curl -L https://nixos.org/nix/install) --no-daemon
```
## Run Local
First time run (can take a while):
```
make run-integration-tests
```
Once you've run them once and, you can run:
```
nix-shell tests/integration_tests/shell.nix
cd tests/integration_tests
pytest -s -vv
```
If you're changing anything on the ethermint rpc, rerun the first command.
## Caching
You can enable Binary Cache to speed up the tests:
```
$ nix-env -iA cachix -f https://cachix.org/api/v1/install
$ cachix use ethermint
```

View File

@ -0,0 +1,20 @@
pragma solidity >0.5.0;
contract Greeter {
string public greeting;
event ChangeGreeting(address from, string value);
constructor() public {
greeting = "Hello";
}
function setGreeting(string memory _greeting) public {
greeting = _greeting;
emit ChangeGreeting(msg.sender, _greeting);
}
function greet() public view returns (string memory) {
return greeting;
}
}

View File

@ -0,0 +1,118 @@
import pytest
from web3 import Web3
from .utils import (
ADDRS,
CONTRACTS,
deploy_contract,
send_successful_transaction,
send_transaction,
)
def test_pending_transaction_filter(cluster):
w3: Web3 = cluster.w3
flt = w3.eth.filter("pending")
# without tx
assert flt.get_new_entries() == [] # GetFilterChanges
# with tx
txhash = send_successful_transaction(w3)
assert txhash in flt.get_new_entries()
# without new txs since last call
assert flt.get_new_entries() == []
def test_block_filter(cluster):
w3: Web3 = cluster.w3
flt = w3.eth.filter("latest")
# without tx
assert flt.get_new_entries() == []
# with tx
send_successful_transaction(w3)
blocks = flt.get_new_entries()
assert len(blocks) >= 1
# without new txs since last call
assert flt.get_new_entries() == []
def test_event_log_filter_by_contract(cluster):
w3: Web3 = cluster.w3
contract = deploy_contract(w3, CONTRACTS["Greeter"])
assert contract.caller.greet() == "Hello"
# Create new filter from contract
current_height = hex(w3.eth.get_block_number())
flt = contract.events.ChangeGreeting.createFilter(fromBlock=current_height)
# without tx
assert flt.get_new_entries() == [] # GetFilterChanges
assert flt.get_all_entries() == [] # GetFilterLogs
# with tx
tx = contract.functions.setGreeting("world").buildTransaction()
tx_receipt = send_transaction(w3, tx)
assert tx_receipt.status == 1
log = contract.events.ChangeGreeting().processReceipt(tx_receipt)[0]
assert log["event"] == "ChangeGreeting"
new_entries = flt.get_new_entries()
assert len(new_entries) == 1
assert new_entries[0] == log
assert contract.caller.greet() == "world"
# without new txs since last call
assert flt.get_new_entries() == []
assert flt.get_all_entries() == new_entries
# Uninstall
assert w3.eth.uninstall_filter(flt.filter_id)
assert not w3.eth.uninstall_filter(flt.filter_id)
with pytest.raises(Exception):
flt.get_all_entries()
def test_event_log_filter_by_address(cluster):
w3: Web3 = cluster.w3
contract = deploy_contract(w3, CONTRACTS["Greeter"])
assert contract.caller.greet() == "Hello"
flt = w3.eth.filter({"address": contract.address})
flt2 = w3.eth.filter({"address": ADDRS["validator"]})
# without tx
assert flt.get_new_entries() == [] # GetFilterChanges
assert flt.get_all_entries() == [] # GetFilterLogs
# with tx
tx = contract.functions.setGreeting("world").buildTransaction()
receipt = send_transaction(w3, tx)
assert receipt.status == 1
assert len(flt.get_new_entries()) == 1
assert len(flt2.get_new_entries()) == 0
def test_get_logs(cluster):
w3: Web3 = cluster.w3
contract = deploy_contract(w3, CONTRACTS["Greeter"])
# without tx
assert w3.eth.get_logs({"address": contract.address}) == []
assert w3.eth.get_logs({"address": ADDRS["validator"]}) == []
# with tx
tx = contract.functions.setGreeting("world").buildTransaction()
receipt = send_transaction(w3, tx)
assert receipt.status == 1
assert len(w3.eth.get_logs({"address": contract.address})) == 1
assert len(w3.eth.get_logs({"address": ADDRS["validator"]})) == 0

View File

@ -24,6 +24,7 @@ ADDRS = {name: account.address for name, account in ACCOUNTS.items()}
ETHERMINT_ADDRESS_PREFIX = "ethm" ETHERMINT_ADDRESS_PREFIX = "ethm"
TEST_CONTRACTS = { TEST_CONTRACTS = {
"TestERC20A": "TestERC20A.sol", "TestERC20A": "TestERC20A.sol",
"Greeter": "Greeter.sol",
} }
@ -140,6 +141,14 @@ def send_transaction(w3, tx, key=KEYS["validator"]):
return w3.eth.wait_for_transaction_receipt(txhash) return w3.eth.wait_for_transaction_receipt(txhash)
def send_successful_transaction(w3):
signed = sign_transaction(w3, {"to": ADDRS["community"], "value": 1000})
txhash = w3.eth.send_raw_transaction(signed.rawTransaction)
receipt = w3.eth.wait_for_transaction_receipt(txhash)
assert receipt.status == 1
return txhash
def eth_to_bech32(addr, prefix=ETHERMINT_ADDRESS_PREFIX): def eth_to_bech32(addr, prefix=ETHERMINT_ADDRESS_PREFIX):
bz = bech32.convertbits(HexBytes(addr), 8, 5) bz = bech32.convertbits(HexBytes(addr), 8, 5)
return bech32.bech32_encode(prefix, bz) return bech32.bech32_encode(prefix, bz)