From 699494613ffeeaa343e9c59d37f48995718c2621 Mon Sep 17 00:00:00 2001 From: Lev Berman Date: Thu, 6 Sep 2018 15:49:00 +0200 Subject: [PATCH] Problem: The commit mode behaves incorrectly. (#2510) * Problem: The commit mode behaves incorrectly. Solution: Parse the Tendermint response properly. The functionality was disabled in https://github.com/bigchaindb/bigchaindb/pull/2235/files#diff-c6511560546a7dc577e7e647b5bfdaceL68 and was not fixed since then. * Add a test case for the sync mode. * Do not strictly expect deliver_tx in the response. * Fix post_mock in web/test_transactions.py. * Check for the error field first. --- bigchaindb/lib.py | 39 ++++++++++++---------------- tests/tendermint/test_integration.py | 19 +++++++------- tests/web/test_transactions.py | 6 +++++ 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/bigchaindb/lib.py b/bigchaindb/lib.py index 017151db..fae4c76a 100644 --- a/bigchaindb/lib.py +++ b/bigchaindb/lib.py @@ -56,9 +56,10 @@ class BigchainDB(object): A connection to the database. """ config_utils.autoconfigure() + self.mode_commit = 'broadcast_tx_commit' self.mode_list = ('broadcast_tx_async', 'broadcast_tx_sync', - 'broadcast_tx_commit') + self.mode_commit) self.tendermint_host = bigchaindb.config['tendermint']['host'] self.tendermint_port = bigchaindb.config['tendermint']['port'] self.endpoint = 'http://{}:{}/'.format(self.tendermint_host, self.tendermint_port) @@ -96,29 +97,23 @@ class BigchainDB(object): def _process_post_response(self, response, mode): logger.debug(response) - if response.get('error') is not None: - return (500, 'Internal error') + + error = response.get('error') + if error: + return (500, error) + + result = response['result'] + if mode == self.mode_commit: + check_tx_code = result.get('check_tx', {}).get('code', 0) + deliver_tx_code = result.get('deliver_tx', {}).get('code', 0) + error_code = check_tx_code or deliver_tx_code + else: + error_code = result.get('code', 0) + + if error_code: + return (500, 'Transaction validation failed') return (202, '') - # result = response['result'] - # if mode == self.mode_list[2]: - # return self._process_commit_mode_response(result) - # else: - # status_code = result['code'] - # return self._process_status_code(status_code, - # 'Error while processing transaction') - - # def _process_commit_mode_response(self, result): - # check_tx_status_code = result['check_tx']['code'] - # if check_tx_status_code == 0: - # deliver_tx_status_code = result['deliver_tx']['code'] - # return self._process_status_code(deliver_tx_status_code, - # 'Error while commiting the transaction') - # else: - # return (500, 'Error while validating the transaction') - - def process_status_code(self, status_code, failure_msg): - return (202, '') if status_code == 0 else (500, failure_msg) def store_bulk_transactions(self, transactions): txns = [] diff --git a/tests/tendermint/test_integration.py b/tests/tendermint/test_integration.py index b860abdf..d3f01612 100644 --- a/tests/tendermint/test_integration.py +++ b/tests/tendermint/test_integration.py @@ -130,12 +130,13 @@ def test_post_transaction_responses(tendermint_ws_url, b): code, message = b.write_transaction(tx_transfer, 'broadcast_tx_commit') assert code == 202 - # NOTE: DOESN'T WORK (double spend) - # Tendermint crashes with error: Unexpected result type - # carly = generate_key_pair() - # double_spend = Transaction.transfer(tx.to_inputs(), - # [([carly.public_key], 1)], - # asset_id=tx.id)\ - # .sign([alice.private_key]) - # code, message = b.write_transaction(double_spend, 'broadcast_tx_commit') - # assert code == 500 + carly = generate_key_pair() + double_spend = Transaction.transfer( + tx.to_inputs(), + [([carly.public_key], 1)], + asset_id=tx.id, + ).sign([alice.private_key]) + for mode in ('broadcast_tx_sync', 'broadcast_tx_commit'): + code, message = b.write_transaction(double_spend, mode) + assert code == 500 + assert message == 'Transaction validation failed' diff --git a/tests/web/test_transactions.py b/tests/web/test_transactions.py index 7c7f2b7a..97386da0 100644 --- a/tests/web/test_transactions.py +++ b/tests/web/test_transactions.py @@ -416,6 +416,12 @@ def test_transactions_get_list_bad(client): def test_post_transaction_valid_modes(mock_post, client, mode): from bigchaindb.models import Transaction from bigchaindb.common.crypto import generate_key_pair + + def _mock_post(*args, **kwargs): + return Mock(json=Mock(return_value={'result': {'code': 0}})) + + mock_post.side_effect = _mock_post + alice = generate_key_pair() tx = Transaction.create([alice.public_key], [([alice.public_key], 1)],