Update BigchainDB core class

This commit is contained in:
vrde 2016-11-29 14:18:22 +01:00 committed by Sylvain Bellemare
parent 53fb9f3d5f
commit 4549e2ee4a

View File

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