mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
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
This commit is contained in:
parent
c047487523
commit
e8e02cac50
@ -93,12 +93,9 @@ def run_configure(args):
|
|||||||
|
|
||||||
|
|
||||||
def _run_init():
|
def _run_init():
|
||||||
b = bigchaindb.Bigchain()
|
bdb = bigchaindb.Bigchain()
|
||||||
|
|
||||||
schema.init_database(connection=b.connection)
|
schema.init_database(connection=bdb.connection)
|
||||||
|
|
||||||
b.create_genesis_block()
|
|
||||||
logger.info('Genesis block created.')
|
|
||||||
|
|
||||||
|
|
||||||
@configure_bigchaindb
|
@configure_bigchaindb
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
"$schema": "http://json-schema.org/draft-04/schema#"
|
"$schema": "http://json-schema.org/draft-04/schema#"
|
||||||
type: object
|
type: object
|
||||||
title: Transaction Schema - CREATE/GENESIS specific constraints
|
title: Transaction Schema - CREATE specific constraints
|
||||||
required:
|
required:
|
||||||
- asset
|
- asset
|
||||||
- inputs
|
- inputs
|
||||||
|
@ -58,7 +58,6 @@ definitions:
|
|||||||
enum:
|
enum:
|
||||||
- CREATE
|
- CREATE
|
||||||
- TRANSFER
|
- TRANSFER
|
||||||
- GENESIS
|
|
||||||
asset:
|
asset:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
@ -480,8 +480,8 @@ class Transaction(object):
|
|||||||
spend.
|
spend.
|
||||||
outputs (:obj:`list` of :class:`~bigchaindb.common.
|
outputs (:obj:`list` of :class:`~bigchaindb.common.
|
||||||
transaction.Output`, optional): Define the assets to lock.
|
transaction.Output`, optional): Define the assets to lock.
|
||||||
asset (dict): Asset payload for this Transaction. ``CREATE`` and
|
asset (dict): Asset payload for this Transaction. ``CREATE``
|
||||||
``GENESIS`` Transactions require a dict with a ``data``
|
Transactions require a dict with a ``data``
|
||||||
property while ``TRANSFER`` Transactions require a dict with a
|
property while ``TRANSFER`` Transactions require a dict with a
|
||||||
``id`` property.
|
``id`` property.
|
||||||
metadata (dict):
|
metadata (dict):
|
||||||
@ -491,8 +491,7 @@ class Transaction(object):
|
|||||||
|
|
||||||
CREATE = 'CREATE'
|
CREATE = 'CREATE'
|
||||||
TRANSFER = 'TRANSFER'
|
TRANSFER = 'TRANSFER'
|
||||||
GENESIS = 'GENESIS'
|
ALLOWED_OPERATIONS = (CREATE, TRANSFER)
|
||||||
ALLOWED_OPERATIONS = (CREATE, TRANSFER, GENESIS)
|
|
||||||
VERSION = '2.0'
|
VERSION = '2.0'
|
||||||
|
|
||||||
def __init__(self, operation, asset, inputs=None, outputs=None,
|
def __init__(self, operation, asset, inputs=None, outputs=None,
|
||||||
@ -521,10 +520,10 @@ class Transaction(object):
|
|||||||
raise ValueError('`operation` must be one of {}'
|
raise ValueError('`operation` must be one of {}'
|
||||||
.format(allowed_ops))
|
.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'
|
# dicts holding a `data` property. Asset payloads for 'TRANSFER'
|
||||||
# operations must be dicts holding an `id` property.
|
# 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)):
|
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` '
|
raise TypeError(('`asset` must be None or a dict holding a `data` '
|
||||||
" property instance for '{}' Transactions".format(operation)))
|
" property instance for '{}' Transactions".format(operation)))
|
||||||
@ -928,7 +927,7 @@ class Transaction(object):
|
|||||||
Outputs.
|
Outputs.
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
Given a `CREATE` or `GENESIS` Transaction is passed,
|
Given a `CREATE` Transaction is passed,
|
||||||
dummy values for Outputs are submitted for validation that
|
dummy values for Outputs are submitted for validation that
|
||||||
evaluate parts of the validation-checks to `True`.
|
evaluate parts of the validation-checks to `True`.
|
||||||
|
|
||||||
@ -940,7 +939,7 @@ class Transaction(object):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: If all Inputs are valid.
|
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
|
# NOTE: Since in the case of a `CREATE`-transaction we do not have
|
||||||
# to check for outputs, we're just submitting dummy
|
# to check for outputs, we're just submitting dummy
|
||||||
# values to the actual method. This simplifies it's logic
|
# 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.
|
"""Validates a single Input against a single Output.
|
||||||
|
|
||||||
Note:
|
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`.
|
does not validate against `output_condition_uri`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -1013,8 +1012,8 @@ class Transaction(object):
|
|||||||
ParsingError, ASN1DecodeError, ASN1EncodeError):
|
ParsingError, ASN1DecodeError, ASN1EncodeError):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if operation in (Transaction.CREATE, Transaction.GENESIS):
|
if operation == Transaction.CREATE:
|
||||||
# NOTE: In the case of a `CREATE` or `GENESIS` transaction, the
|
# NOTE: In the case of a `CREATE` transaction, the
|
||||||
# output is always valid.
|
# output is always valid.
|
||||||
output_valid = True
|
output_valid = True
|
||||||
else:
|
else:
|
||||||
|
@ -131,7 +131,7 @@ class Transaction(Transaction):
|
|||||||
for tx in tx_dict_list:
|
for tx in tx_dict_list:
|
||||||
tx.update({'metadata': None})
|
tx.update({'metadata': None})
|
||||||
tx_map[tx['id']] = tx
|
tx_map[tx['id']] = tx
|
||||||
if tx['operation'] in [Transaction.CREATE, Transaction.GENESIS]:
|
if tx['operation'] == Transaction.CREATE:
|
||||||
tx_ids.append(tx['id'])
|
tx_ids.append(tx['id'])
|
||||||
|
|
||||||
assets = list(bigchain.get_assets(tx_ids))
|
assets = list(bigchain.get_assets(tx_ids))
|
||||||
@ -411,8 +411,7 @@ class Block(object):
|
|||||||
|
|
||||||
assets = []
|
assets = []
|
||||||
for transaction in block_dict['block']['transactions']:
|
for transaction in block_dict['block']['transactions']:
|
||||||
if transaction['operation'] in [Transaction.CREATE,
|
if transaction['operation'] == Transaction.CREATE:
|
||||||
Transaction.GENESIS]:
|
|
||||||
asset = transaction.pop('asset')
|
asset = transaction.pop('asset')
|
||||||
asset.update({'id': transaction['id']})
|
asset.update({'id': transaction['id']})
|
||||||
assets.append(asset)
|
assets.append(asset)
|
||||||
@ -458,8 +457,7 @@ class Block(object):
|
|||||||
assets = {asset.pop('id'): asset for asset in assets}
|
assets = {asset.pop('id'): asset for asset in assets}
|
||||||
# add the assets to the block transactions
|
# add the assets to the block transactions
|
||||||
for transaction in block_dict['block']['transactions']:
|
for transaction in block_dict['block']['transactions']:
|
||||||
if transaction['operation'] in [Transaction.CREATE,
|
if transaction['operation'] == Transaction.CREATE:
|
||||||
Transaction.GENESIS]:
|
|
||||||
transaction.update({'asset': assets.get(transaction['id'])})
|
transaction.update({'asset': assets.get(transaction['id'])})
|
||||||
return block_dict
|
return block_dict
|
||||||
|
|
||||||
@ -506,8 +504,7 @@ class Block(object):
|
|||||||
"""
|
"""
|
||||||
asset_ids = []
|
asset_ids = []
|
||||||
for transaction in block_dict['block']['transactions']:
|
for transaction in block_dict['block']['transactions']:
|
||||||
if transaction['operation'] in [Transaction.CREATE,
|
if transaction['operation'] == Transaction.CREATE:
|
||||||
Transaction.GENESIS]:
|
|
||||||
asset_ids.append(transaction['id'])
|
asset_ids.append(transaction['id'])
|
||||||
|
|
||||||
return asset_ids
|
return asset_ids
|
||||||
|
@ -123,25 +123,6 @@ def condition_details_has_owner(condition_details, owner):
|
|||||||
return False
|
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:
|
class Lazy:
|
||||||
"""Lazy objects are useful to create chains of methods to
|
"""Lazy objects are useful to create chains of methods to
|
||||||
execute later.
|
execute later.
|
||||||
|
@ -99,7 +99,6 @@ def test__run_init(mocker):
|
|||||||
bigchain_mock.assert_called_once_with()
|
bigchain_mock.assert_called_once_with()
|
||||||
init_db_mock.assert_called_once_with(
|
init_db_mock.assert_called_once_with(
|
||||||
connection=bigchain_mock.return_value.connection)
|
connection=bigchain_mock.return_value.connection)
|
||||||
bigchain_mock.return_value.create_genesis_block.assert_called_once_with()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.tendermint
|
@pytest.mark.tendermint
|
||||||
|
@ -135,12 +135,6 @@ def test_process_group_instantiates_and_start_processes(mock_process):
|
|||||||
process.start.assert_called_with()
|
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():
|
def test_lazy_execution():
|
||||||
from bigchaindb.utils import Lazy
|
from bigchaindb.utils import Lazy
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user