Merge branch 'z-bowen-remove_bigchain_class'

This commit is contained in:
z-bowen 2018-06-28 12:19:57 +02:00
commit 97946bd81a
14 changed files with 171 additions and 490 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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,

View File

@ -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()

View File

@ -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():

View File

@ -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')

View File

@ -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))

View File

@ -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