Skip to content

Commit 74a8178

Browse files
authored
Merge pull request #117 from shravan-shandilya/master
Whisper support
2 parents ce346fe + 1b9eda6 commit 74a8178

16 files changed

+256
-35
lines changed

.travis.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ env:
4545
- TOX_ENV=py27-net
4646
- TOX_ENV=py34-net
4747
- TOX_ENV=py35-net
48+
# shh
49+
- TOX_ENV=py27-shh
50+
- TOX_ENV=py34-shh
51+
- TOX_ENV=py35-shh
4852
# txpool
4953
- TOX_ENV=py27-txpool
5054
- TOX_ENV=py34-txpool

conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ def setup_testing_geth():
156156
geth_process = GethProcess(
157157
'testing',
158158
base_dir=base_dir,
159-
overrides={'verbosity': '3'},
159+
overrides={'verbosity': '3','shh': True},
160160
)
161161
with geth_process as running_geth_process:
162162
running_geth_process.wait_for_ipc(60)

docs/filters.rst

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ will return a new :py:class::`BlockFilter` object.
102102
... sys.stdout.write("New Block: {0}".format(transaction_hash))
103103
...
104104
>>> new_transaction_filter = web3.eth.filter('pending')
105-
>>> new_transaction_filter.watch(new_transaction_filter)
105+
>>> new_transaction_filter.watch(new_transaction_callback)
106106
# each time the client receieves a unmined transaction the
107107
# `new_transaction_filter` function will be called with the transaction
108108
# hash.
@@ -143,3 +143,23 @@ event data from the event logs.
143143
The :py:class::`PastLogFilter` is a subclass of :py:class::`LogFilter` that is
144144
configured specially to return historical event logs. It conforms to the same
145145
API as the ``LogFilter`` class.
146+
147+
148+
Shh Filter
149+
----------
150+
151+
.. py:class:: ShhFilter(web3, filter_id)
152+
153+
The :py:class:: `ShhFilter` class is used for filtering Shh messages.
154+
You can setup a callback function for Whipser messages matching the topics subscribed using ``web3.shh.filter(filter_params)``,which
155+
will return a :py:class::`ShhFilter` object
156+
157+
.. code-block:: python
158+
159+
>>>def filter_callback(new_message):
160+
... sys.stdout.write("New Shh Message: {0}".format(new_message))
161+
...
162+
>>>shh_filter = web3.shh.filter({"topics":[web3.fromAscii("topic_to_subscribe")]})
163+
>>>shh_filter.watch(filter_callback)
164+
#each time client recieves a Shh messages matching the topics subscibed,
165+
#filter_callback is called

docs/web3.shh.rst

Lines changed: 99 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,120 @@ SHH API
77
The ``web3.shh`` object exposes methods to interact with the RPC APIs under the
88
``shh_`` namespace.
99

10+
Properties
11+
----------
12+
13+
The following properties are available on the ``web.shh`` namespace.
14+
15+
.. py:attribute:: Shh.version
16+
17+
The version of Whisper protocol used by client
18+
19+
.. code-block:: python
20+
21+
>>>web3.shh.version
22+
2
23+
1024
Methods
1125
-------
1226

13-
The following methods are available on the ``web3.personal`` namespace.
27+
The following methods are available on the ``web3.shh`` namespace.
28+
29+
30+
.. py:method:: Shh.post(self, params)
31+
32+
* Delegates to ``shh_post`` RPC method
33+
34+
* ``params`` cannot be ``None`` and should contain ``topics`` and ``payload``
35+
36+
* Returns ``True`` if the message was succesfully sent,otherwise ``False``
37+
38+
.. code-block:: python
39+
40+
>>>web3.shh.post({"topics":[web3.fromAscii("test_topic")],"payload":web3.fromAscii("test_payload")})
41+
True
42+
43+
.. py:method:: Shh.newIdentity(self)
44+
45+
* Delegates to ``shh_newIdentity`` RPC method
46+
47+
* Returns ``address`` of newly created identity.
48+
49+
.. code-block:: python
50+
51+
>>>web3.shh.newIdentity()
52+
u'0x045ed8042f436e1b546afd16e1f803888b896962484c0154fcc7c5fc43e276972af85f29a995a3beb232a4e9a0648858c0c8c0639d709f5d3230807d084b2d5030'
53+
54+
.. py:method:: Shh.hasIdentity(self, identity)
55+
56+
* Delegates to ``shh_hasIdentity`` RPC method
57+
58+
* Returns ``True`` if the client holds the private key for the given identity,otherwise ``False``
59+
60+
.. code-block:: python
61+
62+
>>>web3.shh.hasIdentity(u'0x045ed8042f436e1b546afd16e1f803888b896962484c0154fcc7c5fc43e276972af85f29a995a3beb232a4e9a0648858c0c8c0639d709f5d3230807d084b2d5030')
63+
True
64+
65+
.. py:method:: Shh.newGroup(self)
66+
67+
* Delegates to ``shh_newGroup`` RPC method
68+
69+
* Returns ``address`` of newly created group.
70+
71+
.. note:: This method is not implemented yet in ``Geth``. `Open Issue <https://github.com/ethereum/go-ethereum/issues/310>`_
72+
73+
.. py:method:: Shh.addToGroup(self, identity)
74+
75+
* Delegates to ``shh_addToGroup`` RPC Method
76+
77+
* Returns ``True`` if the identity was succesfully added to the group,otherwise ``False``
78+
79+
.. note:: This method is not implemented yet in ``Geth``. `Open Issue <https://github.com/ethereum/go-ethereum/issues/310>`_
80+
81+
.. py:method:: Shh.filter(self, filter_params)
82+
83+
* Delegates to ``shh_newFilter`` RPC Method
84+
85+
* ``filter_params`` should contain the ``topics`` to subscribe
1486

87+
* Returns an instance of ``ShhFilter`` on succesful creation of filter,otherwise raises ``ValueError`` exception
1588

16-
.. py:method:: Shh.post(self, *args, **kwargs)
89+
.. code-block:: python
1790
18-
.. note:: Not Implemented
91+
>>>shh_filter = shh.filter({"topics":[web.fromAscii("topic_to_subscribe")]})
92+
>>>shh_filter.filter_id
93+
u'0x0'
1994
95+
.. py:method:: Shh.uninstallFilter(self, filter_id)
2096
21-
.. py:method:: Shh.newIdentity(self, *args, **kwargs)
97+
* Delegates to ``shh_uninstallFilter`` RPC Method
2298

23-
.. note:: Not Implemented
99+
* Returns ``True`` if the filter was sucesfully uninstalled ,otherwise ``False``
24100

101+
.. code-block:: python
25102
26-
.. py:method:: Shh.hasIdentity(self, *args, **kwargs)
103+
>>>web3.shh.uninstallFilter("0x2")
104+
True
27105
28-
.. note:: Not Implemented
106+
.. py:method:: Shh.getFilterChanges(self, filter_id)
29107
108+
* Delegates to ``shh_getFilterChanges`` RPC Method
30109

31-
.. py:method:: Shh.newGroup(self, *args, **kwargs)
110+
* Returns list of messages recieved since last poll
111+
112+
.. code-block:: python
113+
114+
>>>web3.shh.getFilterChanges(self,"0x2")
115+
[{u'from': u'0x0', u'to': u'0x0', u'ttl': 50, u'hash': u'0xf84900b57d856a6ab1b41afc9784c31be48e841b9bcfc6accac14d05d7189f2f', u'payload': u'0x746573696e67', u'sent': 1476625149}]
32116
33-
.. note:: Not Implemented
117+
.. py:method:: Shh.getMessages(self, filter_id)
34118
119+
* Delegates to ``shh_getMessages`` RPC Method
35120

36-
.. py:method:: Shh.addToGroup(self, *args, **kwargs)
121+
* Returns a list of all messages
37122

38-
.. note:: Not Implemented
123+
.. code-block:: python
124+
125+
>>>web3.shh.getMessages("0x2")
126+
[{u'from': u'0x0', u'to': u'0x0', u'ttl': 50, u'hash': u'0x808d74d003d1dcbed546cca29d7a4e839794c226296b613b0fa7a8c670f84146', u'payload': u'0x746573696e67617364', u'sent': 1476625342}, {u'from': u'0x0', u'to': u'0x0', u'ttl': 50, u'hash': u'0x62a2eb9a19968d59d8a85e6dc8d73deb9b4cd40c83d95b796262d6affe6397c6', u'payload': u'0x746573696e67617364617364', u'sent': 1476625369}]

requirements-dev.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ pytest-pythonpath>=0.3
33
tox>=1.8.0
44
eth-testrpc>=0.8.6
55
ethereum-tester-client>=1.2.3
6-
py-geth>=1.2.0
6+
py-geth>=1.4.0
77
ethereum>=1.5.2
88
secp256k1>=0.13.1
99
rlp>=0.4.6
1010
hypothesis>=3.4.2
1111
flaky>=3.3.0
12+
flake8==3.0.4

requirements-docs.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ contextlib2>=0.5.4
1010
#eth-testrpc>=0.8.0
1111
#ethereum-tester-client>=1.1.0
1212
gevent>=1.1.2
13-
py-geth>=1.1.0
13+
py-geth>=1.4.0
1414
py-solc>=0.4.0
1515
#pysha3>=0.3
1616
pytest>=2.7.2

tests/filtering/test_contract_on_event_filtering.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def test_on_filter_using_get_interface(web3_empty,
2323
txn_hash = emitter.transact().logNoArgs(emitter_event_ids.LogNoArguments)
2424
txn_receipt = wait_for_transaction(web3, txn_hash)
2525

26-
with gevent.Timeout(10):
26+
with gevent.Timeout(30):
2727
while not filter.get(False):
2828
gevent.sleep(random.random())
2929

@@ -54,11 +54,11 @@ def test_on_filter_with_only_event_name(web3_empty,
5454
txn_hash = emitter.transact().logNoArgs(emitter_event_ids.LogNoArguments)
5555
txn_receipt = wait_for_transaction(web3, txn_hash)
5656

57-
with gevent.Timeout(5):
57+
with gevent.Timeout(30):
5858
while not seen_logs:
5959
gevent.sleep(random.random())
6060

61-
filter.stop_watching(10)
61+
filter.stop_watching(30)
6262

6363
assert len(seen_logs) == 1
6464
assert seen_logs[0]['transactionHash'] == txn_hash
@@ -99,11 +99,11 @@ def test_on_filter_with_event_name_and_single_argument(web3_empty,
9999
for txn_hash in txn_hashes:
100100
wait_for_transaction(web3, txn_hash)
101101

102-
with gevent.Timeout(5):
102+
with gevent.Timeout(30):
103103
while len(seen_logs) < 2:
104104
gevent.sleep(random.random())
105105

106-
filter.stop_watching(10)
106+
filter.stop_watching(30)
107107

108108
assert len(seen_logs) == 2
109109
assert {l['transactionHash'] for l in seen_logs} == set(txn_hashes[1:])
@@ -144,11 +144,11 @@ def test_on_filter_with_event_name_and_non_indexed_argument(web3_empty,
144144
for txn_hash in txn_hashes:
145145
wait_for_transaction(web3, txn_hash)
146146

147-
with gevent.Timeout(5):
147+
with gevent.Timeout(30):
148148
while not seen_logs:
149149
gevent.sleep(random.random())
150150

151-
filter.stop_watching(10)
151+
filter.stop_watching(30)
152152

153153
assert len(seen_logs) == 1
154154
assert seen_logs[0]['transactionHash'] == txn_hashes[1]

tests/filtering/test_contract_past_event_filtering.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ def test_past_events_filter_with_callback(web3_empty,
2626
else:
2727
filter = Emitter.pastEvents('LogNoArguments', {}, seen_logs.append)
2828

29-
with gevent.Timeout(5):
29+
with gevent.Timeout(30):
3030
while not seen_logs:
3131
gevent.sleep(random.random())
3232

33-
filter.stop_watching(10)
33+
filter.stop_watching(30)
3434

3535
assert len(seen_logs) == 1
3636
event_data = seen_logs[0]
@@ -62,7 +62,7 @@ def test_past_events_filter_using_get_api(web3_empty,
6262
else:
6363
filter = Emitter.pastEvents('LogNoArguments')
6464

65-
with gevent.Timeout(10):
65+
with gevent.Timeout(30):
6666
while not filter.get(False):
6767
gevent.sleep(random.random())
6868

tests/shh-module/test_shh_filter.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import gevent
2+
3+
def test_shh_filter(web3, skip_if_testrpc):
4+
skip_if_testrpc(web3)
5+
recieved_messages = []
6+
shh_filter = web3.shh.filter({"topics":[web3.fromAscii("test")]})
7+
shh_filter.watch(recieved_messages.append)
8+
gevent.sleep(1)
9+
10+
payloads = []
11+
payloads.append(str.encode("payload1"))
12+
web3.shh.post({"topics":[web3.fromAscii("test")], "payload":web3.fromAscii(payloads[len(payloads)-1])})
13+
gevent.sleep(1)
14+
15+
payloads.append(str.encode("payload2"))
16+
web3.shh.post({"topics":[web3.fromAscii("test")], "payload":web3.fromAscii(payloads[len(payloads)-1])})
17+
gevent.sleep(1)
18+
19+
assert len(recieved_messages) > 1
20+
21+
for message in recieved_messages:
22+
assert web3.toAscii(message["payload"]) in payloads
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
def test_shh_has_identity(web3, skip_if_testrpc):
2+
skip_if_testrpc(web3)
3+
new_identity = web3.shh.newIdentity()
4+
assert len(new_identity) == 132
5+
assert web3.shh.hasIdentity(new_identity)

0 commit comments

Comments
 (0)