diff --git a/tests/core/eth-module/test_transactions.py b/tests/core/eth-module/test_transactions.py index 2fab7fbd2b..2a1c59b468 100644 --- a/tests/core/eth-module/test_transactions.py +++ b/tests/core/eth-module/test_transactions.py @@ -1,12 +1,15 @@ import pytest from web3.exceptions import ( + TimeExhausted, ValidationError, ) from web3.middleware.simulate_unmined_transaction import ( unmined_receipt_simulator_middleware, ) +RECEIPT_TIMEOUT = 0.2 + @pytest.mark.parametrize( 'make_chain_id, expect_success', @@ -28,8 +31,9 @@ def test_send_transaction_with_valid_chain_id(web3, make_chain_id, expect_succes 'chainId': make_chain_id(web3), } if expect_success: - # just be happy that we didn't crash - web3.eth.sendTransaction(transaction) + txn_hash = web3.eth.sendTransaction(transaction) + receipt = web3.eth.waitForTransactionReceipt(txn_hash, timeout=RECEIPT_TIMEOUT) + assert receipt.get('blockNumber') is not None else: with pytest.raises(ValidationError) as exc_info: web3.eth.sendTransaction(transaction) @@ -37,7 +41,12 @@ def test_send_transaction_with_valid_chain_id(web3, make_chain_id, expect_succes assert 'chain ID' in str(exc_info.value) -def test_unmined_transaction_wait_for_receipt(web3, extra_accounts): +def test_wait_for_missing_receipt(web3): + with pytest.raises(TimeExhausted): + web3.eth.waitForTransactionReceipt(b'\0' * 32, timeout=RECEIPT_TIMEOUT) + + +def test_unmined_transaction_wait_for_receipt(web3): web3.middleware_stack.add(unmined_receipt_simulator_middleware) txn_hash = web3.eth.sendTransaction({ 'from': web3.eth.coinbase, diff --git a/tests/generate_go_ethereum_fixture.py b/tests/generate_go_ethereum_fixture.py index bc212adf73..5892db5302 100644 --- a/tests/generate_go_ethereum_fixture.py +++ b/tests/generate_go_ethereum_fixture.py @@ -297,17 +297,11 @@ def verify_chain_state(web3, chain_data): def mine_transaction_hash(web3, txn_hash): - start_time = time.time() web3.miner.start(1) - while time.time() < start_time + 60: - receipt = web3.eth.waitForTransactionReceipt(txn_hash) - if receipt is not None: - web3.miner.stop() - return receipt - else: - time.sleep(0.1) - else: - raise ValueError("Math contract deploy transaction not mined during wait period") + try: + return web3.eth.waitForTransactionReceipt(txn_hash, timeout=60) + finally: + web3.miner.stop() def mine_block(web3): diff --git a/web3/eth.py b/web3/eth.py index cf773db5aa..dfd377eead 100644 --- a/web3/eth.py +++ b/web3/eth.py @@ -27,6 +27,9 @@ LogFilter, TransactionFilter, ) +from web3._utils.threads import ( + Timeout, +) from web3._utils.toolz import ( assoc, merge, @@ -42,6 +45,9 @@ from web3.contract import ( Contract, ) +from web3.exceptions import ( + TimeExhausted, +) from web3.iban import ( Iban, ) @@ -220,7 +226,15 @@ def getTransactionByBlock(self, block_identifier, transaction_index): ) def waitForTransactionReceipt(self, transaction_hash, timeout=120): - return wait_for_transaction_receipt(self.web3, transaction_hash, timeout) + try: + return wait_for_transaction_receipt(self.web3, transaction_hash, timeout) + except Timeout: + raise TimeExhausted( + "Transaction {} is not in the chain, after {} seconds".format( + transaction_hash, + timeout, + ) + ) def getTransactionReceipt(self, transaction_hash): return self.web3.manager.request_blocking( diff --git a/web3/exceptions.py b/web3/exceptions.py index aa0671d87b..406aacae41 100644 --- a/web3/exceptions.py +++ b/web3/exceptions.py @@ -107,3 +107,10 @@ class InsufficientData(Exception): complete a calculation """ pass + + +class TimeExhausted(Exception): + """ + Raised when a method has not retrieved the desired result within a specified timeout. + """ + pass