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

tests(rpc): add filter tests #1233

Merged
merged 15 commits into from
Aug 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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:/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):
danburck marked this conversation as resolved.
Show resolved Hide resolved

```
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)