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 10 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
43 changes: 43 additions & 0 deletions tests/integration_tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# RPC Integration tests

The RPC integration test suite uses nix and python to send identical queries to both an Ethermint and a [Geth](https://github.com/ethereum/go-ethereum) client and compare the responses. It allows for quickly assessing the compatibility with Geth.
danburck marked this conversation as resolved.
Show resolved Hide resolved

## 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.
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;
}
}
120 changes: 120 additions & 0 deletions tests/integration_tests/test_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
from web3 import Web3

import pytest
from .utils import (
ADDRS,
CONTRACTS,
deploy_contract,
send_transaction,
send_successful_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
myContract = deploy_contract(w3, CONTRACTS["Greeter"])
assert myContract.caller.greet() == "Hello"

# Create new filter from contract
current_height = hex(w3.eth.get_block_number())
flt = myContract.events.ChangeGreeting.createFilter(
fromBlock=current_height
)

# without tx
assert flt.get_new_entries() == [] # GetFilterChanges
assert flt.get_all_entries() == [] # GetFilterLogs

# with tx
tx = myContract.functions.setGreeting("world").buildTransaction()
tx_receipt = send_transaction(w3, tx)
assert tx_receipt.status == 1

log = myContract.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 myContract.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

myContract = deploy_contract(w3, CONTRACTS["Greeter"])
assert myContract.caller.greet() == "Hello"

flt = w3.eth.filter({"address": myContract.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 = myContract.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

myContract = deploy_contract(w3, CONTRACTS["Greeter"])

# without tx
assert w3.eth.get_logs({"address": myContract.address}) == []
assert w3.eth.get_logs({"address": ADDRS["validator"]}) == []

# with tx
tx = myContract.functions.setGreeting("world").buildTransaction()
receipt = send_transaction(w3, tx)
assert receipt.status == 1

assert len(w3.eth.get_logs({"address": myContract.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 @@ -23,6 +23,7 @@
ETHERMINT_ADDRESS_PREFIX = "ethm"
TEST_CONTRACTS = {
"TestERC20A": "TestERC20A.sol",
"Greeter": "Greeter.sol",
}


Expand Down Expand Up @@ -108,6 +109,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)