Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

Commit

Permalink
tests(rpc): add filter tests (#1233)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
danburck and fedekunze authored Aug 12, 2022
1 parent 94cab52 commit 9bbf356
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 4 deletions.
8 changes: 4 additions & 4 deletions rpc/namespaces/ethereum/eth/filters/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ import (

// FilterAPI gathers
type FilterAPI interface {
GetLogs(ctx context.Context, crit filters.FilterCriteria) ([]*ethtypes.Log, error)
GetFilterChanges(id rpc.ID) (interface{}, error)
GetFilterLogs(ctx context.Context, id rpc.ID) ([]*ethtypes.Log, error)
NewPendingTransactionFilter() rpc.ID
NewBlockFilter() rpc.ID
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
GetLogs(ctx context.Context, crit filters.FilterCriteria) ([]*ethtypes.Log, error)
}

// Backend defines the methods requided by the PublicFilterAPI backend
Expand Down
55 changes: 55 additions & 0 deletions tests/integration_tests/README.md
Original file line number Diff line number Diff line change
@@ -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
```
20 changes: 20 additions & 0 deletions tests/integration_tests/contracts/contracts/Greeter.sol
Original file line number Diff line number Diff line change
@@ -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;
}
}
118 changes: 118 additions & 0 deletions tests/integration_tests/test_filters.py
Original file line number Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions tests/integration_tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
ETHERMINT_ADDRESS_PREFIX = "ethm"
TEST_CONTRACTS = {
"TestERC20A": "TestERC20A.sol",
"Greeter": "Greeter.sol",
}


Expand Down Expand Up @@ -140,6 +141,14 @@ def send_transaction(w3, tx, key=KEYS["validator"]):
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):
bz = bech32.convertbits(HexBytes(addr), 8, 5)
return bech32.bech32_encode(prefix, bz)

0 comments on commit 9bbf356

Please sign in to comment.