From e8e02cac5075b494eb6931f8c90bc43cf8cc0192 Mon Sep 17 00:00:00 2001 From: Shahbaz Nazir Date: Fri, 16 Mar 2018 16:19:12 +0100 Subject: [PATCH] Problem: Bigchaindb startup sometimes fails due genesis block creation during init (#2129) * removing GENESIS transaction type * remove GENESIS transaction schema * all blocks are same in the eyes of GOD no checks needed for genesis blocks --- bigchaindb/commands/bigchaindb.py | 7 ++----- .../schema/transaction_create_v2.0.yaml | 2 +- .../common/schema/transaction_v2.0.yaml | 1 - bigchaindb/common/transaction.py | 21 +++++++++---------- bigchaindb/models.py | 11 ++++------ bigchaindb/utils.py | 19 ----------------- tests/commands/test_commands.py | 1 - tests/test_utils.py | 6 ------ 8 files changed, 17 insertions(+), 51 deletions(-) diff --git a/bigchaindb/commands/bigchaindb.py b/bigchaindb/commands/bigchaindb.py index fa5bd1a7..92dce33d 100644 --- a/bigchaindb/commands/bigchaindb.py +++ b/bigchaindb/commands/bigchaindb.py @@ -93,12 +93,9 @@ def run_configure(args): def _run_init(): - b = bigchaindb.Bigchain() + bdb = bigchaindb.Bigchain() - schema.init_database(connection=b.connection) - - b.create_genesis_block() - logger.info('Genesis block created.') + schema.init_database(connection=bdb.connection) @configure_bigchaindb diff --git a/bigchaindb/common/schema/transaction_create_v2.0.yaml b/bigchaindb/common/schema/transaction_create_v2.0.yaml index 3d393347..ed018ea5 100644 --- a/bigchaindb/common/schema/transaction_create_v2.0.yaml +++ b/bigchaindb/common/schema/transaction_create_v2.0.yaml @@ -1,7 +1,7 @@ --- "$schema": "http://json-schema.org/draft-04/schema#" type: object -title: Transaction Schema - CREATE/GENESIS specific constraints +title: Transaction Schema - CREATE specific constraints required: - asset - inputs diff --git a/bigchaindb/common/schema/transaction_v2.0.yaml b/bigchaindb/common/schema/transaction_v2.0.yaml index 16cafd33..0a22b810 100644 --- a/bigchaindb/common/schema/transaction_v2.0.yaml +++ b/bigchaindb/common/schema/transaction_v2.0.yaml @@ -58,7 +58,6 @@ definitions: enum: - CREATE - TRANSFER - - GENESIS asset: type: object additionalProperties: false diff --git a/bigchaindb/common/transaction.py b/bigchaindb/common/transaction.py index 6ba7ab80..59c58264 100644 --- a/bigchaindb/common/transaction.py +++ b/bigchaindb/common/transaction.py @@ -480,8 +480,8 @@ class Transaction(object): spend. outputs (:obj:`list` of :class:`~bigchaindb.common. transaction.Output`, optional): Define the assets to lock. - asset (dict): Asset payload for this Transaction. ``CREATE`` and - ``GENESIS`` Transactions require a dict with a ``data`` + asset (dict): Asset payload for this Transaction. ``CREATE`` + Transactions require a dict with a ``data`` property while ``TRANSFER`` Transactions require a dict with a ``id`` property. metadata (dict): @@ -491,8 +491,7 @@ class Transaction(object): CREATE = 'CREATE' TRANSFER = 'TRANSFER' - GENESIS = 'GENESIS' - ALLOWED_OPERATIONS = (CREATE, TRANSFER, GENESIS) + ALLOWED_OPERATIONS = (CREATE, TRANSFER) VERSION = '2.0' def __init__(self, operation, asset, inputs=None, outputs=None, @@ -521,10 +520,10 @@ class Transaction(object): raise ValueError('`operation` must be one of {}' .format(allowed_ops)) - # Asset payloads for 'CREATE' and 'GENESIS' operations must be None or + # Asset payloads for 'CREATE' operations must be None or # dicts holding a `data` property. Asset payloads for 'TRANSFER' # operations must be dicts holding an `id` property. - if (operation in [Transaction.CREATE, Transaction.GENESIS] and + if (operation == Transaction.CREATE and asset is not None and not (isinstance(asset, dict) and 'data' in asset)): raise TypeError(('`asset` must be None or a dict holding a `data` ' " property instance for '{}' Transactions".format(operation))) @@ -928,7 +927,7 @@ class Transaction(object): Outputs. Note: - Given a `CREATE` or `GENESIS` Transaction is passed, + Given a `CREATE` Transaction is passed, dummy values for Outputs are submitted for validation that evaluate parts of the validation-checks to `True`. @@ -940,7 +939,7 @@ class Transaction(object): Returns: bool: If all Inputs are valid. """ - if self.operation in (Transaction.CREATE, Transaction.GENESIS): + if self.operation == Transaction.CREATE: # NOTE: Since in the case of a `CREATE`-transaction we do not have # to check for outputs, we're just submitting dummy # values to the actual method. This simplifies it's logic @@ -992,7 +991,7 @@ class Transaction(object): """Validates a single Input against a single Output. Note: - In case of a `CREATE` or `GENESIS` Transaction, this method + In case of a `CREATE` Transaction, this method does not validate against `output_condition_uri`. Args: @@ -1013,8 +1012,8 @@ class Transaction(object): ParsingError, ASN1DecodeError, ASN1EncodeError): return False - if operation in (Transaction.CREATE, Transaction.GENESIS): - # NOTE: In the case of a `CREATE` or `GENESIS` transaction, the + if operation == Transaction.CREATE: + # NOTE: In the case of a `CREATE` transaction, the # output is always valid. output_valid = True else: diff --git a/bigchaindb/models.py b/bigchaindb/models.py index a91ccc24..fb23a94c 100644 --- a/bigchaindb/models.py +++ b/bigchaindb/models.py @@ -131,7 +131,7 @@ class Transaction(Transaction): for tx in tx_dict_list: tx.update({'metadata': None}) tx_map[tx['id']] = tx - if tx['operation'] in [Transaction.CREATE, Transaction.GENESIS]: + if tx['operation'] == Transaction.CREATE: tx_ids.append(tx['id']) assets = list(bigchain.get_assets(tx_ids)) @@ -411,8 +411,7 @@ class Block(object): assets = [] for transaction in block_dict['block']['transactions']: - if transaction['operation'] in [Transaction.CREATE, - Transaction.GENESIS]: + if transaction['operation'] == Transaction.CREATE: asset = transaction.pop('asset') asset.update({'id': transaction['id']}) assets.append(asset) @@ -458,8 +457,7 @@ class Block(object): assets = {asset.pop('id'): asset for asset in assets} # add the assets to the block transactions for transaction in block_dict['block']['transactions']: - if transaction['operation'] in [Transaction.CREATE, - Transaction.GENESIS]: + if transaction['operation'] == Transaction.CREATE: transaction.update({'asset': assets.get(transaction['id'])}) return block_dict @@ -506,8 +504,7 @@ class Block(object): """ asset_ids = [] for transaction in block_dict['block']['transactions']: - if transaction['operation'] in [Transaction.CREATE, - Transaction.GENESIS]: + if transaction['operation'] == Transaction.CREATE: asset_ids.append(transaction['id']) return asset_ids diff --git a/bigchaindb/utils.py b/bigchaindb/utils.py index 52361296..8c4180d0 100644 --- a/bigchaindb/utils.py +++ b/bigchaindb/utils.py @@ -123,25 +123,6 @@ def condition_details_has_owner(condition_details, owner): return False -def is_genesis_block(block): - """Check if the block is the genesis block. - - Args: - block (dict | Block): the block to check - - Returns: - bool: True if the block is the genesis block, False otherwise. - """ - - # we cannot have empty blocks, there will always be at least one - # element in the list so we can safely refer to it - # TODO: Remove this try-except and only handle `Block` as input - try: - return block.transactions[0].operation == 'GENESIS' - except AttributeError: - return block['block']['transactions'][0]['operation'] == 'GENESIS' - - class Lazy: """Lazy objects are useful to create chains of methods to execute later. diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 73aaa8fe..3cf53f43 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -99,7 +99,6 @@ def test__run_init(mocker): bigchain_mock.assert_called_once_with() init_db_mock.assert_called_once_with( connection=bigchain_mock.return_value.connection) - bigchain_mock.return_value.create_genesis_block.assert_called_once_with() @pytest.mark.tendermint diff --git a/tests/test_utils.py b/tests/test_utils.py index d01ba633..ffb45ddf 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -135,12 +135,6 @@ def test_process_group_instantiates_and_start_processes(mock_process): process.start.assert_called_with() -def test_is_genesis_block_returns_true_if_genesis(b): - from bigchaindb.utils import is_genesis_block - genesis_block = b.prepare_genesis_block() - assert is_genesis_block(genesis_block) - - def test_lazy_execution(): from bigchaindb.utils import Lazy