diff --git a/bigchaindb/core.py b/bigchaindb/core.py index b59f4ebd..3cc669b8 100644 --- a/bigchaindb/core.py +++ b/bigchaindb/core.py @@ -10,7 +10,7 @@ from bigchaindb.common.transaction import TransactionLink, Asset import bigchaindb -from bigchaindb.db.utils import Connection, get_backend +from bigchaindb import backend from bigchaindb import config_utils, util from bigchaindb.consensus import BaseConsensusRules from bigchaindb.models import Block, Transaction @@ -31,9 +31,7 @@ class Bigchain(object): # return if transaction is in backlog TX_IN_BACKLOG = 'backlog' - def __init__(self, host=None, port=None, dbname=None, backend=None, - public_key=None, private_key=None, keyring=[], - backlog_reassign_delay=None): + def __init__(self, public_key=None, private_key=None, keyring=[], connection=None, backlog_reassign_delay=None): """Initialize the Bigchain instance A Bigchain instance has several configuration parameters (e.g. host). @@ -46,34 +44,24 @@ class Bigchain(object): its default value (defined in bigchaindb.__init__). Args: - host (str): hostname where RethinkDB is running. - port (int): port in which RethinkDB is running (usually 28015). - dbname (str): the name of the database to connect to (usually bigchain). - backend (:class:`~bigchaindb.db.backends.rethinkdb.RehinkDBBackend`): - the database backend to use. public_key (str): the base58 encoded public key for the ED25519 curve. private_key (str): the base58 encoded private key for the ED25519 curve. keyring (list[str]): list of base58 encoded public keys of the federation nodes. + connection (:class:`~bigchaindb.backend.connection.Connection`): + A connection to the database. """ config_utils.autoconfigure() - self.host = host or bigchaindb.config['database']['host'] - self.port = port or bigchaindb.config['database']['port'] - self.dbname = dbname or bigchaindb.config['database']['name'] - self.backend = backend or get_backend(host, port, dbname) + self.me = public_key or bigchaindb.config['keypair']['public'] self.me_private = private_key or bigchaindb.config['keypair']['private'] self.nodes_except_me = keyring or bigchaindb.config['keyring'] self.backlog_reassign_delay = backlog_reassign_delay or bigchaindb.config['backlog_reassign_delay'] self.consensus = BaseConsensusRules - # change RethinkDB read mode to majority. This ensures consistency in query results - self.read_mode = 'majority' - + self.connection = connection if connection else backend.connect(**bigchaindb.config['database']) if not self.me or not self.me_private: raise exceptions.KeypairNotFoundException() - self.connection = Connection(host=self.host, port=self.port, db=self.dbname) - def write_transaction(self, signed_transaction, durability='soft'): """Write the transaction to bigchain. @@ -100,7 +88,7 @@ class Bigchain(object): signed_transaction.update({'assignment_timestamp': time()}) # write to the backlog - return self.backend.write_transaction(signed_transaction) + return backend.query.write_transaction(self.connection, signed_transaction) def reassign_transaction(self, transaction): """Assign a transaction to a new node @@ -126,8 +114,8 @@ class Bigchain(object): # There is no other node to assign to new_assignee = self.me - return self.backend.update_transaction( - transaction['id'], + return backend.query.update_transaction( + self.connection, transaction['id'], {'assignee': new_assignee, 'assignment_timestamp': time()}) def delete_transaction(self, *transaction_id): @@ -140,7 +128,7 @@ class Bigchain(object): The database response. """ - return self.backend.delete_transaction(*transaction_id) + return backend.query.delete_transaction(self.connection, *transaction_id) def get_stale_transactions(self): """Get a cursor of stale transactions. @@ -149,7 +137,7 @@ class Bigchain(object): backlog after some amount of time specified in the configuration """ - return self.backend.get_stale_transactions(self.backlog_reassign_delay) + return backend.query.get_stale_transactions(self.connection, self.backlog_reassign_delay) def validate_transaction(self, transaction): """Validate a transaction. @@ -200,7 +188,7 @@ class Bigchain(object): include_status (bool): also return the status of the block the return value is then a tuple: (block, status) """ - block = self.backend.get_block(block_id) + block = backend.query.get_block(self.connection, block_id) status = None if include_status: @@ -260,10 +248,10 @@ class Bigchain(object): break # Query the transaction in the target block and return - response = self.backend.get_transaction_from_block(txid, target_block_id) + response = backend.query.get_transaction_from_block(self.connection, txid, target_block_id) if check_backlog: - response = self.backend.get_transaction_from_backlog(txid) + response = backend.query.get_transaction_from_backlog(self.connection, txid) if response: tx_status = self.TX_IN_BACKLOG @@ -304,7 +292,7 @@ class Bigchain(object): """ # First, get information on all blocks which contain this transaction - blocks = self.backend.get_blocks_status_from_transaction(txid) + blocks = backend.query.get_blocks_status_from_transaction(self.connection, txid) if blocks: # Determine the election status of each block validity = { @@ -346,7 +334,7 @@ class Bigchain(object): If no transaction exists for that asset it returns an empty list `[]` """ - txids = self.backend.get_txids_by_asset_id(asset_id) + txids = backend.query.get_txids_by_asset_id(self.connection, asset_id) transactions = [] for txid in txids: tx = self.get_transaction(txid) @@ -364,7 +352,7 @@ class Bigchain(object): :class:`~bigchaindb.common.transaction.Asset` if the asset exists else None. """ - cursor = self.backend.get_asset_by_id(asset_id) + cursor = backend.query.get_asset_by_id(self.connection, asset_id) cursor = list(cursor) if cursor: return Asset.from_dict(cursor[0]['asset']) @@ -385,7 +373,7 @@ class Bigchain(object): """ # checks if an input was already spent # checks if the bigchain has any transaction with input {'txid': ..., 'cid': ...} - transactions = list(self.backend.get_spent(txid, cid)) + transactions = list(backend.query.get_spent(self.connection, txid, cid)) # a transaction_id should have been spent at most one time if transactions: @@ -422,7 +410,7 @@ class Bigchain(object): """ # get all transactions in which owner is in the `owners_after` list - response = self.backend.get_owned_ids(owner) + response = backend.query.get_owned_ids(self.connection, owner) owned = [] for tx in response: @@ -507,7 +495,7 @@ class Bigchain(object): but the vote is invalid. """ - votes = list(self.backend.get_votes_by_block_id_and_voter(block_id, self.me)) + votes = list(backend.query.get_votes_by_block_id_and_voter(self.connection, block_id, self.me)) if len(votes) > 1: raise exceptions.MultipleVotesError('Block {block_id} has {n_votes} votes from public key {me}' @@ -529,10 +517,10 @@ class Bigchain(object): block (Block): block to write to bigchain. """ - return self.backend.write_block(block.to_str(), durability=durability) + return backend.query.write_block(self.connection, block.to_str(), durability=durability) def transaction_exists(self, transaction_id): - return self.backend.has_transaction(transaction_id) + return backend.query.has_transaction(self.connection, transaction_id) def prepare_genesis_block(self): """Prepare a genesis block.""" @@ -561,7 +549,7 @@ class Bigchain(object): # 2. create the block with one transaction # 3. write the block to the bigchain - blocks_count = self.backend.count_blocks() + blocks_count = backend.query.count_blocks(self.connection) if blocks_count: raise exceptions.GenesisBlockAlreadyExistsError('Cannot create the Genesis block') @@ -606,12 +594,12 @@ class Bigchain(object): def write_vote(self, vote): """Write the vote to the database.""" - return self.backend.write_vote(vote) + return backend.query.write_vote(self.connection, vote) def get_last_voted_block(self): """Returns the last block that this node voted on.""" - return Block.from_dict(self.backend.get_last_voted_block(self.me)) + return Block.from_dict(backend.query.get_last_voted_block(self.connection, self.me)) def get_unvoted_blocks(self): """Return all the blocks that have not been voted on by this node. @@ -621,12 +609,12 @@ class Bigchain(object): """ # XXX: should this return instaces of Block? - return self.backend.get_unvoted_blocks(self.me) + return backend.query.get_unvoted_blocks(self.connection, self.me) def block_election_status(self, block_id, voters): """Tally the votes on a block, and return the status: valid, invalid, or undecided.""" - votes = list(self.backend.get_votes_by_block_id(block_id)) + votes = list(backend.query.get_votes_by_block_id(self.connection, block_id)) n_voters = len(voters) voter_counts = collections.Counter([vote['node_pubkey'] for vote in votes])