diff --git a/bigchaindb/backend/connection.py b/bigchaindb/backend/connection.py index ab86e5d8..0fa19fdb 100644 --- a/bigchaindb/backend/connection.py +++ b/bigchaindb/backend/connection.py @@ -2,14 +2,14 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 -from itertools import repeat -from importlib import import_module import logging +from importlib import import_module +from itertools import repeat import bigchaindb -from bigchaindb.common.exceptions import ConfigurationError from bigchaindb.backend.exceptions import ConnectionError - +from bigchaindb.backend.utils import get_bigchaindb_config_value, get_bigchaindb_config_value_or_key_error +from bigchaindb.common.exceptions import ConfigurationError BACKENDS = { 'localmongodb': 'bigchaindb.backend.localmongodb.connection.LocalMongoDBConnection', @@ -47,10 +47,10 @@ def connect(backend=None, host=None, port=None, name=None, max_tries=None, Authentication failure after connecting to the database. """ - backend = backend or bigchaindb.config['database']['backend'] - host = host or bigchaindb.config['database']['host'] - port = port or bigchaindb.config['database']['port'] - dbname = name or bigchaindb.config['database']['name'] + backend = backend or get_bigchaindb_config_value_or_key_error('backend') + host = host or get_bigchaindb_config_value_or_key_error('host') + port = port or get_bigchaindb_config_value_or_key_error('port') + dbname = name or get_bigchaindb_config_value_or_key_error('name') # Not sure how to handle this here. This setting is only relevant for # mongodb. # I added **kwargs for both RethinkDBConnection and MongoDBConnection @@ -60,15 +60,15 @@ def connect(backend=None, host=None, port=None, name=None, max_tries=None, # UPD: RethinkDBConnection is not here anymore cause we no longer support RethinkDB. # The problem described above might be reconsidered next time we introduce a backend, # if it ever happens. - replicaset = replicaset or bigchaindb.config['database'].get('replicaset') - ssl = ssl if ssl is not None else bigchaindb.config['database'].get('ssl', False) - login = login or bigchaindb.config['database'].get('login') - password = password or bigchaindb.config['database'].get('password') - ca_cert = ca_cert or bigchaindb.config['database'].get('ca_cert', None) - certfile = certfile or bigchaindb.config['database'].get('certfile', None) - keyfile = keyfile or bigchaindb.config['database'].get('keyfile', None) - keyfile_passphrase = keyfile_passphrase or bigchaindb.config['database'].get('keyfile_passphrase', None) - crlfile = crlfile or bigchaindb.config['database'].get('crlfile', None) + replicaset = replicaset or get_bigchaindb_config_value('replicaset') + ssl = ssl if ssl is not None else get_bigchaindb_config_value('ssl', False) + login = login or get_bigchaindb_config_value('login') + password = password or get_bigchaindb_config_value('password') + ca_cert = ca_cert or get_bigchaindb_config_value('ca_cert') + certfile = certfile or get_bigchaindb_config_value('certfile') + keyfile = keyfile or get_bigchaindb_config_value('keyfile') + keyfile_passphrase = keyfile_passphrase or get_bigchaindb_config_value('keyfile_passphrase', None) + crlfile = crlfile or get_bigchaindb_config_value('crlfile') try: module_name, _, class_name = BACKENDS[backend].rpartition('.') @@ -117,7 +117,7 @@ class Connection: self.host = host or dbconf['host'] self.port = port or dbconf['port'] self.dbname = dbname or dbconf['name'] - self.connection_timeout = connection_timeout if connection_timeout is not None\ + self.connection_timeout = connection_timeout if connection_timeout is not None \ else dbconf['connection_timeout'] self.max_tries = max_tries if max_tries is not None else dbconf['max_tries'] self.max_tries_counter = range(self.max_tries) if self.max_tries != 0 else repeat(0) diff --git a/bigchaindb/backend/localmongodb/connection.py b/bigchaindb/backend/localmongodb/connection.py index 40142168..f638dcac 100644 --- a/bigchaindb/backend/localmongodb/connection.py +++ b/bigchaindb/backend/localmongodb/connection.py @@ -7,13 +7,13 @@ from ssl import CERT_REQUIRED import pymongo -import bigchaindb -from bigchaindb.utils import Lazy -from bigchaindb.common.exceptions import ConfigurationError +from bigchaindb.backend.connection import Connection from bigchaindb.backend.exceptions import (DuplicateKeyError, OperationError, ConnectionError) -from bigchaindb.backend.connection import Connection +from bigchaindb.backend.utils import get_bigchaindb_config_value +from bigchaindb.common.exceptions import ConfigurationError +from bigchaindb.utils import Lazy logger = logging.getLogger(__name__) @@ -33,15 +33,15 @@ class LocalMongoDBConnection(Connection): """ super().__init__(**kwargs) - self.replicaset = replicaset or bigchaindb.config['database'].get('replicaset') - self.ssl = ssl if ssl is not None else bigchaindb.config['database'].get('ssl', False) - self.login = login or bigchaindb.config['database'].get('login') - self.password = password or bigchaindb.config['database'].get('password') - self.ca_cert = ca_cert or bigchaindb.config['database'].get('ca_cert', None) - self.certfile = certfile or bigchaindb.config['database'].get('certfile', None) - self.keyfile = keyfile or bigchaindb.config['database'].get('keyfile', None) - self.keyfile_passphrase = keyfile_passphrase or bigchaindb.config['database'].get('keyfile_passphrase', None) - self.crlfile = crlfile or bigchaindb.config['database'].get('crlfile', None) + self.replicaset = replicaset or get_bigchaindb_config_value('replicaset') + self.ssl = ssl if ssl is not None else get_bigchaindb_config_value('ssl', False) + self.login = login or get_bigchaindb_config_value('login') + self.password = password or get_bigchaindb_config_value('password') + self.ca_cert = ca_cert or get_bigchaindb_config_value('ca_cert') + self.certfile = certfile or get_bigchaindb_config_value('certfile') + self.keyfile = keyfile or get_bigchaindb_config_value('keyfile') + self.keyfile_passphrase = keyfile_passphrase or get_bigchaindb_config_value('keyfile_passphrase') + self.crlfile = crlfile or get_bigchaindb_config_value('crlfile') @property def db(self): diff --git a/bigchaindb/backend/utils.py b/bigchaindb/backend/utils.py index a64995a7..246f9961 100644 --- a/bigchaindb/backend/utils.py +++ b/bigchaindb/backend/utils.py @@ -2,6 +2,8 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 +import bigchaindb + class ModuleDispatchRegistrationError(Exception): """Raised when there is a problem registering dispatched functions for a @@ -21,6 +23,16 @@ def module_dispatch_registrar(module): ('`{module}` does not contain a single-dispatchable ' 'function named `{func}`. The module being registered ' 'was not implemented correctly!').format( - func=func_name, module=module.__name__)) from ex + func=func_name, module=module.__name__)) from ex + return wrapper + return dispatch_wrapper + + +def get_bigchaindb_config_value(key, default_value=None): + return bigchaindb.config['database'].get(key, default_value) + + +def get_bigchaindb_config_value_or_key_error(key): + return bigchaindb.config['database'][key] diff --git a/bigchaindb/commands/bigchaindb.py b/bigchaindb/commands/bigchaindb.py index 639b3584..383c19aa 100644 --- a/bigchaindb/commands/bigchaindb.py +++ b/bigchaindb/commands/bigchaindb.py @@ -16,6 +16,7 @@ import sys from bigchaindb.core import rollback from bigchaindb.migrations.chain_migration_election import ChainMigrationElection from bigchaindb.utils import load_node_key +from bigchaindb.common.transaction_mode_types import BROADCAST_TX_COMMIT from bigchaindb.common.exceptions import (DatabaseDoesNotExist, ValidationError) from bigchaindb.elections.vote import Vote @@ -131,7 +132,7 @@ def create_new_election(sk, bigchain, election_class, data): logger.error(fd_404) return False - resp = bigchain.write_transaction(election, 'broadcast_tx_commit') + resp = bigchain.write_transaction(election, BROADCAST_TX_COMMIT) if resp == (202, ''): logger.info('[SUCCESS] Submitted proposal with id: {}'.format(election.id)) return election.id @@ -206,7 +207,7 @@ def run_election_approve(args, bigchain): tx.id).sign([key.private_key]) approval.validate(bigchain) - resp = bigchain.write_transaction(approval, 'broadcast_tx_commit') + resp = bigchain.write_transaction(approval, BROADCAST_TX_COMMIT) if resp == (202, ''): logger.info('[SUCCESS] Your vote has been submitted') @@ -261,7 +262,6 @@ def run_drop(args): return conn = backend.connect() - dbname = bigchaindb.config['database']['name'] try: schema.drop_database(conn, dbname) except DatabaseDoesNotExist: diff --git a/bigchaindb/common/transaction_mode_types.py b/bigchaindb/common/transaction_mode_types.py new file mode 100644 index 00000000..a1a58ca2 --- /dev/null +++ b/bigchaindb/common/transaction_mode_types.py @@ -0,0 +1,7 @@ +# Copyright BigchainDB GmbH and BigchainDB contributors +# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) +# Code is Apache-2.0 and docs are CC-BY-4.0 + +BROADCAST_TX_COMMIT = 'broadcast_tx_commit' +BROADCAST_TX_ASYNC = 'broadcast_tx_async' +BROADCAST_TX_SYNC = 'broadcast_tx_sync' diff --git a/bigchaindb/lib.py b/bigchaindb/lib.py index ce7091d3..53745985 100644 --- a/bigchaindb/lib.py +++ b/bigchaindb/lib.py @@ -9,6 +9,7 @@ MongoDB. import logging from collections import namedtuple from uuid import uuid4 + import rapidjson try: @@ -25,6 +26,9 @@ from bigchaindb.models import Transaction from bigchaindb.common.exceptions import (SchemaValidationError, ValidationError, DoubleSpend) +from bigchaindb.common.transaction_mode_types import (BROADCAST_TX_COMMIT, + BROADCAST_TX_ASYNC, + BROADCAST_TX_SYNC) from bigchaindb.tendermint_utils import encode_transaction, merkleroot from bigchaindb import exceptions as core_exceptions from bigchaindb.validation import BaseValidationRules @@ -56,9 +60,9 @@ 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', + self.mode_commit = BROADCAST_TX_COMMIT + self.mode_list = (BROADCAST_TX_ASYNC, + BROADCAST_TX_SYNC, self.mode_commit) self.tendermint_host = bigchaindb.config['tendermint']['host'] self.tendermint_port = bigchaindb.config['tendermint']['port'] diff --git a/bigchaindb/models.py b/bigchaindb/models.py index 9c05cd90..b12a6d76 100644 --- a/bigchaindb/models.py +++ b/bigchaindb/models.py @@ -2,15 +2,18 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 +from bigchaindb.backend.schema import validate_language_key from bigchaindb.common.exceptions import (InvalidSignature, DuplicateTransaction) +from bigchaindb.common.schema import validate_transaction_schema from bigchaindb.common.transaction import Transaction from bigchaindb.common.utils import (validate_txn_obj, validate_key) -from bigchaindb.common.schema import validate_transaction_schema -from bigchaindb.backend.schema import validate_language_key class Transaction(Transaction): + ASSET = 'asset' + METADATA = 'metadata' + DATA = 'data' def validate(self, bigchain, current_transactions=[]): """Validate transaction spend @@ -46,10 +49,10 @@ class Transaction(Transaction): @classmethod def validate_schema(cls, tx_body): validate_transaction_schema(tx_body) - validate_txn_obj('asset', tx_body['asset'], 'data', validate_key) - validate_txn_obj('metadata', tx_body, 'metadata', validate_key) - validate_language_key(tx_body['asset'], 'data') - validate_language_key(tx_body, 'metadata') + validate_txn_obj(cls.ASSET, tx_body[cls.ASSET], cls.DATA, validate_key) + validate_txn_obj(cls.METADATA, tx_body, cls.METADATA, validate_key) + validate_language_key(tx_body[cls.ASSET], cls.DATA) + validate_language_key(tx_body, cls.METADATA) class FastTransaction: diff --git a/bigchaindb/web/views/base.py b/bigchaindb/web/views/base.py index 3ca79f0c..6110e648 100644 --- a/bigchaindb/web/views/base.py +++ b/bigchaindb/web/views/base.py @@ -36,7 +36,10 @@ def base_ws_uri(): customized (typically when running behind NAT, firewall, etc.) """ - scheme = config['wsserver']['advertised_scheme'] - host = config['wsserver']['advertised_host'] - port = config['wsserver']['advertised_port'] + config_wsserver = config['wsserver'] + + scheme = config_wsserver['advertised_scheme'] + host = config_wsserver['advertised_host'] + port = config_wsserver['advertised_port'] + return '{}://{}:{}'.format(scheme, host, port) diff --git a/bigchaindb/web/views/parameters.py b/bigchaindb/web/views/parameters.py index ed78157a..d568ceb1 100644 --- a/bigchaindb/web/views/parameters.py +++ b/bigchaindb/web/views/parameters.py @@ -4,6 +4,10 @@ import re +from bigchaindb.common.transaction_mode_types import (BROADCAST_TX_COMMIT, + BROADCAST_TX_ASYNC, + BROADCAST_TX_SYNC) + def valid_txid(txid): if re.match('^[a-fA-F0-9]{64}$', txid): @@ -38,9 +42,9 @@ def valid_operation(op): def valid_mode(mode): if mode == 'async': - return 'broadcast_tx_async' + return BROADCAST_TX_ASYNC if mode == 'sync': - return 'broadcast_tx_sync' + return BROADCAST_TX_SYNC if mode == 'commit': - return 'broadcast_tx_commit' + return BROADCAST_TX_COMMIT raise ValueError('Mode must be "async", "sync" or "commit"') diff --git a/bigchaindb/web/views/transactions.py b/bigchaindb/web/views/transactions.py index 9bbc209d..78f338d4 100644 --- a/bigchaindb/web/views/transactions.py +++ b/bigchaindb/web/views/transactions.py @@ -11,6 +11,7 @@ import logging from flask import current_app, request, jsonify from flask_restful import Resource, reqparse +from bigchaindb.common.transaction_mode_types import BROADCAST_TX_ASYNC from bigchaindb.common.exceptions import SchemaValidationError, ValidationError from bigchaindb.web.views.base import make_error from bigchaindb.web.views import parameters @@ -62,7 +63,7 @@ class TransactionListApi(Resource): """ parser = reqparse.RequestParser() parser.add_argument('mode', type=parameters.valid_mode, - default='broadcast_tx_async') + default=BROADCAST_TX_ASYNC) args = parser.parse_args() mode = str(args['mode']) diff --git a/tests/conftest.py b/tests/conftest.py index ab798749..d1bf9920 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,6 +22,7 @@ from pymongo import MongoClient from bigchaindb import ValidatorElection from bigchaindb.common import crypto +from bigchaindb.common.transaction_mode_types import BROADCAST_TX_COMMIT from bigchaindb.tendermint_utils import key_from_base64 from bigchaindb.backend import schema, query from bigchaindb.common.crypto import (key_pair_from_ed25519_key, @@ -272,7 +273,7 @@ def signed_create_tx(alice, create_tx): @pytest.fixture def posted_create_tx(b, signed_create_tx): - res = b.post_transaction(signed_create_tx, 'broadcast_tx_commit') + res = b.post_transaction(signed_create_tx, BROADCAST_TX_COMMIT) assert res.status_code == 200 return signed_create_tx diff --git a/tests/tendermint/test_integration.py b/tests/tendermint/test_integration.py index da373442..c9288841 100644 --- a/tests/tendermint/test_integration.py +++ b/tests/tendermint/test_integration.py @@ -11,6 +11,8 @@ import pytest from abci.server import ProtocolHandler from abci.encoding import read_messages + +from bigchaindb.common.transaction_mode_types import BROADCAST_TX_COMMIT, BROADCAST_TX_SYNC from bigchaindb.version import __tm_supported_versions__ from io import BytesIO @@ -120,7 +122,7 @@ def test_post_transaction_responses(tendermint_ws_url, b): asset=None)\ .sign([alice.private_key]) - code, message = b.write_transaction(tx, 'broadcast_tx_commit') + code, message = b.write_transaction(tx, BROADCAST_TX_COMMIT) assert code == 202 tx_transfer = Transaction.transfer(tx.to_inputs(), @@ -128,7 +130,7 @@ def test_post_transaction_responses(tendermint_ws_url, b): asset_id=tx.id)\ .sign([alice.private_key]) - code, message = b.write_transaction(tx_transfer, 'broadcast_tx_commit') + code, message = b.write_transaction(tx_transfer, BROADCAST_TX_COMMIT) assert code == 202 carly = generate_key_pair() @@ -137,7 +139,7 @@ def test_post_transaction_responses(tendermint_ws_url, b): [([carly.public_key], 1)], asset_id=tx.id, ).sign([alice.private_key]) - for mode in ('broadcast_tx_sync', 'broadcast_tx_commit'): + 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/tendermint/test_lib.py b/tests/tendermint/test_lib.py index 5bf41d23..06a5e1f4 100644 --- a/tests/tendermint/test_lib.py +++ b/tests/tendermint/test_lib.py @@ -5,6 +5,7 @@ import os from unittest.mock import patch + try: from hashlib import sha3_256 except ImportError: @@ -15,6 +16,9 @@ import pytest from pymongo import MongoClient from bigchaindb import backend +from bigchaindb.common.transaction_mode_types import (BROADCAST_TX_COMMIT, + BROADCAST_TX_ASYNC, + BROADCAST_TX_SYNC) from bigchaindb.lib import Block @@ -103,20 +107,20 @@ def test_write_and_post_transaction(mock_post, b): .sign([alice.private_key]).to_dict() tx = b.validate_transaction(tx) - b.write_transaction(tx, 'broadcast_tx_async') + b.write_transaction(tx, BROADCAST_TX_ASYNC) assert mock_post.called args, kwargs = mock_post.call_args - assert 'broadcast_tx_async' == kwargs['json']['method'] + assert BROADCAST_TX_ASYNC == kwargs['json']['method'] encoded_tx = [encode_transaction(tx.to_dict())] assert encoded_tx == kwargs['json']['params'] @patch('requests.post') @pytest.mark.parametrize('mode', [ - 'broadcast_tx_async', - 'broadcast_tx_sync', - 'broadcast_tx_commit' + BROADCAST_TX_SYNC, + BROADCAST_TX_ASYNC, + BROADCAST_TX_COMMIT ]) def test_post_transaction_valid_modes(mock_post, b, mode): from bigchaindb.models import Transaction diff --git a/tests/upsert_validator/test_upsert_validator_vote.py b/tests/upsert_validator/test_upsert_validator_vote.py index eeac3e66..305b4f2e 100644 --- a/tests/upsert_validator/test_upsert_validator_vote.py +++ b/tests/upsert_validator/test_upsert_validator_vote.py @@ -11,6 +11,7 @@ from bigchaindb.upsert_validator import ValidatorElection from bigchaindb.common.exceptions import AmountError from bigchaindb.common.crypto import generate_key_pair from bigchaindb.common.exceptions import ValidationError +from bigchaindb.common.transaction_mode_types import BROADCAST_TX_COMMIT from bigchaindb.elections.vote import Vote from tests.utils import generate_block, gen_vote @@ -241,13 +242,13 @@ def test_upsert_validator(b, node_key, node_keys, ed25519_node_keys): election = ValidatorElection.generate([node_key.public_key], voters, new_validator, None).sign([node_key.private_key]) - code, message = b.write_transaction(election, 'broadcast_tx_commit') + code, message = b.write_transaction(election, BROADCAST_TX_COMMIT) assert code == 202 assert b.get_transaction(election.id) tx_vote = gen_vote(election, 0, ed25519_node_keys) assert tx_vote.validate(b) - code, message = b.write_transaction(tx_vote, 'broadcast_tx_commit') + code, message = b.write_transaction(tx_vote, BROADCAST_TX_COMMIT) assert code == 202 resp = b.get_validators() diff --git a/tests/utils.py b/tests/utils.py index 2fb89892..6aba9941 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -11,6 +11,7 @@ from functools import singledispatch from bigchaindb.backend.localmongodb.connection import LocalMongoDBConnection from bigchaindb.backend.schema import TABLES from bigchaindb.common import crypto +from bigchaindb.common.transaction_mode_types import BROADCAST_TX_COMMIT from bigchaindb.elections.election import Election, Vote from bigchaindb.tendermint_utils import key_to_base64 @@ -36,7 +37,7 @@ def generate_block(bigchain): asset=None)\ .sign([alice.private_key]) - code, message = bigchain.write_transaction(tx, 'broadcast_tx_commit') + code, message = bigchain.write_transaction(tx, BROADCAST_TX_COMMIT) assert code == 202 diff --git a/tests/web/test_transactions.py b/tests/web/test_transactions.py index 68df7f8b..ccf9d27c 100644 --- a/tests/web/test_transactions.py +++ b/tests/web/test_transactions.py @@ -11,7 +11,9 @@ from cryptoconditions import Ed25519Sha256 from sha3 import sha3_256 from bigchaindb.common import crypto - +from bigchaindb.common.transaction_mode_types import (BROADCAST_TX_COMMIT, + BROADCAST_TX_ASYNC, + BROADCAST_TX_SYNC) TX_ENDPOINT = '/api/v1/transactions/' @@ -404,10 +406,10 @@ def test_transactions_get_list_bad(client): @patch('requests.post') @pytest.mark.parametrize('mode', [ - ('', 'broadcast_tx_async'), - ('?mode=async', 'broadcast_tx_async'), - ('?mode=sync', 'broadcast_tx_sync'), - ('?mode=commit', 'broadcast_tx_commit'), + ('', BROADCAST_TX_ASYNC), + ('?mode=async', BROADCAST_TX_ASYNC), + ('?mode=sync', BROADCAST_TX_SYNC), + ('?mode=commit', BROADCAST_TX_COMMIT), ]) def test_post_transaction_valid_modes(mock_post, client, mode): from bigchaindb.models import Transaction