From 920fe2bb203fe9dd4cd1bb1d209faa6a4b40245f Mon Sep 17 00:00:00 2001 From: z-bowen Date: Thu, 28 Jun 2018 12:01:03 +0200 Subject: [PATCH 01/11] Problem: core.py contains an unused class, `Bigchain` Solution: Remove core.py. Refactor BigchainDB Class to remove inheritance from Bigchain. --- bigchaindb/tendermint/lib.py | 128 ++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 3 deletions(-) diff --git a/bigchaindb/tendermint/lib.py b/bigchaindb/tendermint/lib.py index 9f13030e..ec61d535 100644 --- a/bigchaindb/tendermint/lib.py +++ b/bigchaindb/tendermint/lib.py @@ -16,8 +16,8 @@ except ImportError: import requests -from bigchaindb import backend -from bigchaindb import Bigchain +import bigchaindb +from bigchaindb import backend, config_utils from bigchaindb.models import Transaction from bigchaindb.common.exceptions import (SchemaValidationError, ValidationError, @@ -25,6 +25,7 @@ from bigchaindb.common.exceptions import (SchemaValidationError, from bigchaindb.tendermint.utils import encode_transaction, merkleroot from bigchaindb.tendermint import fastquery from bigchaindb import exceptions as core_exceptions +from bigchaindb.consensus import BaseConsensusRules logger = logging.getLogger(__name__) @@ -39,7 +40,52 @@ MODE_LIST = ('broadcast_tx_async', 'broadcast_tx_commit') -class BigchainDB(Bigchain): +class BigchainDB(object): + """Bigchain API + + Create, read, sign, write transactions to the database + """ + + BLOCK_INVALID = 'invalid' + """return if a block has been voted invalid""" + + BLOCK_VALID = TX_VALID = 'valid' + """return if a block is valid, or tx is in valid block""" + + BLOCK_UNDECIDED = TX_UNDECIDED = 'undecided' + """return if block is undecided, or tx is in undecided block""" + + TX_IN_BACKLOG = 'backlog' + """return if transaction is in backlog""" + + def __init__(self, connection=None): + """Initialize the Bigchain instance + + A Bigchain instance has several configuration parameters (e.g. host). + If a parameter value is passed as an argument to the Bigchain + __init__ method, then that is the value it will have. + Otherwise, the parameter value will come from an environment variable. + If that environment variable isn't set, then the value + will come from the local configuration file. And if that variable + isn't in the local configuration file, then the parameter will have + its default value (defined in bigchaindb.__init__). + + Args: + connection (:class:`~bigchaindb.backend.connection.Connection`): + A connection to the database. + """ + config_utils.autoconfigure() + + consensusPlugin = bigchaindb.config.get('consensus_plugin') + + if consensusPlugin: + self.consensus = config_utils.load_consensus_plugin(consensusPlugin) + else: + self.consensus = BaseConsensusRules + + self.connection = connection if connection else backend.connect(**bigchaindb.config['database']) + + def post_transaction(self, transaction, mode): """Submit a valid transaction to the mempool.""" @@ -236,6 +282,37 @@ class BigchainDB(Bigchain): else: return transaction + def get_transactions_filtered(self, asset_id, operation=None): + """Get a list of transactions filtered on some criteria + """ + txids = backend.query.get_txids_filtered(self.connection, asset_id, + operation) + for txid in txids: + tx, status = self.get_transaction(txid, True) + if status == self.TX_VALID: + yield tx + + def get_outputs_filtered(self, owner, spent=None): + """Get a list of output links filtered on some criteria + + Args: + owner (str): base58 encoded public_key. + spent (bool): If ``True`` return only the spent outputs. If + ``False`` return only unspent outputs. If spent is + not specified (``None``) return all outputs. + + Returns: + :obj:`list` of TransactionLink: list of ``txid`` s and ``output`` s + pointing to another transaction's condition + """ + outputs = self.fastquery.get_outputs_by_public_key(owner) + if spent is None: + return outputs + elif spent is True: + return self.fastquery.filter_unspent_outputs(outputs) + elif spent is False: + return self.fastquery.filter_spent_outputs(outputs) + def get_spent(self, txid, output, current_transactions=[]): transactions = backend.query.get_spent(self.connection, txid, output) @@ -342,6 +419,51 @@ class BigchainDB(Bigchain): logger.warning('Invalid transaction (%s): %s', type(e).__name__, e) return False + def text_search(self, search, *, limit=0, table='assets'): + """Return an iterator of assets that match the text search + + Args: + search (str): Text search string to query the text index + limit (int, optional): Limit the number of returned documents. + + Returns: + iter: An iterator of assets that match the text search. + """ + objects = backend.query.text_search(self.connection, search, limit=limit, + table=table) + + # TODO: This is not efficient. There may be a more efficient way to + # query by storing block ids with the assets and using fastquery. + # See https://github.com/bigchaindb/bigchaindb/issues/1496 + for obj in objects: + tx, status = self.get_transaction(obj['id'], True) + if status == self.TX_VALID: + yield obj + + def get_assets(self, asset_ids): + """Return a list of assets that match the asset_ids + + Args: + asset_ids (:obj:`list` of :obj:`str`): A list of asset_ids to + retrieve from the database. + + Returns: + list: The list of assets returned from the database. + """ + return backend.query.get_assets(self.connection, asset_ids) + + def get_metadata(self, txn_ids): + """Return a list of metadata that match the transaction ids (txn_ids) + + Args: + txn_ids (:obj:`list` of :obj:`str`): A list of txn_ids to + retrieve from the database. + + Returns: + list: The list of metadata returned from the database. + """ + return backend.query.get_metadata(self.connection, txn_ids) + @property def fastquery(self): return fastquery.FastQuery(self.connection) From e71fd5da9f0bc12077a3d5a43660f44fc9c9f44a Mon Sep 17 00:00:00 2001 From: z-bowen Date: Thu, 28 Jun 2018 12:01:43 +0200 Subject: [PATCH 02/11] Problem: core.py contains an unused class, `Bigchain` Solution: Remove core.py. Refactor BigchainDB Class to remove inheritance from Bigchain. --- bigchaindb/README.md | 4 +- bigchaindb/__init__.py | 2 +- bigchaindb/commands/bigchaindb.py | 4 +- bigchaindb/core.py | 442 ------------------ bigchaindb/models.py | 12 +- bigchaindb/web/server.py | 4 +- .../generate_http_server_api_documentation.py | 2 +- tests/commands/test_commands.py | 2 +- tests/db/test_bigchain_api.py | 24 +- tests/test_config_utils.py | 3 +- tests/test_core.py | 14 +- tests/test_voting.py | 6 +- tests/web/test_transactions.py | 14 +- 13 files changed, 46 insertions(+), 487 deletions(-) delete mode 100644 bigchaindb/core.py diff --git a/bigchaindb/README.md b/bigchaindb/README.md index 59fbe77c..dbb08afb 100644 --- a/bigchaindb/README.md +++ b/bigchaindb/README.md @@ -4,9 +4,9 @@ A high-level description of the files and subdirectories of BigchainDB. ## Files -### [`core.py`](./core.py) +### [`tendermint/lib.py`](./tendermint/lib.py) -The `Bigchain` class is defined here. Most node-level operations and database interactions are found in this file. This is the place to start if you are interested in implementing a server API, since many of these class methods concern BigchainDB interacting with the outside world. +The `BigchainDB` class is defined here. Most node-level operations and database interactions are found in this file. This is the place to start if you are interested in implementing a server API, since many of these class methods concern BigchainDB interacting with the outside world. ### [`models.py`](./models.py) diff --git a/bigchaindb/__init__.py b/bigchaindb/__init__.py index b90fcea0..b21f69fb 100644 --- a/bigchaindb/__init__.py +++ b/bigchaindb/__init__.py @@ -80,5 +80,5 @@ config = { # the user wants to reconfigure the node. Check ``bigchaindb.config_utils`` # for more info. _config = copy.deepcopy(config) -from bigchaindb.core import Bigchain # noqa +from bigchaindb.tendermint import BigchainDB # noqa from bigchaindb.version import __version__ # noqa diff --git a/bigchaindb/commands/bigchaindb.py b/bigchaindb/commands/bigchaindb.py index ad02d33e..871bf0de 100644 --- a/bigchaindb/commands/bigchaindb.py +++ b/bigchaindb/commands/bigchaindb.py @@ -94,7 +94,7 @@ def run_configure(args): def run_upsert_validator(args): """Store validators which should be synced with Tendermint""" - b = bigchaindb.Bigchain() + b = bigchaindb.tendermint.BigchainDB() public_key = public_key_from_base64(args.public_key) validator = {'pub_key': {'type': 'ed25519', 'data': public_key}, @@ -110,7 +110,7 @@ def run_upsert_validator(args): def _run_init(): - bdb = bigchaindb.Bigchain() + bdb = bigchaindb.tendermint.BigchainDB() schema.init_database(connection=bdb.connection) diff --git a/bigchaindb/core.py b/bigchaindb/core.py deleted file mode 100644 index a318b701..00000000 --- a/bigchaindb/core.py +++ /dev/null @@ -1,442 +0,0 @@ -from bigchaindb import exceptions as core_exceptions - -import bigchaindb - -from bigchaindb import backend, config_utils -from bigchaindb.consensus import BaseConsensusRules -from bigchaindb.models import Transaction - - -class Bigchain(object): - """Bigchain API - - Create, read, sign, write transactions to the database - """ - - BLOCK_INVALID = 'invalid' - """return if a block has been voted invalid""" - - BLOCK_VALID = TX_VALID = 'valid' - """return if a block is valid, or tx is in valid block""" - - BLOCK_UNDECIDED = TX_UNDECIDED = 'undecided' - """return if block is undecided, or tx is in undecided block""" - - TX_IN_BACKLOG = 'backlog' - """return if transaction is in backlog""" - - def __init__(self, connection=None): - """Initialize the Bigchain instance - - A Bigchain instance has several configuration parameters (e.g. host). - If a parameter value is passed as an argument to the Bigchain - __init__ method, then that is the value it will have. - Otherwise, the parameter value will come from an environment variable. - If that environment variable isn't set, then the value - will come from the local configuration file. And if that variable - isn't in the local configuration file, then the parameter will have - its default value (defined in bigchaindb.__init__). - - Args: - connection (:class:`~bigchaindb.backend.connection.Connection`): - A connection to the database. - """ - config_utils.autoconfigure() - - consensusPlugin = bigchaindb.config.get('consensus_plugin') - - if consensusPlugin: - self.consensus = config_utils.load_consensus_plugin(consensusPlugin) - else: - self.consensus = BaseConsensusRules - - self.connection = connection if connection else backend.connect(**bigchaindb.config['database']) - - def delete_transaction(self, *transaction_id): - """Delete a transaction from the backlog. - - Args: - *transaction_id (str): the transaction(s) to delete - - Returns: - The database response. - """ - - return backend.query.delete_transaction(self.connection, *transaction_id) - - def get_stale_transactions(self): - """Get a cursor of stale transactions. - - Transactions are considered stale if they have been assigned a node, but are still in the - backlog after some amount of time specified in the configuration - """ - - return backend.query.get_stale_transactions(self.connection) - - def validate_transaction(self, transaction): - """Validate a transaction. - - Args: - transaction (Transaction): transaction to validate. - - Returns: - The transaction if the transaction is valid else it raises an - exception describing the reason why the transaction is invalid. - """ - - return self.consensus.validate_transaction(self, transaction) - - def is_new_transaction(self, txid, exclude_block_id=None): - """Return True if the transaction does not exist in any - VALID or UNDECIDED block. Return False otherwise. - - Args: - txid (str): Transaction ID - exclude_block_id (str): Exclude block from search - """ - block_statuses = self.get_blocks_status_containing_tx(txid) - block_statuses.pop(exclude_block_id, None) - for status in block_statuses.values(): - if status != self.BLOCK_INVALID: - return False - return True - - def get_transaction(self, txid, include_status=False): - """Get the transaction with the specified `txid` (and optionally its status) - - This query begins by looking in the bigchain table for all blocks containing - a transaction with the specified `txid`. If one of those blocks is valid, it - returns the matching transaction from that block. Else if some of those - blocks are undecided, it returns a matching transaction from one of them. If - the transaction was found in invalid blocks only, or in no blocks, then this - query looks for a matching transaction in the backlog table, and if it finds - one there, it returns that. - - Args: - txid (str): transaction id of the transaction to get - include_status (bool): also return the status of the transaction - the return value is then a tuple: (tx, status) - - Returns: - A :class:`~.models.Transaction` instance if the transaction - was found in a valid block, an undecided block, or the backlog table, - otherwise ``None``. - If :attr:`include_status` is ``True``, also returns the - transaction's status if the transaction was found. - """ - - response, tx_status = None, None - - blocks_validity_status = self.get_blocks_status_containing_tx(txid) - check_backlog = True - - if blocks_validity_status: - # Disregard invalid blocks, and return if there are no valid or undecided blocks - blocks_validity_status = { - _id: status for _id, status in blocks_validity_status.items() - if status != Bigchain.BLOCK_INVALID - } - if blocks_validity_status: - - # The transaction _was_ found in an undecided or valid block, - # so there's no need to look in the backlog table - check_backlog = False - - tx_status = self.TX_UNDECIDED - # If the transaction is in a valid or any undecided block, return it. Does not check - # if transactions in undecided blocks are consistent, but selects the valid block - # before undecided ones - for target_block_id in blocks_validity_status: - if blocks_validity_status[target_block_id] == Bigchain.BLOCK_VALID: - tx_status = self.TX_VALID - break - - # Query the transaction in the target block and return - response = backend.query.get_transaction_from_block(self.connection, txid, target_block_id) - - if check_backlog: - response = backend.query.get_transaction_from_backlog(self.connection, txid) - - if response: - tx_status = self.TX_IN_BACKLOG - - if response: - if tx_status == self.TX_IN_BACKLOG: - response = Transaction.from_dict(response) - else: - # If we are reading from the bigchain collection the asset is - # not in the transaction so we need to fetch the asset and - # reconstruct the transaction. - response = Transaction.from_db(self, response) - - if include_status: - return response, tx_status - else: - return response - - def get_status(self, txid): - """Retrieve the status of a transaction with `txid` from bigchain. - - Args: - txid (str): transaction id of the transaction to query - - Returns: - (string): transaction status ('valid', 'undecided', - or 'backlog'). If no transaction with that `txid` was found it - returns `None` - """ - _, status = self.get_transaction(txid, include_status=True) - return status - - def get_blocks_status_containing_tx(self, txid): - """Retrieve block ids and statuses related to a transaction - - Transactions may occur in multiple blocks, but no more than one valid block. - - Args: - txid (str): transaction id of the transaction to query - - Returns: - A dict of blocks containing the transaction, - e.g. {block_id_1: 'valid', block_id_2: 'invalid' ...}, or None - """ - - # First, get information on all blocks which contain this transaction - blocks = backend.query.get_blocks_status_from_transaction(self.connection, txid) - if blocks: - # Determine the election status of each block - blocks_validity_status = { - block['id']: self.block_election_status(block) - for block in blocks - } - - # NOTE: If there are multiple valid blocks with this transaction, - # something has gone wrong - if list(blocks_validity_status.values()).count(Bigchain.BLOCK_VALID) > 1: - block_ids = str([ - block for block in blocks_validity_status - if blocks_validity_status[block] == Bigchain.BLOCK_VALID - ]) - raise core_exceptions.CriticalDoubleInclusion( - 'Transaction {tx} is present in ' - 'multiple valid blocks: {block_ids}' - .format(tx=txid, block_ids=block_ids)) - - return blocks_validity_status - - else: - return None - - def get_asset_by_id(self, asset_id): - """Returns the asset associated with an asset_id. - - Args: - asset_id (str): The asset id. - - Returns: - dict if the asset exists else None. - """ - cursor = backend.query.get_asset_by_id(self.connection, asset_id) - cursor = list(cursor) - if cursor: - return cursor[0]['asset'] - - def get_spent(self, txid, output): - """Check if a `txid` was already used as an input. - - A transaction can be used as an input for another transaction. Bigchain - needs to make sure that a given `(txid, output)` is only used once. - - This method will check if the `(txid, output)` has already been - spent in a transaction that is in either the `VALID`, `UNDECIDED` or - `BACKLOG` state. - - Args: - txid (str): The id of the transaction - output (num): the index of the output in the respective transaction - - Returns: - The transaction (Transaction) that used the `(txid, output)` as an - input else `None` - - Raises: - CriticalDoubleSpend: If the given `(txid, output)` was spent in - more than one valid transaction. - """ - # checks if an input was already spent - # checks if the bigchain has any transaction with input {'txid': ..., - # 'output': ...} - transactions = list(backend.query.get_spent(self.connection, txid, - output)) - - # a transaction_id should have been spent at most one time - # determine if these valid transactions appear in more than one valid - # block - num_valid_transactions = 0 - non_invalid_transactions = [] - for transaction in transactions: - # ignore transactions in invalid blocks - # FIXME: Isn't there a faster solution than doing I/O again? - txn, status = self.get_transaction(transaction['id'], - include_status=True) - if status == self.TX_VALID: - num_valid_transactions += 1 - # `txid` can only have been spent in at most on valid block. - if num_valid_transactions > 1: - raise core_exceptions.CriticalDoubleSpend( - '`{}` was spent more than once. There is a problem' - ' with the chain'.format(txid)) - # if its not and invalid transaction - if status is not None: - transaction.update({'metadata': txn.metadata}) - non_invalid_transactions.append(transaction) - - if non_invalid_transactions: - return Transaction.from_dict(non_invalid_transactions[0]) - - # Either no transaction was returned spending the `(txid, output)` as - # input or the returned transactions are not valid. - - def get_owned_ids(self, owner): - """Retrieve a list of ``txid`` s that can be used as inputs. - - Args: - owner (str): base58 encoded public key. - - Returns: - :obj:`list` of TransactionLink: list of ``txid`` s and ``output`` s - pointing to another transaction's condition - """ - return self.get_outputs_filtered(owner, spent=False) - - def get_outputs_filtered(self, owner, spent=None): - """Get a list of output links filtered on some criteria - - Args: - owner (str): base58 encoded public_key. - spent (bool): If ``True`` return only the spent outputs. If - ``False`` return only unspent outputs. If spent is - not specified (``None``) return all outputs. - - Returns: - :obj:`list` of TransactionLink: list of ``txid`` s and ``output`` s - pointing to another transaction's condition - """ - outputs = self.fastquery.get_outputs_by_public_key(owner) - if spent is None: - return outputs - elif spent is True: - return self.fastquery.filter_unspent_outputs(outputs) - elif spent is False: - return self.fastquery.filter_spent_outputs(outputs) - - def get_transactions_filtered(self, asset_id, operation=None): - """Get a list of transactions filtered on some criteria - """ - txids = backend.query.get_txids_filtered(self.connection, asset_id, - operation) - for txid in txids: - tx, status = self.get_transaction(txid, True) - if status == self.TX_VALID: - yield tx - - # TODO: check that the votings structure is correctly constructed - def validate_block(self, block): - """Validate a block. - - Args: - block (Block): block to validate. - - Returns: - The block if the block is valid else it raises and exception - describing the reason why the block is invalid. - """ - return self.consensus.validate_block(self, block) - - def write_block(self, block): - """Write a block to bigchain. - - Args: - block (Block): block to write to bigchain. - """ - - # Decouple assets from block - assets, block_dict = block.decouple_assets() - metadatas, block_dict = block.decouple_metadata(block_dict) - - # write the assets - if assets: - self.write_assets(assets) - - if metadatas: - self.write_metadata(metadatas) - - # write the block - return backend.query.write_block(self.connection, block_dict) - - def write_vote(self, vote): - """Write the vote to the database.""" - return backend.query.write_vote(self.connection, vote) - - def get_assets(self, asset_ids): - """Return a list of assets that match the asset_ids - - Args: - asset_ids (:obj:`list` of :obj:`str`): A list of asset_ids to - retrieve from the database. - - Returns: - list: The list of assets returned from the database. - """ - return backend.query.get_assets(self.connection, asset_ids) - - def get_metadata(self, txn_ids): - """Return a list of metadata that match the transaction ids (txn_ids) - - Args: - txn_ids (:obj:`list` of :obj:`str`): A list of txn_ids to - retrieve from the database. - - Returns: - list: The list of metadata returned from the database. - """ - return backend.query.get_metadata(self.connection, txn_ids) - - def write_assets(self, assets): - """Writes a list of assets into the database. - - Args: - assets (:obj:`list` of :obj:`dict`): A list of assets to write to - the database. - """ - return backend.query.write_assets(self.connection, assets) - - def write_metadata(self, metadata): - """Writes a list of metadata into the database. - - Args: - metadata (:obj:`list` of :obj:`dict`): A list of metadata to write to - the database. - """ - return backend.query.write_metadata(self.connection, metadata) - - def text_search(self, search, *, limit=0, table='assets'): - """Return an iterator of assets that match the text search - - Args: - search (str): Text search string to query the text index - limit (int, optional): Limit the number of returned documents. - - Returns: - iter: An iterator of assets that match the text search. - """ - objects = backend.query.text_search(self.connection, search, limit=limit, - table=table) - - # TODO: This is not efficient. There may be a more efficient way to - # query by storing block ids with the assets and using fastquery. - # See https://github.com/bigchaindb/bigchaindb/issues/1496 - for obj in objects: - tx, status = self.get_transaction(obj['id'], True) - if status == self.TX_VALID: - yield obj diff --git a/bigchaindb/models.py b/bigchaindb/models.py index a451c1da..f152f47b 100644 --- a/bigchaindb/models.py +++ b/bigchaindb/models.py @@ -208,8 +208,8 @@ class Block(object): """Validate the Block. Args: - bigchain (:class:`~bigchaindb.Bigchain`): An instantiated Bigchain - object. + bigchain (:class:`~bigchaindb.tendermint.BigchainDB`): An + instantiated BigchainDB object. Note: The hash of the block (`id`) is validated on the `self.from_dict` @@ -236,8 +236,8 @@ class Block(object): """Validate the Block without validating the transactions. Args: - bigchain (:class:`~bigchaindb.Bigchain`): An instantiated Bigchain - object. + bigchain (:class:`~bigchaindb.tendermint.BigchainDB`): An + instantiated BigchainDB object. Raises: ValidationError: If there is a problem with the block @@ -365,8 +365,8 @@ class Block(object): assets from the assets table and reconstructs the block. Args: - bigchain (:class:`~bigchaindb.Bigchain`): An instance of Bigchain - used to perform database queries. + bigchain (:class:`~bigchaindb.tendermint.BigchainDB`): An instance of + BigchainDB used to perform database queries. block_dict(:obj:`dict`): The block dict as returned from the database. from_dict_kwargs (:obj:`dict`): additional kwargs to pass to from_dict diff --git a/bigchaindb/web/server.py b/bigchaindb/web/server.py index 05d378b6..646f6f17 100644 --- a/bigchaindb/web/server.py +++ b/bigchaindb/web/server.py @@ -11,7 +11,7 @@ from flask_cors import CORS import gunicorn.app.base from bigchaindb import utils -from bigchaindb import Bigchain +from bigchaindb.tendermint import BigchainDB from bigchaindb.web.routes import add_routes from bigchaindb.web.strip_content_type_middleware import StripContentTypeMiddleware @@ -67,7 +67,7 @@ def create_app(*, debug=False, threads=1, bigchaindb_factory=None): """ if not bigchaindb_factory: - bigchaindb_factory = Bigchain + bigchaindb_factory = BigchainDB app = Flask(__name__) app.wsgi_app = StripContentTypeMiddleware(app.wsgi_app) diff --git a/docs/server/generate_http_server_api_documentation.py b/docs/server/generate_http_server_api_documentation.py index 31403da5..f2e2d502 100644 --- a/docs/server/generate_http_server_api_documentation.py +++ b/docs/server/generate_http_server_api_documentation.py @@ -5,7 +5,7 @@ import os import os.path from bigchaindb.common.transaction import Transaction, Input, TransactionLink -from bigchaindb.core import Bigchain +from bigchaindb.tendermint import BigchainDB from bigchaindb.models import Block from bigchaindb.tendermint import lib from bigchaindb.web import server diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 5ee502c6..17403e8c 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -90,7 +90,7 @@ def test_bigchain_run_init_when_db_exists(mocker, capsys): def test__run_init(mocker): from bigchaindb.commands.bigchaindb import _run_init bigchain_mock = mocker.patch( - 'bigchaindb.commands.bigchaindb.bigchaindb.Bigchain') + 'bigchaindb.commands.bigchaindb.bigchaindb.tendermint.BigchainDB') init_db_mock = mocker.patch( 'bigchaindb.commands.bigchaindb.schema.init_database', autospec=True, diff --git a/tests/db/test_bigchain_api.py b/tests/db/test_bigchain_api.py index bfa2c1b2..3b16cbf8 100644 --- a/tests/db/test_bigchain_api.py +++ b/tests/db/test_bigchain_api.py @@ -280,7 +280,7 @@ class TestBigchainApi(object): @pytest.mark.usefixtures('inputs') def test_write_transaction(self, b, user_pk, user_sk): - from bigchaindb import Bigchain + from bigchaindb.tendermint import BigchainDB from bigchaindb.models import Transaction input_tx = b.get_owned_ids(user_pk).pop() @@ -294,7 +294,7 @@ class TestBigchainApi(object): tx_from_db, status = b.get_transaction(tx.id, include_status=True) assert tx_from_db.to_dict() == tx.to_dict() - assert status == Bigchain.TX_IN_BACKLOG + assert status == BigchainDB.TX_IN_BACKLOG @pytest.mark.usefixtures('inputs') def test_read_transaction(self, b, user_pk, user_sk): @@ -450,7 +450,7 @@ class TestBigchainApi(object): from bigchaindb.common.exceptions import InputDoesNotExist from bigchaindb.common.transaction import Input, TransactionLink from bigchaindb.models import Transaction - from bigchaindb import Bigchain + from bigchaindb.tendermint import BigchainDB # Create an input for a non existing transaction input = Input(Ed25519Sha256(public_key=b58decode(user_pk)), @@ -460,7 +460,7 @@ class TestBigchainApi(object): asset_id='mock_asset_link') with pytest.raises(InputDoesNotExist): - tx.validate(Bigchain()) + tx.validate(BigchainDB()) def test_count_backlog(self, b, user_pk, alice): from bigchaindb.backend import query @@ -981,9 +981,9 @@ class TestMultipleInputs(object): def test_get_owned_ids_calls_get_outputs_filtered(): - from bigchaindb.core import Bigchain + from bigchaindb.tendermint import BigchainDB with patch('bigchaindb.core.Bigchain.get_outputs_filtered') as gof: - b = Bigchain() + b = BigchainDB() res = b.get_owned_ids('abc') gof.assert_called_once_with('abc', spent=False) assert res == gof() @@ -991,26 +991,26 @@ def test_get_owned_ids_calls_get_outputs_filtered(): def test_get_outputs_filtered_only_unspent(): from bigchaindb.common.transaction import TransactionLink - from bigchaindb.core import Bigchain + from bigchaindb.tendermint import BigchainDB with patch('bigchaindb.fastquery.FastQuery.get_outputs_by_public_key') as get_outputs: get_outputs.return_value = [TransactionLink('a', 1), TransactionLink('b', 2)] with patch('bigchaindb.fastquery.FastQuery.filter_spent_outputs') as filter_spent: filter_spent.return_value = [TransactionLink('b', 2)] - out = Bigchain().get_outputs_filtered('abc', spent=False) + out = BigchainDB().get_outputs_filtered('abc', spent=False) get_outputs.assert_called_once_with('abc') assert out == [TransactionLink('b', 2)] def test_get_outputs_filtered_only_spent(): from bigchaindb.common.transaction import TransactionLink - from bigchaindb.core import Bigchain + from bigchaindb.tendermint import BigchainDB with patch('bigchaindb.fastquery.FastQuery.get_outputs_by_public_key') as get_outputs: get_outputs.return_value = [TransactionLink('a', 1), TransactionLink('b', 2)] with patch('bigchaindb.fastquery.FastQuery.filter_unspent_outputs') as filter_spent: filter_spent.return_value = [TransactionLink('b', 2)] - out = Bigchain().get_outputs_filtered('abc', spent=True) + out = BigchainDB().get_outputs_filtered('abc', spent=True) get_outputs.assert_called_once_with('abc') assert out == [TransactionLink('b', 2)] @@ -1019,11 +1019,11 @@ def test_get_outputs_filtered_only_spent(): @patch('bigchaindb.fastquery.FastQuery.filter_spent_outputs') def test_get_outputs_filtered(filter_spent, filter_unspent): from bigchaindb.common.transaction import TransactionLink - from bigchaindb.core import Bigchain + from bigchaindb.tendermint import BigchainDB with patch('bigchaindb.fastquery.FastQuery.get_outputs_by_public_key') as get_outputs: get_outputs.return_value = [TransactionLink('a', 1), TransactionLink('b', 2)] - out = Bigchain().get_outputs_filtered('abc') + out = BigchainDB().get_outputs_filtered('abc') get_outputs.assert_called_once_with('abc') filter_spent.assert_not_called() filter_unspent.assert_not_called() diff --git a/tests/test_config_utils.py b/tests/test_config_utils.py index a96e1405..30dcfd60 100644 --- a/tests/test_config_utils.py +++ b/tests/test_config_utils.py @@ -35,6 +35,7 @@ def test_bigchain_instance_raises_when_not_configured(request, monkeypatch): import bigchaindb from bigchaindb import config_utils from bigchaindb.common import exceptions + from bigchaindb.tendermint import BigchainDB assert 'CONFIGURED' not in bigchaindb.config # We need to disable ``bigchaindb.config_utils.autoconfigure`` to avoid reading @@ -42,7 +43,7 @@ def test_bigchain_instance_raises_when_not_configured(request, monkeypatch): monkeypatch.setattr(config_utils, 'autoconfigure', lambda: 0) with pytest.raises(exceptions.ConfigurationError): - bigchaindb.Bigchain() + BigchainDB() def test_load_consensus_plugin_loads_default_rules_without_name(): diff --git a/tests/test_core.py b/tests/test_core.py index b563c385..9f6150e6 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -26,10 +26,10 @@ def config(request, monkeypatch): def test_bigchain_class_default_initialization(config): - from bigchaindb.core import Bigchain + from bigchaindb.tendermint import BigchainDB from bigchaindb.consensus import BaseConsensusRules from bigchaindb.backend.connection import Connection - bigchain = Bigchain() + bigchain = BigchainDB() assert isinstance(bigchain.connection, Connection) assert bigchain.connection.host == config['database']['host'] assert bigchain.connection.port == config['database']['port'] @@ -38,7 +38,7 @@ def test_bigchain_class_default_initialization(config): def test_bigchain_class_initialization_with_parameters(config): - from bigchaindb.core import Bigchain + from bigchaindb.tendermint import BigchainDB from bigchaindb.backend import connect from bigchaindb.consensus import BaseConsensusRules init_db_kwargs = { @@ -48,7 +48,7 @@ def test_bigchain_class_initialization_with_parameters(config): 'name': 'this_is_the_db_name', } connection = connect(**init_db_kwargs) - bigchain = Bigchain(connection=connection, **init_db_kwargs) + bigchain = BigchainDB(connection=connection, **init_db_kwargs) assert bigchain.connection == connection assert bigchain.connection.host == init_db_kwargs['host'] assert bigchain.connection.port == init_db_kwargs['port'] @@ -58,13 +58,13 @@ def test_bigchain_class_initialization_with_parameters(config): def test_get_blocks_status_containing_tx(monkeypatch): from bigchaindb.backend import query as backend_query - from bigchaindb.core import Bigchain + from bigchaindb.tendermint import BigchainDB blocks = [ {'id': 1}, {'id': 2} ] monkeypatch.setattr(backend_query, 'get_blocks_status_from_transaction', lambda x: blocks) - monkeypatch.setattr(Bigchain, 'block_election_status', lambda x, y, z: Bigchain.BLOCK_VALID) - bigchain = Bigchain(public_key='pubkey', private_key='privkey') + monkeypatch.setattr(BigchainDB, 'block_election_status', lambda x, y, z: BigchainDB.BLOCK_VALID) + bigchain = BigchainDB(public_key='pubkey', private_key='privkey') with pytest.raises(Exception): bigchain.get_blocks_status_containing_tx('txid') diff --git a/tests/test_voting.py b/tests/test_voting.py index 19bee4bb..51d36a44 100644 --- a/tests/test_voting.py +++ b/tests/test_voting.py @@ -1,6 +1,6 @@ import pytest -from bigchaindb.core import Bigchain +from bigchaindb.tendermint import BigchainDB from bigchaindb.voting import Voting, INVALID, VALID, UNDECIDED @@ -39,7 +39,7 @@ def test_count_votes(): voters = (['says invalid', 'malformed'] + ['kosher' + str(i) for i in range(10)]) - votes = [Bigchain(v).vote('block', 'a', True) for v in voters] + votes = [BigchainDB(v).vote('block', 'a', True) for v in voters] votes[0]['vote']['is_block_valid'] = False # Incorrect previous block subtracts from n_valid and adds to n_invalid votes[-1]['vote']['previous_block'] = 'z' @@ -64,7 +64,7 @@ def test_must_agree_prev_block(): return True voters = 'abcd' - votes = [Bigchain(v).vote('block', 'a', True) for v in voters] + votes = [BigchainDB(v).vote('block', 'a', True) for v in voters] votes[0]['vote']['previous_block'] = 'b' votes[1]['vote']['previous_block'] = 'c' by_voter = dict(enumerate(votes)) diff --git a/tests/web/test_transactions.py b/tests/web/test_transactions.py index c81a9db8..7c52ea94 100644 --- a/tests/web/test_transactions.py +++ b/tests/web/test_transactions.py @@ -372,7 +372,7 @@ def test_transactions_get_list_good(client): asset_id = '1' * 64 - with patch('bigchaindb.core.Bigchain.get_transactions_filtered', get_txs_patched): + with patch('bigchaindb.tendermint.BigchainDB.get_transactions_filtered', get_txs_patched): url = TX_ENDPOINT + '?asset_id=' + asset_id assert client.get(url).json == [ ['asset_id', asset_id], @@ -389,7 +389,7 @@ def test_transactions_get_list_good(client): def test_transactions_get_list_bad(client): def should_not_be_called(): assert False - with patch('bigchaindb.core.Bigchain.get_transactions_filtered', + with patch('bigchaindb.tendermint.BigchainDB.get_transactions_filtered', lambda *_, **__: should_not_be_called()): # Test asset id validated url = TX_ENDPOINT + '?asset_id=' + '1' * 63 @@ -404,7 +404,7 @@ def test_transactions_get_list_bad(client): @pytest.mark.tendermint def test_return_only_valid_transaction(client): - from bigchaindb import Bigchain + from bigchaindb.tendermint import BigchainDB def get_transaction_patched(status): def inner(self, tx_id, include_status): @@ -415,13 +415,13 @@ def test_return_only_valid_transaction(client): # UNDECIDED or VALID block, as well as transactions from the backlog. # As the endpoint uses `get_transaction`, we don't have to test # against invalid transactions here. - with patch('bigchaindb.core.Bigchain.get_transaction', - get_transaction_patched(Bigchain.TX_UNDECIDED)): + with patch('bigchaindb.tendermint.BigchainDB.get_transaction', + get_transaction_patched(BigchainDB.TX_UNDECIDED)): url = '{}{}'.format(TX_ENDPOINT, '123') assert client.get(url).status_code == 404 - with patch('bigchaindb.core.Bigchain.get_transaction', - get_transaction_patched(Bigchain.TX_IN_BACKLOG)): + with patch('bigchaindb.tendermint.BigchainDB.get_transaction', + get_transaction_patched(BigchainDB.TX_IN_BACKLOG)): url = '{}{}'.format(TX_ENDPOINT, '123') assert client.get(url).status_code == 404 From a3b9bb62f97b45aeb359727a143ac524b71c2557 Mon Sep 17 00:00:00 2001 From: z-bowen Date: Thu, 28 Jun 2018 15:52:17 +0200 Subject: [PATCH 03/11] Fixed flake8 complaint about too many blank lines --- bigchaindb/tendermint/lib.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/bigchaindb/tendermint/lib.py b/bigchaindb/tendermint/lib.py index ec61d535..ffff7667 100644 --- a/bigchaindb/tendermint/lib.py +++ b/bigchaindb/tendermint/lib.py @@ -85,12 +85,10 @@ class BigchainDB(object): self.connection = connection if connection else backend.connect(**bigchaindb.config['database']) - - def post_transaction(self, transaction, mode): """Submit a valid transaction to the mempool.""" if not mode or mode not in MODE_LIST: - raise ValidationError(('Mode must be one of the following {}.') + raise ValidationError('Mode must be one of the following {}.' .format(', '.join(MODE_LIST))) payload = { @@ -108,7 +106,7 @@ class BigchainDB(object): response = self.post_transaction(transaction, mode) return self._process_post_response(response.json(), mode) - def _process_post_response(self, response, mode): + def process_post_response(self, response, mode): logger.debug(response) if response.get('error') is not None: return (500, 'Internal error') @@ -131,7 +129,7 @@ class BigchainDB(object): # else: # return (500, 'Error while validating the transaction') - def _process_status_code(self, status_code, failure_msg): + def process_status_code(self, status_code, failure_msg): return (202, '') if status_code == 0 else (500, failure_msg) def store_transaction(self, transaction): From 80c90c7b4f97c7af46e78909a6add67568a3e7b3 Mon Sep 17 00:00:00 2001 From: z-bowen Date: Thu, 28 Jun 2018 17:39:33 +0200 Subject: [PATCH 04/11] Attempting to fix Sphinx docs. This may result in some redundant commits, as I don't know what I'm doing, and I can't experiment without running the CI... Sorry in advance! --- docs/server/source/appendices/tendermint-integration.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/server/source/appendices/tendermint-integration.rst b/docs/server/source/appendices/tendermint-integration.rst index 175cbe80..bc800400 100644 --- a/docs/server/source/appendices/tendermint-integration.rst +++ b/docs/server/source/appendices/tendermint-integration.rst @@ -8,6 +8,7 @@ Tendermint Integration .. automodule:: bigchaindb.tendermint.lib :special-members: __init__ + :noindex: .. automodule:: bigchaindb.tendermint.core :special-members: __init__ From 8176fc6e8bf4055ce89291d5f5ee1563f5798a7a Mon Sep 17 00:00:00 2001 From: z-bowen Date: Thu, 28 Jun 2018 17:49:44 +0200 Subject: [PATCH 05/11] Attempting to fix Sphinx docs. This may result in some redundant commits, as I don't know what I'm doing, and I can't experiment without running the CI... Sorry in advance! --- docs/server/source/appendices/tendermint-integration.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/server/source/appendices/tendermint-integration.rst b/docs/server/source/appendices/tendermint-integration.rst index 175cbe80..bc800400 100644 --- a/docs/server/source/appendices/tendermint-integration.rst +++ b/docs/server/source/appendices/tendermint-integration.rst @@ -8,6 +8,7 @@ Tendermint Integration .. automodule:: bigchaindb.tendermint.lib :special-members: __init__ + :noindex: .. automodule:: bigchaindb.tendermint.core :special-members: __init__ From f42c6ad2b5dbed775a3685e20fd906a3ea43b580 Mon Sep 17 00:00:00 2001 From: z-bowen Date: Fri, 29 Jun 2018 12:04:36 +0200 Subject: [PATCH 06/11] Updating from master changed BigchainDB.process_post_response to a private method, so I had to align with that. --- bigchaindb/tendermint/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bigchaindb/tendermint/lib.py b/bigchaindb/tendermint/lib.py index ffff7667..f3cc6b08 100644 --- a/bigchaindb/tendermint/lib.py +++ b/bigchaindb/tendermint/lib.py @@ -106,7 +106,7 @@ class BigchainDB(object): response = self.post_transaction(transaction, mode) return self._process_post_response(response.json(), mode) - def process_post_response(self, response, mode): + def _process_post_response(self, response, mode): logger.debug(response) if response.get('error') is not None: return (500, 'Internal error') From 8f189489cea1c328cdfeb1e314343728ea97cd3d Mon Sep 17 00:00:00 2001 From: z-bowen Date: Fri, 29 Jun 2018 13:57:40 +0200 Subject: [PATCH 07/11] Fixed a couple stale references to bigchaindb.Bigchain in docstrings --- bigchaindb/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bigchaindb/models.py b/bigchaindb/models.py index e58dd6f8..4f72139f 100644 --- a/bigchaindb/models.py +++ b/bigchaindb/models.py @@ -18,7 +18,7 @@ class Transaction(Transaction): """Validate transaction spend Args: - bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. + bigchain (BigchainDB): an instantiated bigchaindb.tendermint.BigchainDB object. Returns: The transaction (Transaction) if the transaction is valid else it @@ -112,8 +112,8 @@ class Transaction(Transaction): asset from the asset table and reconstructs the transaction. Args: - bigchain (:class:`~bigchaindb.Bigchain`): An instance of Bigchain - used to perform database queries. + bigchain (:class:`~bigchaindb.tendermint.BigchainDB`): An instance + of BigchainDB used to perform database queries. tx_dict_list (:list:`dict` or :obj:`dict`): The transaction dict or list of transaction dict as returned from the database. From 5dbe4e4f8ed388417420f59cfc471a36dce3dcdb Mon Sep 17 00:00:00 2001 From: z-bowen Date: Fri, 29 Jun 2018 15:08:46 +0200 Subject: [PATCH 08/11] Missed a reference to `Bigchain` in a patch call... --- tests/db/test_bigchain_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/db/test_bigchain_api.py b/tests/db/test_bigchain_api.py index 3b16cbf8..0cf0b9d9 100644 --- a/tests/db/test_bigchain_api.py +++ b/tests/db/test_bigchain_api.py @@ -982,7 +982,7 @@ class TestMultipleInputs(object): def test_get_owned_ids_calls_get_outputs_filtered(): from bigchaindb.tendermint import BigchainDB - with patch('bigchaindb.core.Bigchain.get_outputs_filtered') as gof: + with patch('bigchaindb.tendermint.BigchainDB.get_outputs_filtered') as gof: b = BigchainDB() res = b.get_owned_ids('abc') gof.assert_called_once_with('abc', spent=False) From d521a00925819fb560fd0a0e39d98f5c521d6ed9 Mon Sep 17 00:00:00 2001 From: codegeschrei Date: Wed, 18 Jul 2018 10:52:33 +0200 Subject: [PATCH 09/11] Problem: a valid transaction is detected as double spend (#2389) Solution: query the wanted data per input --- bigchaindb/backend/localmongodb/query.py | 8 +++++--- tests/test_core.py | 20 ++++++++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/bigchaindb/backend/localmongodb/query.py b/bigchaindb/backend/localmongodb/query.py index 6aca2197..b2b381c4 100644 --- a/bigchaindb/backend/localmongodb/query.py +++ b/bigchaindb/backend/localmongodb/query.py @@ -99,11 +99,13 @@ def get_assets(conn, asset_ids): @register_query(LocalMongoDBConnection) def get_spent(conn, transaction_id, output): + query = {'inputs.fulfills': { + 'transaction_id': transaction_id, + 'output_index': output}} + return conn.run( conn.collection('transactions') - .find({'inputs.fulfills.transaction_id': transaction_id, - 'inputs.fulfills.output_index': output}, - {'_id': 0})) + .find(query, {'_id': 0})) @register_query(LocalMongoDBConnection) diff --git a/tests/test_core.py b/tests/test_core.py index 9f6150e6..5f89baa1 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1,6 +1,10 @@ import pytest +pytestmark = pytest.mark.tendermint + + +@pytest.mark.skipif(reason='will be fixed in another PR') @pytest.fixture def config(request, monkeypatch): backend = request.config.getoption('--database-backend') @@ -25,6 +29,7 @@ def config(request, monkeypatch): return config +@pytest.mark.skipif(reason='will be fixed in another PR') def test_bigchain_class_default_initialization(config): from bigchaindb.tendermint import BigchainDB from bigchaindb.consensus import BaseConsensusRules @@ -37,6 +42,7 @@ def test_bigchain_class_default_initialization(config): assert bigchain.consensus == BaseConsensusRules +@pytest.mark.skipif(reason='will be fixed in another PR') def test_bigchain_class_initialization_with_parameters(config): from bigchaindb.tendermint import BigchainDB from bigchaindb.backend import connect @@ -56,6 +62,7 @@ def test_bigchain_class_initialization_with_parameters(config): assert bigchain.consensus == BaseConsensusRules +@pytest.mark.skipif(reason='will be fixed in another PR') def test_get_blocks_status_containing_tx(monkeypatch): from bigchaindb.backend import query as backend_query from bigchaindb.tendermint import BigchainDB @@ -77,6 +84,8 @@ def test_get_spent_issue_1271(b, alice, bob, carol): [carol.public_key], [([carol.public_key], 8)], ).sign([carol.private_key]) + assert b.validate_transaction(tx_1) + b.store_bulk_transactions([tx_1]) tx_2 = Transaction.transfer( tx_1.to_inputs(), @@ -85,6 +94,8 @@ def test_get_spent_issue_1271(b, alice, bob, carol): ([carol.public_key], 4)], asset_id=tx_1.id, ).sign([carol.private_key]) + assert b.validate_transaction(tx_2) + b.store_bulk_transactions([tx_2]) tx_3 = Transaction.transfer( tx_2.to_inputs()[2:3], @@ -92,20 +103,25 @@ def test_get_spent_issue_1271(b, alice, bob, carol): ([carol.public_key], 3)], asset_id=tx_1.id, ).sign([carol.private_key]) + assert b.validate_transaction(tx_3) + b.store_bulk_transactions([tx_3]) tx_4 = Transaction.transfer( tx_2.to_inputs()[1:2] + tx_3.to_inputs()[0:1], [([bob.public_key], 3)], asset_id=tx_1.id, ).sign([alice.private_key]) + assert b.validate_transaction(tx_4) + b.store_bulk_transactions([tx_4]) tx_5 = Transaction.transfer( tx_2.to_inputs()[0:1], [([alice.public_key], 2)], asset_id=tx_1.id, ).sign([bob.private_key]) - block_5 = b.create_block([tx_1, tx_2, tx_3, tx_4, tx_5]) - b.write_block(block_5) + assert b.validate_transaction(tx_5) + b.store_bulk_transactions([tx_5]) + assert b.get_spent(tx_2.id, 0) == tx_5 assert not b.get_spent(tx_5.id, 0) assert b.get_outputs_filtered(alice.public_key) From abc6db7999d41e68ffa317e8214f94b0d3a85ba7 Mon Sep 17 00:00:00 2001 From: Troy McConaghy Date: Wed, 18 Jul 2018 15:20:13 +0200 Subject: [PATCH 10/11] Last PR before the release of BigchainDB 2.0 Beta 3 (#2391) * Update CHANGELOG.md for 2.0 Beta 3 release * Update docs re/ installation for 2.0.0b3 * Update version.py and k8s files for 2.0.0b3 --- CHANGELOG.md | 8 ++++++++ bigchaindb/version.py | 4 ++-- docs/server/source/simple-network-setup.md | 5 +++-- k8s/bigchaindb/bigchaindb-ss.yaml | 2 +- k8s/dev-setup/bigchaindb.yaml | 2 +- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bffdd155..e89ccc85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,14 @@ For reference, the possible headings are: * **Known Issues** * **Notes** +## [2.0 Beta 3] - 2018-07-18 + +Tag name: v2.0.0b3 + +### Fixed + +Fixed a bug in transaction validation. For some more-complex situations, it would say that a valid transaction was invalid. This bug was actually fixed before; it was [issue #1271](https://github.com/bigchaindb/bigchaindb/issues/1271). The unit test for it was turned off while we integrated Tendermint. Then the query implementation code got changed, reintroducing the bug, but the unit test was off so the bug wasn't caught. When we turned the test back on, shortly after releasing Beta 2, it failed, unveiling the bug. [Pull request #2389](https://github.com/bigchaindb/bigchaindb/pull/2389) + ## [2.0 Beta 2] - 2018-07-16 Tag name: v2.0.0b2 diff --git a/bigchaindb/version.py b/bigchaindb/version.py index edc112cd..72f9eecf 100644 --- a/bigchaindb/version.py +++ b/bigchaindb/version.py @@ -1,2 +1,2 @@ -__version__ = '2.0.0b2' -__short_version__ = '2.0b2' +__version__ = '2.0.0b3' +__short_version__ = '2.0b3' diff --git a/docs/server/source/simple-network-setup.md b/docs/server/source/simple-network-setup.md index 165cf006..752b39ba 100644 --- a/docs/server/source/simple-network-setup.md +++ b/docs/server/source/simple-network-setup.md @@ -52,10 +52,11 @@ BigchainDB Server requires **Python 3.6+**, so make sure your system has it. Ins sudo apt install -y python3-pip libssl-dev ``` -Now install the latest version of BigchainDB. Check the [project page on PyPI][bdb:pypi] for the last version (which was `2.0.0a6` at the time of writing) and install it: +Now install the latest version of BigchainDB. You can find the latest version by going to the [BigchainDB project release history page on PyPI][bdb:pypi]. For example, to install version 2.0.0b3, you would do: ``` -sudo pip3 install bigchaindb==2.0.0a6 +# Change 2.0.0b3 to the latest version as explained above: +sudo pip3 install bigchaindb==2.0.0b3 ``` Check that you installed the correct version of BigchainDB Server using `bigchaindb --version`. diff --git a/k8s/bigchaindb/bigchaindb-ss.yaml b/k8s/bigchaindb/bigchaindb-ss.yaml index 636da377..027c3fed 100644 --- a/k8s/bigchaindb/bigchaindb-ss.yaml +++ b/k8s/bigchaindb/bigchaindb-ss.yaml @@ -154,7 +154,7 @@ spec: timeoutSeconds: 15 # BigchainDB container - name: bigchaindb - image: bigchaindb/bigchaindb:2.0.0-beta2 + image: bigchaindb/bigchaindb:2.0.0-beta3 imagePullPolicy: Always args: - start diff --git a/k8s/dev-setup/bigchaindb.yaml b/k8s/dev-setup/bigchaindb.yaml index e8db3042..d62685fc 100644 --- a/k8s/dev-setup/bigchaindb.yaml +++ b/k8s/dev-setup/bigchaindb.yaml @@ -34,7 +34,7 @@ spec: terminationGracePeriodSeconds: 10 containers: - name: bigchaindb - image: bigchaindb/bigchaindb:2.0.0-beta2 + image: bigchaindb/bigchaindb:2.0.0-beta3 imagePullPolicy: Always args: - start From e681427b757754252fec441e0530940d1f29fb7b Mon Sep 17 00:00:00 2001 From: Troy McConaghy Date: Mon, 23 Jul 2018 10:42:36 +0200 Subject: [PATCH 11/11] Problem: The write-a-bep page/process is daunting (#2347) * Problem: The write-a-bep page/process is daunting Solution: Make the BEP writing process easier and more approachable * Problem: BEP should be written uppercase Solution: Change bigchaindb/BEPs label names to use uppercase "BEP" --- .../source/ways-to-contribute/write-a-bep.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/docs/contributing/source/ways-to-contribute/write-a-bep.md b/docs/contributing/source/ways-to-contribute/write-a-bep.md index 182f850c..9bb5e8f4 100644 --- a/docs/contributing/source/ways-to-contribute/write-a-bep.md +++ b/docs/contributing/source/ways-to-contribute/write-a-bep.md @@ -1,7 +1,14 @@ -# Write a BigchaindB Enhancement Proposal (BEP) +# Write a BigchainDB Enhancement Proposal (BEP) -- Review [1/C4](https://github.com/bigchaindb/BEPs/tree/master/1), the process we use to accept any new code or PR of any kind, including one that adds a BEP to `bigchaindb/BEPs`. -- Review [2/COSS](https://github.com/bigchaindb/BEPs/tree/master/2). Maybe print it for reference. It outlines what can go in a BEP. -- Don't spend weeks on your BEP. Version 1 should take up to a few hours to write. You can add to it in the future. The process is iterative. If you need more than a few hours, then consider writing multiple BEPs. -- Do _not_ start writing code before you think about it. You should always write a BEP first. Once you do that, you can start implementing it. To do that, make a pull request and say it implements your BEP. -- Do _not_ write your BEP as an issue (i.e. a GitHub issue). +If you have an idea for a new feature or enhancement, and you want some feedback before you write a full BigchainDB Enhancement Proposal (BEP), then feel free to: + - ask in the [bigchaindb/bigchaindb Gitter chat room](https://gitter.im/bigchaindb/bigchaindb) or + - [open a new issue in the bigchaindb/BEPs repo](https://github.com/bigchaindb/BEPs/issues/new) and give it the label **BEP idea**. + +If you want to discuss an existing BEP, then [open a new issue in the bigchaindb/BEPs repo](https://github.com/bigchaindb/BEPs/issues/new) and give it the label **discuss existing BEP**. + +## Steps to Write a New BEP + +1. Look at the structure of existing BEPs in the [bigchaindb/BEPs repo](https://github.com/bigchaindb/BEPs). Note the section headings. [BEP-2](https://github.com/bigchaindb/BEPs/tree/master/2) (our variant of the consensus-oriented specification system [COSS]) says more about the expected structure and process. +1. Write a first draft of your BEP. It doesn't have to be long or perfect. +1. Push your BEP draft to the [bigchaindb/BEPs repo](https://github.com/bigchaindb/BEPs) and make a pull request. [BEP-1](https://github.com/bigchaindb/BEPs/tree/master/1) (our variant of C4) outlines the process we use to handle all pull requests. In particular, we try to merge all pull requests quickly. +1. Your BEP can be revised by pushing more pull requests.