Skip to content

Commit

Permalink
Merge pull request #976 from dylanjw/merging_topic_lists
Browse files Browse the repository at this point in the history
Disallow configuring filters with both manual and generated topic lists
  • Loading branch information
dylanjw authored Aug 2, 2018
2 parents e00740e + 4f55e98 commit 899a991
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 26 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
python_requires='>=3.5, <4',
extras_require={
'tester': [
"eth-tester[py-evm]==0.1.0-beta.29",
"eth-tester[py-evm]==0.1.0-beta.30",
"py-geth>=2.0.1,<3.0.0",
],
'testrpc': ["eth-testrpc>=1.3.3,<2.0.0"],
Expand Down
19 changes: 19 additions & 0 deletions tests/core/filtering/test_contract_createFilter_topic_merging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import pytest


def test_merged_topic_list_event(
web3,
emitter,
emitter_event_ids,
wait_for_transaction):
manual_topics = [
'0xf16c999b533366ca5138d78e85da51611089cd05749f098d6c225d4cd42ee6ec', # event sig
'0x0000000000000000000000000000000000000000000000000000000000000457', # 1111
'0x0000000000000000000000000000000000000000000000000000000000000457', # 1111
'0x0000000000000000000000000000000000000000000000000000000000000457', # 1111
]
with pytest.raises(TypeError):
emitter.events.LogTripleWithIndex().createFilter(
fromBlock="latest",
topics=manual_topics,
argument_filters={'arg0': 2222, 'arg1': 2222, 'arg2': 2222})
49 changes: 49 additions & 0 deletions tests/core/filtering/test_contract_on_event_filtering.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,52 @@ def test_filter_with_contract_address(web3, emitter, emitter_event_ids, wait_for
seen_logs = event_filter.get_new_entries()
assert len(seen_logs) == 1
assert seen_logs[0]['transactionHash'] == txn_hash


@pytest.mark.parametrize('call_as_instance', (True, False))
def test_on_sync_filter_with_topic_filter_options(
web3,
emitter,
Emitter,
wait_for_transaction,
emitter_event_ids,
call_as_instance,
create_filter):

if call_as_instance:
contract = emitter
else:
contract = Emitter

event_filter = create_filter(contract, ['LogTripleWithIndex', {'filter': {
'arg1': [1, 2],
'arg2': [1, 2]
}}])

txn_hashes = []
event_id = emitter_event_ids.LogTripleWithIndex
txn_hashes.append(
emitter.functions.logTriple(event_id, 1, 1, 1).transact()
)
txn_hashes.append(
emitter.functions.logTriple(event_id, 1, 1, 2).transact()
)
txn_hashes.append(
emitter.functions.logTriple(event_id, 1, 2, 2).transact()
)
txn_hashes.append(
emitter.functions.logTriple(event_id, 1, 2, 1).transact()
)
for txn_hash in txn_hashes:
wait_for_transaction(web3, txn_hash)

seen_logs = event_filter.get_new_entries()
assert len(seen_logs) == 4

post_event_filter = contract.events.LogTripleWithIndex.createFilter(
argument_filters={'arg1': [1, 2], 'arg2': [1, 2]},
fromBlock=0,
)

old_logs = post_event_filter.get_all_entries()
assert len(old_logs) == 4
5 changes: 2 additions & 3 deletions tests/core/utilities/test_construct_event_filter_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@
(EVENT_1_ABI, {}, {
"topics": ['0xb470a829ed7792f06947f0ca3730a570cb378329ddcf09f2b4efabd6326f51f6'],
}),
(EVENT_1_ABI, {'topics': ['should-be-preserved']}, {
(EVENT_1_ABI, {'topics': ['should-overwrite-topics']}, {
"topics": [
['should-be-preserved'],
['0xb470a829ed7792f06947f0ca3730a570cb378329ddcf09f2b4efabd6326f51f6'],
'should-overwrite-topics'
]
}),
(EVENT_1_ABI, {'contract_address': '0xd3CdA913deB6f67967B99D67aCDFa1712C293601'}, {
Expand Down
20 changes: 9 additions & 11 deletions tests/core/utilities/test_construct_event_topics.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,48 +31,46 @@ def hex_and_pad(i):
(
EVENT_1_ABI,
{},
[[EVENT_1_TOPIC]],
[EVENT_1_TOPIC],
),
(
EVENT_1_ABI,
{'arg0': 1},
[[EVENT_1_TOPIC]],
[EVENT_1_TOPIC],
),
(
EVENT_1_ABI,
{'arg0': 1, 'arg3': [1, 2]},
[[EVENT_1_TOPIC]],
[EVENT_1_TOPIC],
),
(
EVENT_1_ABI,
{'arg1': 1},
[
[EVENT_1_TOPIC, hex_and_pad(1), None, None],
EVENT_1_TOPIC, hex_and_pad(1)
],
),
(
EVENT_1_ABI,
{'arg1': [1, 2]},
[
[EVENT_1_TOPIC, hex_and_pad(1), None, None],
[EVENT_1_TOPIC, hex_and_pad(2), None, None],
EVENT_1_TOPIC, [hex_and_pad(1), hex_and_pad(2)],
],
),
(
EVENT_1_ABI,
{'arg1': [1], 'arg2': [2]},
[
[EVENT_1_TOPIC, hex_and_pad(1), hex_and_pad(2), None],
EVENT_1_TOPIC, hex_and_pad(1), hex_and_pad(2),
],
),
(
EVENT_1_ABI,
{'arg1': [1, 3], 'arg2': [2, 4]},
[
[EVENT_1_TOPIC, hex_and_pad(1), hex_and_pad(2), None],
[EVENT_1_TOPIC, hex_and_pad(1), hex_and_pad(4), None],
[EVENT_1_TOPIC, hex_and_pad(3), hex_and_pad(2), None],
[EVENT_1_TOPIC, hex_and_pad(3), hex_and_pad(4), None],
EVENT_1_TOPIC,
[hex_and_pad(1), hex_and_pad(3)],
[hex_and_pad(2), hex_and_pad(4)]
],
),
)
Expand Down
29 changes: 23 additions & 6 deletions web3/utils/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
from web3.utils.normalizers import (
BASE_RETURN_NORMALIZERS,
)
from web3.utils.toolz import (
compose,
curry,
)

from .abi import (
exclude_indexed_event_inputs,
Expand Down Expand Up @@ -71,12 +75,7 @@ def construct_event_topic_set(event_abi, arguments=None):
for arg, arg_options in zipped_abi_and_args
]

topics = [
[event_topic] + list(permutation)
if any(value is not None for value in permutation)
else [event_topic]
for permutation in itertools.product(*encoded_args)
]
topics = list(normalize_topic_list([event_topic] + encoded_args))
return topics


Expand Down Expand Up @@ -221,3 +220,21 @@ def get_event_data(event_abi, log_entry):
}

return AttributeDict.recursive(event_data)


@to_tuple
def pop_singlets(seq):
yield from (i[0] if is_list_like(i) and len(i) == 1 else i for i in seq)


@curry
def remove_trailing_from_seq(seq, remove_value=None):
index = len(seq)
while index > 0 and seq[index - 1] == remove_value:
index -= 1
return seq[:index]


normalize_topic_list = compose(
remove_trailing_from_seq(remove_value=None),
pop_singlets,)
13 changes: 8 additions & 5 deletions web3/utils/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@ def construct_event_filter_params(event_abi,
toBlock=None,
address=None):
filter_params = {}

if topics is None:
topic_set = construct_event_topic_set(event_abi, argument_filters)
else:
topic_set = [topics] + construct_event_topic_set(event_abi, argument_filters)
topic_set = construct_event_topic_set(event_abi, argument_filters)

if topics is not None:
if len(topic_set) > 1:
raise TypeError(
"Merging the topics argument with topics generated "
"from argument_filters is not supported.")
topic_set = topics

if len(topic_set) == 1 and is_list_like(topic_set[0]):
filter_params['topics'] = topic_set[0]
Expand Down

0 comments on commit 899a991

Please sign in to comment.