Problem: Some configurations are defunct (#2338)

* Problem: BigchainDB config has stale/deprecated parameters

- Remove `keyring` and `keypair` from config
- Update tests
- Add `tendermint` config

* Fix flake8

* Update some naming conventions and redundant changes

* Remove redundant routine `fast_query`

* Remove deprecated parameters and descriptions

* remove some more unwanted code

* Problem: Two flake8 errors made Travis fail

Solution: Fix the two flake8 errors

* Address comments

- Remove reference of nodes_except_me and me_private and me
  as attributes of BigchainDB instances
- Update and re-add test(s)
- Do not introduce `tendermint` in configuration instead handle that
  in a separate PR along with docs

* Address comments

- Remove tests that are already covered with 2.0
- Remove tests that are no longer relevant
- Add TODO for more cleanup

* Remove tendermint config from configure command
This commit is contained in:
Muawia Khan 2018-06-08 15:50:50 +02:00 committed by Vanshdeep Singh
parent 58a5959170
commit 2b39566a4b
29 changed files with 312 additions and 1293 deletions

View File

@ -7,22 +7,13 @@ from bigchaindb.log.configs import SUBSCRIBER_LOGGING_CONFIG as log_config
# PORT_NUMBER = reduce(lambda x, y: x * y, map(ord, 'BigchainDB')) % 2**16
# basically, the port number is 9984
_base_database_rethinkdb = {
'host': 'localhost',
'port': 28015,
'name': 'bigchain',
}
# The following variable is used by `bigchaindb configure` to
# prompt the user for database values. We cannot rely on
# _base_database_rethinkdb.keys() or _base_database_mongodb.keys()
# because dicts are unordered. I tried to configure
# _base_database_localmongodb.keys() because dicts are unordered.
# I tried to configure
_database_keys_map = {
'localmongodb': ('host', 'port', 'name'),
'mongodb': ('host', 'port', 'name', 'replicaset'),
'rethinkdb': ('host', 'port', 'name')
}
_base_database_localmongodb = {
@ -34,35 +25,6 @@ _base_database_localmongodb = {
'password': None,
}
_base_database_mongodb = {
'host': 'localhost',
'port': 27017,
'name': 'bigchain',
'replicaset': 'bigchain-rs',
'login': None,
'password': None,
}
_database_rethinkdb = {
'backend': 'rethinkdb',
'connection_timeout': 5000,
'max_tries': 3,
}
_database_rethinkdb.update(_base_database_rethinkdb)
_database_mongodb = {
'backend': 'mongodb',
'connection_timeout': 5000,
'max_tries': 3,
'ssl': False,
'ca_cert': None,
'certfile': None,
'keyfile': None,
'keyfile_passphrase': None,
'crlfile': None,
}
_database_mongodb.update(_base_database_mongodb)
_database_localmongodb = {
'backend': 'localmongodb',
'connection_timeout': 5000,
@ -78,8 +40,6 @@ _database_localmongodb.update(_base_database_localmongodb)
_database_map = {
'localmongodb': _database_localmongodb,
'mongodb': _database_mongodb,
'rethinkdb': _database_rethinkdb
}
config = {
@ -101,11 +61,6 @@ config = {
},
# FIXME: hardcoding to localmongodb for now
'database': _database_map['localmongodb'],
'keypair': {
'public': None,
'private': None,
},
'keyring': [],
'log': {
'file': log_config['handlers']['file']['filename'],
'error_file': log_config['handlers']['errors']['filename'],

View File

@ -41,8 +41,6 @@ def run_show_config(args):
# configure the system.
config = copy.deepcopy(bigchaindb.config)
del config['CONFIGURED']
private_key = config['keypair']['private']
config['keypair']['private'] = 'x' * 45 if private_key else None
print(json.dumps(config, indent=4, sort_keys=True))

View File

@ -23,10 +23,6 @@ class CyclicBlockchainError(BigchainDBError):
"""Raised when there is a cycle in the blockchain"""
class KeypairNotFoundException(BigchainDBError):
"""Raised if operation cannot proceed because the keypair was not given"""
class KeypairMismatchException(BigchainDBError):
"""Raised if the private key(s) provided for signing don't match any of the
current owner(s)

View File

@ -1,15 +1,10 @@
import random
from time import time
from bigchaindb import exceptions as core_exceptions
from bigchaindb.common import crypto, exceptions
from bigchaindb.common.utils import gen_timestamp, serialize
import bigchaindb
from bigchaindb import backend, config_utils, fastquery
from bigchaindb import backend, config_utils
from bigchaindb.consensus import BaseConsensusRules
from bigchaindb.models import Block, Transaction
from bigchaindb.models import Transaction
class Bigchain(object):
@ -30,7 +25,7 @@ class Bigchain(object):
TX_IN_BACKLOG = 'backlog'
"""return if transaction is in backlog"""
def __init__(self, public_key=None, private_key=None, keyring=[], connection=None):
def __init__(self, connection=None):
"""Initialize the Bigchain instance
A Bigchain instance has several configuration parameters (e.g. host).
@ -43,19 +38,11 @@ class Bigchain(object):
its default value (defined in bigchaindb.__init__).
Args:
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.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']
consensusPlugin = bigchaindb.config.get('consensus_plugin')
if consensusPlugin:
@ -64,58 +51,6 @@ class Bigchain(object):
self.consensus = BaseConsensusRules
self.connection = connection if connection else backend.connect(**bigchaindb.config['database'])
# if not self.me:
# raise exceptions.KeypairNotFoundException()
federation = property(lambda self: set(self.nodes_except_me + [self.me]))
""" Set of federation member public keys """
def write_transaction(self, signed_transaction):
"""Write the transaction to bigchain.
When first writing a transaction to the bigchain the transaction will be kept in a backlog until
it has been validated by the nodes of the federation.
Args:
signed_transaction (Transaction): transaction with the `signature` included.
Returns:
dict: database response
"""
signed_transaction = signed_transaction.to_dict()
# we will assign this transaction to `one` node. This way we make sure that there are no duplicate
# transactions on the bigchain
if self.nodes_except_me:
assignee = random.choice(self.nodes_except_me)
else:
# I am the only node
assignee = self.me
signed_transaction.update({'assignee': assignee})
signed_transaction.update({'assignment_timestamp': time()})
# write to the backlog
return backend.query.write_transaction(self.connection, signed_transaction)
def reassign_transaction(self, transaction):
"""Assign a transaction to a new node
Args:
transaction (dict): assigned transaction
Returns:
dict: database response or None if no reassignment is possible
"""
other_nodes = tuple(
self.federation.difference([transaction['assignee']])
)
new_assignee = random.choice(other_nodes) if other_nodes else self.me
return backend.query.update_transaction(
self.connection, transaction['id'],
{'assignee': new_assignee, 'assignment_timestamp': time()})
def delete_transaction(self, *transaction_id):
"""Delete a transaction from the backlog.
@ -166,40 +101,6 @@ class Bigchain(object):
return False
return True
def get_block(self, block_id, include_status=False):
"""Get the block with the specified `block_id` (and optionally its status)
Returns the block corresponding to `block_id` or None if no match is
found.
Args:
block_id (str): transaction id of the transaction to get
include_status (bool): also return the status of the block
the return value is then a tuple: (block, status)
"""
# get block from database
block_dict = backend.query.get_block(self.connection, block_id)
# get the asset ids from the block
if block_dict:
asset_ids = Block.get_asset_ids(block_dict)
txn_ids = Block.get_txn_ids(block_dict)
# get the assets from the database
assets = self.get_assets(asset_ids)
# get the metadata from the database
metadata = self.get_metadata(txn_ids)
# add the assets to the block transactions
block_dict = Block.couple_assets(block_dict, assets)
# add the metadata to the block transactions
block_dict = Block.couple_metadata(block_dict, metadata)
status = None
if include_status:
if block_dict:
status = self.block_election_status(block_dict)
return block_dict, status
else:
return block_dict
def get_transaction(self, txid, include_status=False):
"""Get the transaction with the specified `txid` (and optionally its status)
@ -408,10 +309,6 @@ class Bigchain(object):
"""
return self.get_outputs_filtered(owner, spent=False)
@property
def fastquery(self):
return fastquery.FastQuery(self.connection, self.me)
def get_outputs_filtered(self, owner, spent=None):
"""Get a list of output links filtered on some criteria
@ -443,30 +340,6 @@ class Bigchain(object):
if status == self.TX_VALID:
yield tx
def create_block(self, validated_transactions):
"""Creates a block given a list of `validated_transactions`.
Note that this method does not validate the transactions. Transactions
should be validated before calling create_block.
Args:
validated_transactions (list(Transaction)): list of validated
transactions.
Returns:
Block: created block.
"""
# Prevent the creation of empty blocks
if not validated_transactions:
raise exceptions.OperationError('Empty block creation is not '
'allowed')
voters = list(self.federation)
block = Block(validated_transactions, self.me, gen_timestamp(), voters)
block = block.sign(self.me_private)
return block
# TODO: check that the votings structure is correctly constructed
def validate_block(self, block):
"""Validate a block.
@ -480,21 +353,6 @@ class Bigchain(object):
"""
return self.consensus.validate_block(self, block)
def has_previous_vote(self, block_id):
"""Check for previous votes from this node
Args:
block_id (str): the id of the block to check
Returns:
bool: :const:`True` if this block already has a
valid vote from this node, :const:`False` otherwise.
"""
votes = list(backend.query.get_votes_by_block_id_and_voter(self.connection, block_id, self.me))
el, _ = self.consensus.voting.partition_eligible_votes(votes, [self.me])
return bool(el)
def write_block(self, block):
"""Write a block to bigchain.
@ -516,101 +374,10 @@ class Bigchain(object):
# write the block
return backend.query.write_block(self.connection, block_dict)
def prepare_genesis_block(self):
"""Prepare a genesis block."""
metadata = {'message': 'Hello World from the BigchainDB'}
transaction = Transaction.create([self.me], [([self.me], 1)],
metadata=metadata)
# NOTE: The transaction model doesn't expose an API to generate a
# GENESIS transaction, as this is literally the only usage.
transaction.operation = 'GENESIS'
transaction = transaction.sign([self.me_private])
# create the block
return self.create_block([transaction])
def create_genesis_block(self):
"""Create the genesis block
Block created when bigchain is first initialized. This method is not atomic, there might be concurrency
problems if multiple instances try to write the genesis block when the BigchainDB Federation is started,
but it's a highly unlikely scenario.
"""
# 1. create one transaction
# 2. create the block with one transaction
# 3. write the block to the bigchain
blocks_count = backend.query.count_blocks(self.connection)
if blocks_count:
raise exceptions.GenesisBlockAlreadyExistsError('Cannot create the Genesis block')
block = self.prepare_genesis_block()
self.write_block(block)
return block
def vote(self, block_id, previous_block_id, decision, invalid_reason=None):
"""Create a signed vote for a block given the
:attr:`previous_block_id` and the :attr:`decision` (valid/invalid).
Args:
block_id (str): The id of the block to vote on.
previous_block_id (str): The id of the previous block.
decision (bool): Whether the block is valid or invalid.
invalid_reason (Optional[str]): Reason the block is invalid
"""
if block_id == previous_block_id:
raise exceptions.CyclicBlockchainError()
vote = {
'voting_for_block': block_id,
'previous_block': previous_block_id,
'is_block_valid': decision,
'invalid_reason': invalid_reason,
'timestamp': gen_timestamp()
}
vote_data = serialize(vote)
signature = crypto.PrivateKey(self.me_private).sign(vote_data.encode())
vote_signed = {
'node_pubkey': self.me,
'signature': signature.decode(),
'vote': vote
}
return vote_signed
def write_vote(self, vote):
"""Write the vote to the database."""
return backend.query.write_vote(self.connection, vote)
def get_last_voted_block(self):
"""Returns the last block that this node voted on."""
last_block_id = backend.query.get_last_voted_block_id(self.connection,
self.me)
return Block.from_dict(self.get_block(last_block_id))
def block_election(self, block):
if type(block) != dict:
block = block.to_dict()
votes = list(backend.query.get_votes_by_block_id(self.connection,
block['id']))
return self.consensus.voting.block_election(block, votes,
self.federation)
def block_election_status(self, block):
"""Tally the votes on a block, and return the status:
valid, invalid, or undecided.
"""
return self.block_election(block)['status']
def get_assets(self, asset_ids):
"""Return a list of assets that match the asset_ids

View File

@ -18,27 +18,8 @@ class FastQuery:
a byzantine node.
"""
def __init__(self, connection, me):
def __init__(self, connection):
self.connection = connection
self.me = me
def filter_valid_block_ids(self, block_ids, include_undecided=False):
"""Given block ids, return only the ones that are valid."""
block_ids = list(set(block_ids))
votes = query.get_votes_for_blocks_by_voter(
self.connection, block_ids, self.me)
votes = {vote['vote']['voting_for_block']: vote['vote']['is_block_valid']
for vote in votes}
return [block_id for block_id in block_ids
if votes.get(block_id, include_undecided)]
def filter_valid_items(self, items, block_id_key=lambda b: b[0]):
"""Given items with block ids, return only the ones that are valid or undecided.
"""
items = list(items)
block_ids = map(block_id_key, items)
valid_block_ids = set(self.filter_valid_block_ids(block_ids, True))
return [b for b in items if block_id_key(b) in valid_block_ids]
def get_outputs_by_public_key(self, public_key):
"""Get outputs for a public key"""

View File

@ -5,7 +5,7 @@ from bigchaindb.common.exceptions import (InvalidHash, InvalidSignature,
DoubleSpend, InputDoesNotExist,
TransactionNotInValidBlock,
AssetIdMismatch, AmountError,
SybilError, DuplicateTransaction)
DuplicateTransaction)
from bigchaindb.common.transaction import Transaction
from bigchaindb.common.utils import (gen_timestamp, serialize,
validate_txn_obj, validate_key)
@ -156,6 +156,7 @@ class Transaction(Transaction):
return cls.from_dict(tx)
# TODO: Remove node_pubkey as part of cleanup II
class Block(object):
"""Bundle a list of Transactions in a Block. Nodes vote on its validity.
@ -165,14 +166,12 @@ class Block(object):
node_pubkey (str): The public key of the node creating the
Block.
timestamp (str): The Unix time a Block was created.
voters (:obj:`list` of :obj:`str`): A list of a federation
nodes' public keys supposed to vote on the Block.
signature (str): A cryptographic signature ensuring the
integrity and validity of the creator of a Block.
"""
def __init__(self, transactions=None, node_pubkey=None, timestamp=None,
voters=None, signature=None):
signature=None):
"""The Block model is mainly used for (de)serialization and integrity
checking.
@ -182,8 +181,6 @@ class Block(object):
node_pubkey (str): The public key of the node creating the
Block.
timestamp (str): The Unix time a Block was created.
voters (:obj:`list` of :obj:`str`): A list of a federation
nodes' public keys supposed to vote on the Block.
signature (str): A cryptographic signature ensuring the
integrity and validity of the creator of a Block.
"""
@ -192,11 +189,6 @@ class Block(object):
else:
self.transactions = transactions or []
if voters is not None and not isinstance(voters, list):
raise TypeError('`voters` must be a list instance or None')
else:
self.voters = voters or []
if timestamp is not None:
self.timestamp = timestamp
else:
@ -250,10 +242,6 @@ class Block(object):
Raises:
ValidationError: If there is a problem with the block
"""
# Check if the block was created by a federation node
if self.node_pubkey not in bigchain.federation:
raise SybilError('Only federation nodes can create blocks')
# Check that the signature is valid
if not self.is_signature_valid():
raise InvalidSignature('Invalid block signature')
@ -338,7 +326,7 @@ class Block(object):
signature = block_body.get('signature')
return cls(transactions, block['node_pubkey'],
block['timestamp'], block['voters'], signature)
block['timestamp'], [], signature)
@property
def id(self):
@ -360,7 +348,6 @@ class Block(object):
'timestamp': self.timestamp,
'transactions': [tx.to_dict() for tx in self.transactions],
'node_pubkey': self.node_pubkey,
'voters': self.voters,
}
block_serialized = serialize(block)
block_id = hash_data(block_serialized)

View File

@ -24,9 +24,9 @@ class Voting:
"""
@classmethod
def block_election(cls, block, votes, keyring):
def block_election(cls, block, votes):
"""Calculate the election status of a block."""
eligible_voters = set(block['block']['voters']) & set(keyring)
eligible_voters = set(block['block']['voters'])
n_voters = len(eligible_voters)
eligible_votes, ineligible_votes = \
cls.partition_eligible_votes(votes, eligible_voters)

View File

@ -3,7 +3,6 @@
import flask
from flask_restful import Resource
import bigchaindb
from bigchaindb.web.views.base import base_ws_uri
from bigchaindb import version
from bigchaindb.web.websocket_server import EVENTS_ENDPOINT
@ -22,8 +21,6 @@ class RootIndex(Resource):
'docs': ''.join(docs_url),
'software': 'BigchainDB',
'version': version.__version__,
'public_key': bigchaindb.config['keypair']['public'],
'keyring': bigchaindb.config['keyring']
})

View File

@ -120,11 +120,6 @@ def main():
# HTTP Index
res = client.get('/', environ_overrides={'HTTP_HOST': host})
res_data = json.loads(res.data.decode())
res_data['keyring'] = [
"6qHyZew94NMmUTYyHnkZsB8cxJYuRNEiEpXHe1ih9QX3",
"AdDuyrTyjrDt935YnFu4VBCVDhHtY2Y6rcy7x2TFeiRi"
]
res_data['public_key'] = 'NC8c8rYcAhyKVpx1PCV65CBmyq4YUbLysy3Rqrg8L8mz'
ctx['index'] = pretty_json(res_data)
# API index

View File

@ -33,10 +33,9 @@ def test_validate_transfer_asset_id_mismatch(b, signed_create_tx, user_pk, user_
tx_transfer_signed.validate(b)
def test_get_asset_id_create_transaction(b, user_pk):
def test_get_asset_id_create_transaction(alice, user_pk):
from bigchaindb.models import Transaction
tx_create = Transaction.create([b.me], [([user_pk], 1)])
tx_create = Transaction.create([alice.public_key], [([user_pk], 1)])
assert Transaction.get_asset_id(tx_create) == tx_create.id
@ -49,16 +48,16 @@ def test_get_asset_id_transfer_transaction(b, signed_create_tx, user_pk):
assert asset_id == tx_transfer.asset['id']
def test_asset_id_mismatch(b, user_pk):
def test_asset_id_mismatch(alice, user_pk):
from bigchaindb.models import Transaction
from bigchaindb.common.exceptions import AssetIdMismatch
tx1 = Transaction.create([b.me], [([user_pk], 1)],
tx1 = Transaction.create([alice.public_key], [([user_pk], 1)],
metadata={'msg': random.random()})
tx1.sign([b.me_private])
tx2 = Transaction.create([b.me], [([user_pk], 1)],
tx1.sign([alice.private_key])
tx2 = Transaction.create([alice.public_key], [([user_pk], 1)],
metadata={'msg': random.random()})
tx2.sign([b.me_private])
tx2.sign([alice.private_key])
with pytest.raises(AssetIdMismatch):
Transaction.get_asset_id([tx1, tx2])

View File

@ -10,11 +10,11 @@ pytestmark = pytest.mark.tendermint
# Single owners_before
# Single output
# Single owners_after
def test_single_in_single_own_single_out_single_own_create(b, user_pk):
def test_single_in_single_own_single_out_single_own_create(alice, user_pk, b):
from bigchaindb.models import Transaction
tx = Transaction.create([b.me], [([user_pk], 100)], asset={'name': random.random()})
tx_signed = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()})
tx_signed = tx.sign([alice.private_key])
assert tx_signed.validate(b) == tx_signed
assert len(tx_signed.outputs) == 1
@ -27,12 +27,12 @@ def test_single_in_single_own_single_out_single_own_create(b, user_pk):
# Single owners_before
# Multiple outputs
# Single owners_after per output
def test_single_in_single_own_multiple_out_single_own_create(b, user_pk):
def test_single_in_single_own_multiple_out_single_own_create(alice, user_pk, b):
from bigchaindb.models import Transaction
tx = Transaction.create([b.me], [([user_pk], 50), ([user_pk], 50)],
tx = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk], 50)],
asset={'name': random.random()})
tx_signed = tx.sign([b.me_private])
tx_signed = tx.sign([alice.private_key])
assert tx_signed.validate(b) == tx_signed
assert len(tx_signed.outputs) == 2
@ -46,11 +46,11 @@ def test_single_in_single_own_multiple_out_single_own_create(b, user_pk):
# Single owners_before
# Single output
# Multiple owners_after
def test_single_in_single_own_single_out_multiple_own_create(b, user_pk):
def test_single_in_single_own_single_out_multiple_own_create(alice, user_pk, b):
from bigchaindb.models import Transaction
tx = Transaction.create([b.me], [([user_pk, user_pk], 100)], asset={'name': random.random()})
tx_signed = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([user_pk, user_pk], 100)], asset={'name': random.random()})
tx_signed = tx.sign([alice.private_key])
assert tx_signed.validate(b) == tx_signed
assert len(tx_signed.outputs) == 1
@ -69,12 +69,12 @@ def test_single_in_single_own_single_out_multiple_own_create(b, user_pk):
# Multiple outputs
# Mix: one output with a single owners_after, one output with multiple
# owners_after
def test_single_in_single_own_multiple_out_mix_own_create(b, user_pk):
def test_single_in_single_own_multiple_out_mix_own_create(alice, user_pk, b):
from bigchaindb.models import Transaction
tx = Transaction.create([b.me], [([user_pk], 50), ([user_pk, user_pk], 50)],
tx = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk, user_pk], 50)],
asset={'name': random.random()})
tx_signed = tx.sign([b.me_private])
tx_signed = tx.sign([alice.private_key])
assert tx_signed.validate(b) == tx_signed
assert len(tx_signed.outputs) == 2
@ -92,13 +92,13 @@ def test_single_in_single_own_multiple_out_mix_own_create(b, user_pk):
# Single input
# Multiple owners_before
# Output combinations already tested above
def test_single_in_multiple_own_single_out_single_own_create(b, user_pk,
def test_single_in_multiple_own_single_out_single_own_create(alice, b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import _fulfillment_to_details
tx = Transaction.create([b.me, user_pk], [([user_pk], 100)], asset={'name': random.random()})
tx_signed = tx.sign([b.me_private, user_sk])
tx = Transaction.create([alice.public_key, user_pk], [([user_pk], 100)], asset={'name': random.random()})
tx_signed = tx.sign([alice.private_key, user_sk])
assert tx_signed.validate(b) == tx_signed
assert len(tx_signed.outputs) == 1
assert tx_signed.outputs[0].amount == 100
@ -114,16 +114,16 @@ def test_single_in_multiple_own_single_out_single_own_create(b, user_pk,
# Single owners_before
# Single output
# Single owners_after
def test_single_in_single_own_single_out_single_own_transfer(b, user_pk,
def test_single_in_single_own_single_out_single_own_transfer(alice, b, user_pk,
user_sk):
from bigchaindb.models import Transaction
# CREATE divisible asset
tx_create = Transaction.create([b.me], [([user_pk], 100)], asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()})
tx_create_signed = tx_create.sign([alice.private_key])
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
@ -140,17 +140,17 @@ def test_single_in_single_own_single_out_single_own_transfer(b, user_pk,
# Single owners_before
# Multiple output
# Single owners_after
def test_single_in_single_own_multiple_out_single_own_transfer(b, user_pk,
def test_single_in_single_own_multiple_out_single_own_transfer(alice, b, user_pk,
user_sk):
from bigchaindb.models import Transaction
# CREATE divisible asset
tx_create = Transaction.create([b.me], [([user_pk], 100)], asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()})
tx_create_signed = tx_create.sign([alice.private_key])
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 50), ([b.me], 50)],
[([alice.public_key], 50), ([alice.public_key], 50)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
@ -168,17 +168,17 @@ def test_single_in_single_own_multiple_out_single_own_transfer(b, user_pk,
# Single owners_before
# Single output
# Multiple owners_after
def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk,
def test_single_in_single_own_single_out_multiple_own_transfer(alice, b, user_pk,
user_sk):
from bigchaindb.models import Transaction
# CREATE divisible asset
tx_create = Transaction.create([b.me], [([user_pk], 100)], asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()})
tx_create_signed = tx_create.sign([alice.private_key])
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me, b.me], 100)],
[([alice.public_key, alice.public_key], 100)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
@ -201,17 +201,17 @@ def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk,
# Multiple outputs
# Mix: one output with a single owners_after, one output with multiple
# owners_after
def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_pk,
def test_single_in_single_own_multiple_out_mix_own_transfer(alice, b, user_pk,
user_sk):
from bigchaindb.models import Transaction
# CREATE divisible asset
tx_create = Transaction.create([b.me], [([user_pk], 100)], asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()})
tx_create_signed = tx_create.sign([alice.private_key])
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 50), ([b.me, b.me], 50)],
[([alice.public_key], 50), ([alice.public_key, alice.public_key], 50)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
@ -234,20 +234,20 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_pk,
# Multiple owners_before
# Single output
# Single owners_after
def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk,
def test_single_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import _fulfillment_to_details
# CREATE divisible asset
tx_create = Transaction.create([b.me], [([b.me, user_pk], 100)],
tx_create = Transaction.create([alice.public_key], [([alice.public_key, user_pk], 100)],
asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create_signed = tx_create.sign([alice.private_key])
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk])
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
@ -266,17 +266,17 @@ def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk,
# Single owners_before per input
# Single output
# Single owners_after
def test_multiple_in_single_own_single_out_single_own_transfer(b, user_pk,
def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk,
user_sk):
from bigchaindb.models import Transaction
# CREATE divisible asset
tx_create = Transaction.create([b.me], [([user_pk], 50), ([user_pk], 50)],
tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk], 50)],
asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create_signed = tx_create.sign([alice.private_key])
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
@ -293,20 +293,21 @@ def test_multiple_in_single_own_single_out_single_own_transfer(b, user_pk,
# Multiple owners_before per input
# Single output
# Single owners_after
def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_pk,
def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import _fulfillment_to_details
# CREATE divisible asset
tx_create = Transaction.create([b.me], [([user_pk, b.me], 50), ([user_pk, b.me], 50)],
tx_create = Transaction.create([alice.public_key], [([user_pk, alice.public_key], 50),
([user_pk, alice.public_key], 50)],
asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create_signed = tx_create.sign([alice.private_key])
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk])
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
@ -329,20 +330,20 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_pk,
# owners_before
# Single output
# Single owners_after
def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(b, user_pk,
def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import _fulfillment_to_details
# CREATE divisible asset
tx_create = Transaction.create([b.me], [([user_pk], 50), ([user_pk, b.me], 50)],
tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)],
asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create_signed = tx_create.sign([alice.private_key])
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk])
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
@ -365,21 +366,21 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(b, user_pk,
# Multiple outputs
# Mix: one output with a single owners_after, one output with multiple
# owners_after
def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk,
def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(alice, b, user_pk,
user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.transaction import _fulfillment_to_details
# CREATE divisible asset
tx_create = Transaction.create([b.me], [([user_pk], 50), ([user_pk, b.me], 50)],
tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)],
asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create_signed = tx_create.sign([alice.private_key])
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 50), ([b.me, user_pk], 50)],
[([alice.public_key], 50), ([alice.public_key, user_pk], 50)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])
tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk])
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
@ -407,15 +408,15 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk,
# Single owners_before
# Single output
# Single owners_after
def test_multiple_in_different_transactions(b, user_pk, user_sk):
def test_multiple_in_different_transactions(alice, b, user_pk, user_sk):
from bigchaindb.models import Transaction
# CREATE divisible asset
# `b` creates a divisible asset and assigns 50 shares to `b` and
# 50 shares to `user_pk`
tx_create = Transaction.create([b.me], [([user_pk], 50), ([b.me], 50)],
tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([alice.public_key], 50)],
asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create_signed = tx_create.sign([alice.private_key])
# TRANSFER divisible asset
# `b` transfers its 50 shares to `user_pk`
@ -424,14 +425,14 @@ def test_multiple_in_different_transactions(b, user_pk, user_sk):
tx_transfer1 = Transaction.transfer(tx_create.to_inputs([1]),
[([user_pk], 50)],
asset_id=tx_create.id)
tx_transfer1_signed = tx_transfer1.sign([b.me_private])
tx_transfer1_signed = tx_transfer1.sign([alice.private_key])
# TRANSFER
# `user_pk` combines two different transaction with 50 shares each and
# transfers a total of 100 shares back to `b`
tx_transfer2 = Transaction.transfer(tx_create.to_inputs([0]) +
tx_transfer1.to_inputs([0]),
[([b.me], 100)],
[([alice.private_key], 100)],
asset_id=tx_create.id)
tx_transfer2_signed = tx_transfer2.sign([user_sk])
@ -451,19 +452,19 @@ def test_multiple_in_different_transactions(b, user_pk, user_sk):
# In a TRANSFER transaction of a divisible asset the amount being spent in the
# inputs needs to match the amount being sent in the outputs.
# In other words `amount_in_inputs - amount_in_outputs == 0`
def test_amount_error_transfer(b, user_pk, user_sk):
def test_amount_error_transfer(alice, b, user_pk, user_sk):
from bigchaindb.models import Transaction
from bigchaindb.common.exceptions import AmountError
# CREATE divisible asset
tx_create = Transaction.create([b.me], [([user_pk], 100)], asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()})
tx_create_signed = tx_create.sign([alice.private_key])
b.store_bulk_transactions([tx_create_signed])
# TRANSFER
# output amount less than input amount
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 50)],
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 50)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
@ -472,7 +473,7 @@ def test_amount_error_transfer(b, user_pk, user_sk):
# TRANSFER
# output amount greater than input amount
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 101)],
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 101)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
@ -480,7 +481,7 @@ def test_amount_error_transfer(b, user_pk, user_sk):
tx_transfer_signed.validate(b)
def test_threshold_same_public_key(b, user_pk, user_sk):
def test_threshold_same_public_key(alice, b, user_pk, user_sk):
# If we try to fulfill a threshold condition where each subcondition has
# the same key get_subcondition_from_vk will always return the first
# subcondition. This means that only the 1st subfulfillment will be
@ -491,12 +492,12 @@ def test_threshold_same_public_key(b, user_pk, user_sk):
from bigchaindb.models import Transaction
# CREATE divisible asset
tx_create = Transaction.create([b.me], [([user_pk, user_pk], 100)],
tx_create = Transaction.create([alice.public_key], [([user_pk, user_pk], 100)],
asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create_signed = tx_create.sign([alice.private_key])
# TRANSFER
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk, user_sk])
@ -505,17 +506,17 @@ def test_threshold_same_public_key(b, user_pk, user_sk):
assert tx_transfer_signed.validate(b) == tx_transfer_signed
def test_sum_amount(b, user_pk, user_sk):
def test_sum_amount(alice, b, user_pk, user_sk):
from bigchaindb.models import Transaction
# CREATE divisible asset with 3 outputs with amount 1
tx_create = Transaction.create([b.me], [([user_pk], 1), ([user_pk], 1), ([user_pk], 1)],
tx_create = Transaction.create([alice.public_key], [([user_pk], 1), ([user_pk], 1), ([user_pk], 1)],
asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create_signed = tx_create.sign([alice.private_key])
# create a transfer transaction with one output and check if the amount
# is 3
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 3)],
tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 3)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])
@ -526,17 +527,17 @@ def test_sum_amount(b, user_pk, user_sk):
assert tx_transfer_signed.outputs[0].amount == 3
def test_divide(b, user_pk, user_sk):
def test_divide(alice, b, user_pk, user_sk):
from bigchaindb.models import Transaction
# CREATE divisible asset with 1 output with amount 3
tx_create = Transaction.create([b.me], [([user_pk], 3)], asset={'name': random.random()})
tx_create_signed = tx_create.sign([b.me_private])
tx_create = Transaction.create([alice.public_key], [([user_pk], 3)], asset={'name': random.random()})
tx_create_signed = tx_create.sign([alice.private_key])
# create a transfer transaction with 3 outputs and check if the amount
# of each output is 1
tx_transfer = Transaction.transfer(tx_create.to_inputs(),
[([b.me], 1), ([b.me], 1), ([b.me], 1)],
[([alice.public_key], 1), ([alice.public_key], 1), ([alice.public_key], 1)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([user_sk])

View File

@ -35,7 +35,6 @@ def mock_generate_key_pair(monkeypatch):
@pytest.fixture
def mock_bigchaindb_backup_config(monkeypatch):
config = {
'keypair': {},
'database': {'host': 'host', 'port': 12345, 'name': 'adbname'},
}
monkeypatch.setattr('bigchaindb._config', config)

View File

@ -63,7 +63,6 @@ def test_bigchain_show_config(capsys):
# and run_show_config updates the bigchaindb.config
from bigchaindb import config
del config['CONFIGURED']
config['keypair']['private'] = 'x' * 45
assert output_config == config
@ -281,7 +280,7 @@ def test_recover_db_on_start(mock_autoconfigure,
mock_start,
mocked_setup_logging):
from bigchaindb.commands.bigchaindb import run_start
args = Namespace(start_rethinkdb=False, allow_temp_keypair=False, config=None, yes=True,
args = Namespace(config=None, yes=True,
skip_initialize_database=False)
run_start(args)

View File

@ -106,10 +106,6 @@ def _configure_bigchaindb(request):
config = {
'database': bigchaindb._database_map[backend],
'keypair': {
'private': '31Lb1ZGKTyHnmVK3LUMrAUrPNfd4sE2YyBt3UA4A25aA',
'public': '4XYfCbabAWVUCbjTmRTFEu2sc3dFEdkse4r6X498B1s8',
}
}
config['database']['name'] = test_db_name
config = config_utils.env_config(config)
@ -275,15 +271,15 @@ def tb():
@pytest.fixture
def create_tx(b, user_pk):
def create_tx(alice, user_pk):
from bigchaindb.models import Transaction
name = f'I am created by the create_tx fixture. My random identifier is {random.random()}.'
return Transaction.create([b.me], [([user_pk], 1)], asset={'name': name})
return Transaction.create([alice.public_key], [([user_pk], 1)], asset={'name': name})
@pytest.fixture
def signed_create_tx(b, create_tx):
return create_tx.sign([b.me_private])
def signed_create_tx(alice, create_tx):
return create_tx.sign([alice.private_key])
@pytest.mark.abci
@ -332,17 +328,16 @@ def _get_height(b):
@pytest.fixture
def inputs(user_pk, b):
def inputs(user_pk, b, alice):
from bigchaindb.models import Transaction
# create blocks with transactions for `USER` to spend
for block in range(4):
transactions = [
Transaction.create(
[b.me],
[alice_pubkey(alice)],
[([user_pk], 1)],
metadata={'msg': random.random()},
).sign([b.me_private]).to_dict()
).sign([alice_privkey(alice)]).to_dict()
for _ in range(10)
]
block = Block(app_hash='', height=_get_height(b), transactions=transactions)
@ -350,17 +345,17 @@ def inputs(user_pk, b):
@pytest.fixture
def inputs_shared(user_pk, user2_pk):
def inputs_shared(user_pk, user2_pk, alice):
from bigchaindb.models import Transaction
# create blocks with transactions for `USER` to spend
for block in range(4):
transactions = [
Transaction.create(
[b.me],
[alice.public_key],
[user_pk, user2_pk],
metadata={'msg': random.random()},
).sign([b.me_private]).to_dict()
).sign([alice.private_key]).to_dict()
for _ in range(10)
]
block = Block(app_hash='', height=_get_height(b), transaction=transactions)

View File

@ -14,35 +14,17 @@ def test_remove_unclosed_sockets():
pass
# TODO: Get rid of this and move to conftest
def dummy_tx():
import bigchaindb
from bigchaindb.models import Transaction
b = bigchaindb.Bigchain()
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
return tx
# TODO: Get rid of this and move to conftest
def dummy_block():
import bigchaindb
b = bigchaindb.Bigchain()
block = b.create_block([dummy_tx()])
return block
class TestBigchainApi(object):
@pytest.mark.genesis
def test_get_last_voted_block_cyclic_blockchain(self, b, monkeypatch):
def test_get_last_voted_block_cyclic_blockchain(self, b, monkeypatch, alice):
from bigchaindb.common.crypto import PrivateKey
from bigchaindb.common.exceptions import CyclicBlockchainError
from bigchaindb.common.utils import serialize
from bigchaindb.models import Transaction
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)])
tx = tx.sign([alice.private_key])
monkeypatch.setattr('time.time', lambda: 1)
block1 = b.create_block([tx])
b.write_block(block1)
@ -51,7 +33,7 @@ class TestBigchainApi(object):
vote = b.vote(block1.id, b.get_last_voted_block().id, True)
vote['vote']['previous_block'] = block1.id
vote_data = serialize(vote['vote'])
vote['signature'] = PrivateKey(b.me_private).sign(vote_data.encode())
vote['signature'] = PrivateKey(alice.private_key).sign(vote_data.encode())
b.write_vote(vote)
with pytest.raises(CyclicBlockchainError):
@ -59,12 +41,12 @@ class TestBigchainApi(object):
@pytest.mark.genesis
def test_try_voting_while_constructing_cyclic_blockchain(self, b,
monkeypatch):
monkeypatch, alice):
from bigchaindb.common.exceptions import CyclicBlockchainError
from bigchaindb.models import Transaction
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)])
tx = tx.sign([alice.private_key])
block1 = b.create_block([tx])
# We can simply submit twice the same block id and check if `Bigchain`
@ -73,11 +55,11 @@ class TestBigchainApi(object):
b.vote(block1.id, block1.id, True)
@pytest.mark.genesis
def test_has_previous_vote_when_already_voted(self, b, monkeypatch):
def test_has_previous_vote_when_already_voted(self, b, monkeypatch, alice):
from bigchaindb.models import Transaction
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)])
tx = tx.sign([alice.private_key])
monkeypatch.setattr('time.time', lambda: 1)
block = b.create_block([tx])
@ -91,28 +73,28 @@ class TestBigchainApi(object):
assert b.has_previous_vote(block.id) is True
@pytest.mark.genesis
def test_get_spent_with_double_inclusion_detected(self, b, monkeypatch):
def test_get_spent_with_double_inclusion_detected(self, b, monkeypatch, alice):
from bigchaindb.exceptions import CriticalDoubleInclusion
from bigchaindb.models import Transaction
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)])
tx = tx.sign([alice.private_key])
monkeypatch.setattr('time.time', lambda: 1000000000)
block1 = b.create_block([tx])
b.write_block(block1)
monkeypatch.setattr('time.time', lambda: 1000000020)
transfer_tx = Transaction.transfer(tx.to_inputs(), [([b.me], 1)],
transfer_tx = Transaction.transfer(tx.to_inputs(), [([alice.public_key], 1)],
asset_id=tx.id)
transfer_tx = transfer_tx.sign([b.me_private])
transfer_tx = transfer_tx.sign([alice.private_key])
block2 = b.create_block([transfer_tx])
b.write_block(block2)
monkeypatch.setattr('time.time', lambda: 1000000030)
transfer_tx2 = Transaction.transfer(tx.to_inputs(), [([b.me], 1)],
transfer_tx2 = Transaction.transfer(tx.to_inputs(), [([alice.public_key], 1)],
asset_id=tx.id)
transfer_tx2 = transfer_tx2.sign([b.me_private])
transfer_tx2 = transfer_tx2.sign([alice.private_key])
block3 = b.create_block([transfer_tx2])
b.write_block(block3)
@ -126,28 +108,28 @@ class TestBigchainApi(object):
b.get_spent(tx.id, 0)
@pytest.mark.genesis
def test_get_spent_with_double_spend_detected(self, b, monkeypatch):
def test_get_spent_with_double_spend_detected(self, b, monkeypatch, alice):
from bigchaindb.exceptions import CriticalDoubleSpend
from bigchaindb.models import Transaction
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)])
tx = tx.sign([alice.private_key])
monkeypatch.setattr('time.time', lambda: 1000000000)
block1 = b.create_block([tx])
b.write_block(block1)
monkeypatch.setattr('time.time', lambda: 1000000020)
transfer_tx = Transaction.transfer(tx.to_inputs(), [([b.me], 1)],
transfer_tx = Transaction.transfer(tx.to_inputs(), [([alice.public_key], 1)],
asset_id=tx.id)
transfer_tx = transfer_tx.sign([b.me_private])
transfer_tx = transfer_tx.sign([alice.private_key])
block2 = b.create_block([transfer_tx])
b.write_block(block2)
monkeypatch.setattr('time.time', lambda: 1000000030)
transfer_tx2 = Transaction.transfer(tx.to_inputs(), [([b.me], 2)],
transfer_tx2 = Transaction.transfer(tx.to_inputs(), [([alice.public_key], 2)],
asset_id=tx.id)
transfer_tx2 = transfer_tx2.sign([b.me_private])
transfer_tx2 = transfer_tx2.sign([alice.private_key])
block3 = b.create_block([transfer_tx2])
b.write_block(block3)
@ -161,12 +143,12 @@ class TestBigchainApi(object):
b.get_spent(tx.id, 0)
@pytest.mark.genesis
def test_get_block_status_for_tx_with_double_inclusion(self, b, monkeypatch):
def test_get_block_status_for_tx_with_double_inclusion(self, b, monkeypatch, alice):
from bigchaindb.exceptions import CriticalDoubleInclusion
from bigchaindb.models import Transaction
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)])
tx = tx.sign([alice.private_key])
monkeypatch.setattr('time.time', lambda: 1000000000)
block1 = b.create_block([tx])
@ -186,20 +168,20 @@ class TestBigchainApi(object):
b.get_blocks_status_containing_tx(tx.id)
@pytest.mark.genesis
def test_get_transaction_in_invalid_and_valid_block(self, monkeypatch, b):
def test_get_transaction_in_invalid_and_valid_block(self, monkeypatch, b, alice):
from bigchaindb.models import Transaction
monkeypatch.setattr('time.time', lambda: 1000000000)
tx1 = Transaction.create([b.me], [([b.me], 1)],
tx1 = Transaction.create([alice.public_key], [([alice.public_key], 1)],
metadata={'msg': 1})
tx1 = tx1.sign([b.me_private])
tx1 = tx1.sign([alice.private_key])
block1 = b.create_block([tx1])
b.write_block(block1)
monkeypatch.setattr('time.time', lambda: 1000000020)
tx2 = Transaction.create([b.me], [([b.me], 1)],
tx2 = Transaction.create([alice.public_key], [([alice.public_key], 1)],
metadata={'msg': 2})
tx2 = tx2.sign([b.me_private])
tx2 = tx2.sign([alice.private_key])
block2 = b.create_block([tx2])
b.write_block(block2)
@ -215,7 +197,7 @@ class TestBigchainApi(object):
assert b.get_transaction(tx2.id) == tx2
@pytest.mark.genesis
def test_text_search(self, b):
def test_text_search(self, b, alice):
from bigchaindb.models import Transaction
from bigchaindb.backend.exceptions import OperationError
from bigchaindb.backend.localmongodb.connection import LocalMongoDBConnection
@ -226,12 +208,12 @@ class TestBigchainApi(object):
asset3 = {'msg': 'BigchainDB 3'}
# create the transactions
tx1 = Transaction.create([b.me], [([b.me], 1)],
asset=asset1).sign([b.me_private])
tx2 = Transaction.create([b.me], [([b.me], 1)],
asset=asset2).sign([b.me_private])
tx3 = Transaction.create([b.me], [([b.me], 1)],
asset=asset3).sign([b.me_private])
tx1 = Transaction.create([alice.public_key], [([alice.public_key], 1)],
asset=asset1).sign([alice.private_key])
tx2 = Transaction.create([alice.public_key], [([alice.public_key], 1)],
asset=asset2).sign([alice.private_key])
tx3 = Transaction.create([alice.public_key], [([alice.public_key], 1)],
asset=asset3).sign([alice.private_key])
# create the block
block = b.create_block([tx1, tx2, tx3])
@ -251,7 +233,7 @@ class TestBigchainApi(object):
assert len(assets) == 3
@pytest.mark.genesis
def test_text_search_returns_valid_only(self, monkeypatch, b):
def test_text_search_returns_valid_only(self, monkeypatch, b, alice):
from bigchaindb.models import Transaction
from bigchaindb.backend.exceptions import OperationError
from bigchaindb.backend.localmongodb.connection import LocalMongoDBConnection
@ -260,16 +242,16 @@ class TestBigchainApi(object):
asset_invalid = {'msg': 'Goodbye BigchainDB!'}
monkeypatch.setattr('time.time', lambda: 1000000000)
tx1 = Transaction.create([b.me], [([b.me], 1)],
tx1 = Transaction.create([alice.public_key], [([alice.public_key], 1)],
asset=asset_valid)
tx1 = tx1.sign([b.me_private])
tx1 = tx1.sign([alice.private_key])
block1 = b.create_block([tx1])
b.write_block(block1)
monkeypatch.setattr('time.time', lambda: 1000000020)
tx2 = Transaction.create([b.me], [([b.me], 1)],
tx2 = Transaction.create([alice.public_key], [([alice.public_key], 1)],
asset=asset_invalid)
tx2 = tx2.sign([b.me_private])
tx2 = tx2.sign([alice.private_key])
block2 = b.create_block([tx2])
b.write_block(block2)
@ -451,15 +433,6 @@ class TestBigchainApi(object):
assert excinfo.value.args[0] == 'Empty block creation is not allowed'
@pytest.mark.usefixtures('inputs')
def test_get_block_by_id(self, b):
new_block = dummy_block()
b.write_block(new_block)
assert b.get_block(new_block.id) == new_block.to_dict()
block, status = b.get_block(new_block.id, include_status=True)
assert status == b.BLOCK_UNDECIDED
@pytest.mark.genesis
def test_get_last_voted_block_returns_genesis_if_no_votes_has_been_casted(self, b):
from bigchaindb.models import Block
@ -471,111 +444,6 @@ class TestBigchainApi(object):
assert gb == genesis
assert b.validate_block(gb) == gb
def test_get_last_voted_block_returns_the_correct_block_same_timestamp(self,
b,
monkeypatch,
genesis_block):
assert b.get_last_voted_block() == genesis_block
monkeypatch.setattr('time.time', lambda: 1)
block_1 = dummy_block()
monkeypatch.setattr('time.time', lambda: 2)
block_2 = dummy_block()
monkeypatch.setattr('time.time', lambda: 3)
block_3 = dummy_block()
b.write_block(block_1)
b.write_block(block_2)
b.write_block(block_3)
# make sure all the votes are written with the same timestamps
monkeypatch.setattr('time.time', lambda: 4)
b.write_vote(b.vote(block_1.id, b.get_last_voted_block().id, True))
assert b.get_last_voted_block().id == block_1.id
b.write_vote(b.vote(block_2.id, b.get_last_voted_block().id, True))
assert b.get_last_voted_block().id == block_2.id
b.write_vote(b.vote(block_3.id, b.get_last_voted_block().id, True))
assert b.get_last_voted_block().id == block_3.id
def test_get_last_voted_block_returns_the_correct_block_different_timestamps(self,
b,
monkeypatch,
genesis_block):
assert b.get_last_voted_block() == genesis_block
monkeypatch.setattr('time.time', lambda: 1)
block_1 = dummy_block()
monkeypatch.setattr('time.time', lambda: 2)
block_2 = dummy_block()
monkeypatch.setattr('time.time', lambda: 3)
block_3 = dummy_block()
b.write_block(block_1)
b.write_block(block_2)
b.write_block(block_3)
# make sure all the votes are written with different timestamps
monkeypatch.setattr('time.time', lambda: 4)
b.write_vote(b.vote(block_1.id, b.get_last_voted_block().id, True))
assert b.get_last_voted_block().id == block_1.id
monkeypatch.setattr('time.time', lambda: 5)
b.write_vote(b.vote(block_2.id, b.get_last_voted_block().id, True))
assert b.get_last_voted_block().id == block_2.id
monkeypatch.setattr('time.time', lambda: 6)
b.write_vote(b.vote(block_3.id, b.get_last_voted_block().id, True))
assert b.get_last_voted_block().id == block_3.id
@pytest.mark.usefixtures('inputs')
def test_assign_transaction_one_node(self, b, user_pk, user_sk):
from bigchaindb.backend import query
from bigchaindb.models import Transaction
input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)],
asset_id=input_tx.id)
tx = tx.sign([user_sk])
b.write_transaction(tx)
# retrieve the transaction
response = list(query.get_stale_transactions(b.connection))[0]
# check if the assignee is the current node
assert response['assignee'] == b.me
@pytest.mark.usefixtures('inputs')
def test_assign_transaction_multiple_nodes(self, b, user_pk, user_sk):
from bigchaindb.backend import query
from bigchaindb.common.crypto import generate_key_pair
from bigchaindb.models import Transaction
# create 5 federation nodes
for _ in range(5):
b.nodes_except_me.append(generate_key_pair()[1])
# test assignee for several transactions
for i in range(20):
input_tx = b.get_owned_ids(user_pk).pop()
input_tx = b.get_transaction(input_tx.txid)
inputs = input_tx.to_inputs()
tx = Transaction.transfer(inputs, [([user_pk], 1)],
asset_id=input_tx.id,
metadata={'msg': i})
tx = tx.sign([user_sk])
b.write_transaction(tx)
# retrieve the transaction
response = query.get_stale_transactions(b.connection)
# check if the assignee is one of the _other_ federation nodes
for tx in response:
assert tx['assignee'] in b.nodes_except_me
@pytest.mark.usefixtures('inputs')
def test_non_create_input_not_found(self, b, user_pk):
from cryptoconditions import Ed25519Sha256
@ -594,14 +462,14 @@ class TestBigchainApi(object):
with pytest.raises(InputDoesNotExist):
tx.validate(Bigchain())
def test_count_backlog(self, b, user_pk):
def test_count_backlog(self, b, user_pk, alice):
from bigchaindb.backend import query
from bigchaindb.models import Transaction
for i in range(4):
tx = Transaction.create([b.me], [([user_pk], 1)],
tx = Transaction.create([alice.public_key], [([user_pk], 1)],
metadata={'msg': i}) \
.sign([b.me_private])
.sign([alice.private_key])
b.write_transaction(tx)
assert query.count_backlog(b.connection) == 4
@ -712,86 +580,6 @@ class TestTransactionValidation(object):
b.validate_transaction(tx_invalid)
class TestBlockValidation(object):
@pytest.mark.skipif(reason='Separated tx validation from block creation.')
@pytest.mark.usefixtures('inputs')
def test_invalid_transactions_in_block(self, b, user_pk):
from bigchaindb import utils
from bigchaindb.common import crypto
from bigchaindb.common.exceptions import TransactionOwnerError
from bigchaindb.common.utils import gen_timestamp
# invalid transaction
valid_input = b.get_owned_ids(user_pk).pop()
tx_invalid = b.create_transaction('a', 'b', valid_input, 'c')
block = b.create_block([tx_invalid])
# create a block with invalid transactions
block = {
'timestamp': gen_timestamp(),
'transactions': [tx_invalid],
'node_pubkey': b.me,
'voters': b.nodes_except_me
}
# NOTE: This is not the correct function anymore, but this test is
# skipped
block_data = utils.serialize_block(block)
block_hash = crypto.hash_data(block_data)
block_signature = crypto.PrivateKey(b.me_private).sign(block_data)
block = {
'id': block_hash,
'block': block,
'signature': block_signature,
'votes': []
}
with pytest.raises(TransactionOwnerError) as excinfo:
# TODO: Adjust this to the new Block model (test is currently
# skipped.
b.validate_block(block)
assert excinfo.value.args[0] == 'owner_before `a` does not own the input `{}`'.format(valid_input)
def test_invalid_signature(self, b):
from bigchaindb.common.exceptions import InvalidSignature
from bigchaindb.common import crypto
# create a valid block
block = dummy_block()
# replace the block signature with an invalid one
block.signature = crypto.PrivateKey(b.me_private).sign(b'wrongdata')
# check that validate_block raises an InvalidSignature exception
with pytest.raises(InvalidSignature):
b.validate_block(block)
def test_invalid_node_pubkey(self, b):
from bigchaindb.common.exceptions import SybilError
from bigchaindb.common import crypto
# blocks can only be created by a federation node
# create a valid block
block = dummy_block()
# create some temp keys
tmp_sk, tmp_pk = crypto.generate_key_pair()
# change the block node_pubkey
block.node_pubkey = tmp_pk
# just to make sure lets re-hash the block and create a valid signature
# from a non federation node
block = block.sign(tmp_sk)
# check that validate_block raises an SybilError
with pytest.raises(SybilError):
b.validate_block(block)
class TestMultipleInputs(object):
def test_transfer_single_owner_single_input(self, b, inputs, user_pk,
user_sk):
@ -836,15 +624,16 @@ class TestMultipleInputs(object):
@pytest.mark.usefixtures('inputs')
def test_multiple_owners_before_single_owner_after_single_input(self, b,
user_sk,
user_pk):
user_pk,
alice):
from bigchaindb.common import crypto
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
user3_sk, user3_pk = crypto.generate_key_pair()
tx = Transaction.create([b.me], [([user_pk, user2_pk], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)])
tx = tx.sign([alice.private_key])
block = b.create_block([tx])
b.write_block(block)
@ -868,7 +657,8 @@ class TestMultipleInputs(object):
@pytest.mark.usefixtures('inputs')
def test_multiple_owners_before_multiple_owners_after_single_input(self, b,
user_sk,
user_pk):
user_pk,
alice):
from bigchaindb.common import crypto
from bigchaindb.models import Transaction
@ -876,8 +666,8 @@ class TestMultipleInputs(object):
user3_sk, user3_pk = crypto.generate_key_pair()
user4_sk, user4_pk = crypto.generate_key_pair()
tx = Transaction.create([b.me], [([user_pk, user2_pk], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)])
tx = tx.sign([alice.private_key])
block = b.create_block([tx])
b.write_block(block)
@ -898,15 +688,15 @@ class TestMultipleInputs(object):
assert len(tx.inputs) == 1
assert len(tx.outputs) == 1
def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_pk):
def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_pk, alice):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import TransactionLink
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
tx = Transaction.create([b.me], [([user_pk], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([user_pk], 1)])
tx = tx.sign([alice.private_key])
block = b.create_block([tx])
b.write_block(block)
@ -929,15 +719,16 @@ class TestMultipleInputs(object):
def test_get_owned_ids_single_tx_single_output_invalid_block(self, b,
user_sk,
user_pk,
genesis_block):
genesis_block,
alice):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import TransactionLink
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
tx = Transaction.create([b.me], [([user_pk], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([user_pk], 1)])
tx = tx.sign([alice.private_key])
block = b.create_block([tx])
b.write_block(block)
@ -970,7 +761,7 @@ class TestMultipleInputs(object):
assert owned_inputs_user2 == []
def test_get_owned_ids_single_tx_multiple_outputs(self, b, user_sk,
user_pk):
user_pk, alice):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import TransactionLink
from bigchaindb.models import Transaction
@ -978,8 +769,8 @@ class TestMultipleInputs(object):
user2_sk, user2_pk = crypto.generate_key_pair()
# create divisible asset
tx_create = Transaction.create([b.me], [([user_pk], 1), ([user_pk], 1)])
tx_create_signed = tx_create.sign([b.me_private])
tx_create = Transaction.create([alice.public_key], [([user_pk], 1), ([user_pk], 1)])
tx_create_signed = tx_create.sign([alice.private_key])
block = b.create_block([tx_create_signed])
b.write_block(block)
@ -1006,7 +797,7 @@ class TestMultipleInputs(object):
assert owned_inputs_user2 == [TransactionLink(tx_transfer.id, 0),
TransactionLink(tx_transfer.id, 1)]
def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk):
def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk, alice):
from bigchaindb.common import crypto
from bigchaindb.common.transaction import TransactionLink
from bigchaindb.models import Transaction
@ -1014,8 +805,8 @@ class TestMultipleInputs(object):
user2_sk, user2_pk = crypto.generate_key_pair()
user3_sk, user3_pk = crypto.generate_key_pair()
tx = Transaction.create([b.me], [([user_pk, user2_pk], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)])
tx = tx.sign([alice.private_key])
block = b.create_block([tx])
b.write_block(block)
@ -1037,14 +828,14 @@ class TestMultipleInputs(object):
assert owned_inputs_user1 == owned_inputs_user2
assert owned_inputs_user1 == []
def test_get_spent_single_tx_single_output(self, b, user_sk, user_pk):
def test_get_spent_single_tx_single_output(self, b, user_sk, user_pk, alice):
from bigchaindb.common import crypto
from bigchaindb.models import Transaction
user2_sk, user2_pk = crypto.generate_key_pair()
tx = Transaction.create([b.me], [([user_pk], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([user_pk], 1)])
tx = tx.sign([alice.private_key])
block = b.create_block([tx])
b.write_block(block)
@ -1069,15 +860,16 @@ class TestMultipleInputs(object):
def test_get_spent_single_tx_single_output_invalid_block(self, b,
user_sk,
user_pk,
genesis_block):
genesis_block,
alice):
from bigchaindb.common import crypto
from bigchaindb.models import Transaction
# create a new users
user2_sk, user2_pk = crypto.generate_key_pair()
tx = Transaction.create([b.me], [([user_pk], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([user_pk], 1)])
tx = tx.sign([alice.private_key])
block = b.create_block([tx])
b.write_block(block)
@ -1110,7 +902,7 @@ class TestMultipleInputs(object):
# Now there should be no spents (the block is invalid)
assert spent_inputs_user1 is None
def test_get_spent_single_tx_multiple_outputs(self, b, user_sk, user_pk):
def test_get_spent_single_tx_multiple_outputs(self, b, user_sk, user_pk, alice):
from bigchaindb.common import crypto
from bigchaindb.models import Transaction
@ -1118,11 +910,11 @@ class TestMultipleInputs(object):
user2_sk, user2_pk = crypto.generate_key_pair()
# create a divisible asset with 3 outputs
tx_create = Transaction.create([b.me],
tx_create = Transaction.create([alice.public_key],
[([user_pk], 1),
([user_pk], 1),
([user_pk], 1)])
tx_create_signed = tx_create.sign([b.me_private])
tx_create_signed = tx_create.sign([alice.private_key])
block = b.create_block([tx_create_signed])
b.write_block(block)
@ -1149,7 +941,7 @@ class TestMultipleInputs(object):
# spendable by BigchainDB
assert b.get_spent(tx_create.to_inputs()[2].fulfills.txid, 2) is None
def test_get_spent_multiple_owners(self, b, user_sk, user_pk):
def test_get_spent_multiple_owners(self, b, user_sk, user_pk, alice):
from bigchaindb.common import crypto
from bigchaindb.models import Transaction
@ -1159,9 +951,9 @@ class TestMultipleInputs(object):
transactions = []
for i in range(3):
payload = {'somedata': i}
tx = Transaction.create([b.me], [([user_pk, user2_pk], 1)],
tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)],
payload)
tx = tx.sign([b.me_private])
tx = tx.sign([alice.private_key])
transactions.append(tx)
block = b.create_block(transactions)
b.write_block(block)
@ -1239,7 +1031,7 @@ def test_get_outputs_filtered(filter_spent, filter_unspent):
@pytest.mark.bdb
def test_cant_spend_same_input_twice_in_tx(b, genesis_block):
def test_cant_spend_same_input_twice_in_tx(b, genesis_block, alice):
"""Recreate duplicated fulfillments bug
https://github.com/bigchaindb/bigchaindb/issues/1099
"""
@ -1247,8 +1039,8 @@ def test_cant_spend_same_input_twice_in_tx(b, genesis_block):
from bigchaindb.common.exceptions import DoubleSpend
# create a divisible asset
tx_create = Transaction.create([b.me], [([b.me], 100)])
tx_create_signed = tx_create.sign([b.me_private])
tx_create = Transaction.create([alice.public_key], [([alice.public_key], 100)])
tx_create_signed = tx_create.sign([alice.private_key])
assert b.validate_transaction(tx_create_signed) == tx_create_signed
# create a block and valid vote
@ -1259,15 +1051,15 @@ def test_cant_spend_same_input_twice_in_tx(b, genesis_block):
# Create a transfer transaction with duplicated fulfillments
dup_inputs = tx_create.to_inputs() + tx_create.to_inputs()
tx_transfer = Transaction.transfer(dup_inputs, [([b.me], 200)],
tx_transfer = Transaction.transfer(dup_inputs, [([alice.public_key], 200)],
asset_id=tx_create.id)
tx_transfer_signed = tx_transfer.sign([b.me_private])
tx_transfer_signed = tx_transfer.sign([alice.private_key])
with pytest.raises(DoubleSpend):
tx_transfer_signed.validate(b)
@pytest.mark.bdb
def test_transaction_unicode(b):
def test_transaction_unicode(b, alice):
from bigchaindb.common.utils import serialize
from bigchaindb.models import Transaction
@ -1275,8 +1067,8 @@ def test_transaction_unicode(b):
beer_python = {'beer': '\N{BEER MUG}'}
beer_json = '{"beer":"\N{BEER MUG}"}'
tx = (Transaction.create([b.me], [([b.me], 100)], beer_python)
).sign([b.me_private])
tx = (Transaction.create([alice.public_key], [([alice.public_key], 100)], beer_python)
).sign([alice.private_key])
block = b.create_block([tx])
b.write_block(block)
assert b.get_block(block.id) == block.to_dict()
@ -1285,12 +1077,12 @@ def test_transaction_unicode(b):
@pytest.mark.bdb
def test_is_new_transaction(b, genesis_block):
def test_is_new_transaction(b, genesis_block, alice):
from bigchaindb.models import Transaction
def write_tx(n):
tx = Transaction.create([b.me], [([b.me], n)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], n)])
tx = tx.sign([alice.private_key])
# Tx is new because it's not in any block
assert b.is_new_transaction(tx.id)

View File

@ -21,18 +21,18 @@ class TestBlockModel(object):
Block(None, 'valid node_pubkey', 'valid timestamp',
'not a list or None')
def test_block_serialization(self, b):
def test_block_serialization(self, b, alice):
from bigchaindb.common.crypto import hash_data
from bigchaindb.common.utils import gen_timestamp, serialize
from bigchaindb.models import Block, Transaction
transactions = [Transaction.create([b.me], [([b.me], 1)])]
transactions = [Transaction.create([alice.public_key], [([alice.public_key], 1)])]
timestamp = gen_timestamp()
voters = ['Qaaa', 'Qbbb']
expected_block = {
'timestamp': timestamp,
'transactions': [tx.to_dict() for tx in transactions],
'node_pubkey': b.me,
'node_pubkey': alice.public_key,
'voters': voters,
}
expected = {
@ -41,7 +41,7 @@ class TestBlockModel(object):
'signature': None,
}
block = Block(transactions, b.me, timestamp, voters)
block = Block(transactions, alice.public_key, timestamp, voters)
assert block.to_dict() == expected
@ -52,21 +52,21 @@ class TestBlockModel(object):
with raises(ValueError):
block.to_dict()
def test_block_deserialization(self, b):
def test_block_deserialization(self, b, alice):
from bigchaindb.common.crypto import hash_data
from bigchaindb.common.utils import gen_timestamp, serialize
from bigchaindb.models import Block, Transaction
transaction = Transaction.create([b.me], [([b.me], 1)])
transaction.sign([b.me_private])
transaction = Transaction.create([alice.public_key], [([alice.public_key], 1)])
transaction.sign([alice.private_key])
timestamp = gen_timestamp()
voters = ['Qaaa', 'Qbbb']
expected = Block([transaction], b.me, timestamp, voters)
expected = Block([transaction], alice.public_key, timestamp, voters)
block = {
'timestamp': timestamp,
'transactions': [transaction.to_dict()],
'node_pubkey': b.me,
'node_pubkey': alice.public_key,
'voters': voters,
}
@ -78,34 +78,34 @@ class TestBlockModel(object):
assert expected == Block.from_dict(block_body)
def test_block_invalid_id_deserialization(self, b):
def test_block_invalid_id_deserialization(self, b, alice):
from bigchaindb.common.exceptions import InvalidHash
from bigchaindb.models import Block
block = {
'id': 'an invalid id',
'block': {
'node_pubkey': b.me,
'node_pubkey': alice.public_key,
}
}
with raises(InvalidHash):
Block.from_dict(block)
def test_block_invalid_signature(self, b):
def test_block_invalid_signature(self, b, alice):
from bigchaindb.common.crypto import hash_data
from bigchaindb.common.exceptions import InvalidSignature
from bigchaindb.common.utils import gen_timestamp, serialize
from bigchaindb.models import Block, Transaction
transaction = Transaction.create([b.me], [([b.me], 1)])
transaction.sign([b.me_private])
transaction = Transaction.create([alice.public_key], [([alice.public_key], 1)])
transaction.sign([alice.private_key])
timestamp = gen_timestamp()
block = {
'timestamp': timestamp,
'transactions': [transaction.to_dict()],
'node_pubkey': b.me,
'node_pubkey': alice.public_key,
'voters': list(b.federation),
}
@ -118,46 +118,46 @@ class TestBlockModel(object):
with raises(InvalidSignature):
Block.from_dict(block_body).validate(b)
def test_compare_blocks(self, b):
def test_compare_blocks(self, b, alice):
from bigchaindb.models import Block, Transaction
transactions = [Transaction.create([b.me], [([b.me], 1)])]
transactions = [Transaction.create([alice.public_key], [([alice.public_key], 1)])]
assert Block() != 'invalid comparison'
assert Block(transactions) == Block(transactions)
def test_sign_block(self, b):
def test_sign_block(self, b, alice):
from bigchaindb.common.crypto import PrivateKey, PublicKey
from bigchaindb.common.utils import gen_timestamp, serialize
from bigchaindb.models import Block, Transaction
transactions = [Transaction.create([b.me], [([b.me], 1)])]
transactions = [Transaction.create([alice.public_key], [([alice.public_key], 1)])]
timestamp = gen_timestamp()
voters = ['Qaaa', 'Qbbb']
expected_block = {
'timestamp': timestamp,
'transactions': [tx.to_dict() for tx in transactions],
'node_pubkey': b.me,
'node_pubkey': alice.public_key,
'voters': voters,
}
expected_block_serialized = serialize(expected_block).encode()
expected = PrivateKey(b.me_private).sign(expected_block_serialized)
block = Block(transactions, b.me, timestamp, voters)
block = block.sign(b.me_private)
expected = PrivateKey(alice.private_key).sign(expected_block_serialized)
block = Block(transactions, alice.public_key, timestamp, voters)
block = block.sign(alice.private_key)
assert block.signature == expected.decode()
public_key = PublicKey(b.me)
public_key = PublicKey(alice.public_key)
assert public_key.verify(expected_block_serialized, block.signature)
def test_block_dupe_tx(self, b):
def test_block_dupe_tx(self, b, alice):
from bigchaindb.models import Transaction
from bigchaindb.common.exceptions import DuplicateTransaction
tx = Transaction.create([b.me], [([b.me], 1)])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)])
block = b.create_block([tx, tx])
with raises(DuplicateTransaction):
block._validate_block(b)
def test_decouple_assets(self, b):
def test_decouple_assets(self, b, alice):
from bigchaindb.models import Block, Transaction
assets = [
@ -169,15 +169,15 @@ class TestBlockModel(object):
txs = []
# create 3 assets
for asset in assets:
tx = Transaction.create([b.me], [([b.me], 1)], asset=asset)
tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset=asset)
tx.sign([alice.private_key])
txs.append(tx)
# create a `TRANSFER` transaction.
# the asset in `TRANSFER` transactions is not extracted
tx = Transaction.transfer(txs[0].to_inputs(), [([b.me], 1)],
tx = Transaction.transfer(txs[0].to_inputs(), [([alice.public_key], 1)],
asset_id=txs[0].id)
tx.sign([b.me_private])
tx.sign([alice.private_key])
txs.append(tx)
# create the block
@ -194,7 +194,7 @@ class TestBlockModel(object):
assert block.transactions[3].to_dict() == \
block_dict['block']['transactions'][3]
def test_couple_assets(self, b):
def test_couple_assets(self, b, alice):
from bigchaindb.models import Block, Transaction
assets = [
@ -206,15 +206,15 @@ class TestBlockModel(object):
txs = []
# create 3 assets
for asset in assets:
tx = Transaction.create([b.me], [([b.me], 1)], asset=asset)
tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset=asset)
tx.sign([alice.private_key])
txs.append(tx)
# create a `TRANSFER` transaction.
# the asset in `TRANSFER` transactions is not extracted
tx = Transaction.transfer(txs[0].to_inputs(), [([b.me], 1)],
tx = Transaction.transfer(txs[0].to_inputs(), [([alice.public_key], 1)],
asset_id=txs[0].id)
tx.sign([b.me_private])
tx.sign([alice.private_key])
txs.append(tx)
# create the block
@ -229,7 +229,7 @@ class TestBlockModel(object):
# check that the reconstructed block is the same as the original block
assert block == Block.from_dict(block_dict_reconstructed)
def test_get_asset_ids(self, b):
def test_get_asset_ids(self, b, alice):
from bigchaindb.models import Block, Transaction
assets = [
@ -241,15 +241,15 @@ class TestBlockModel(object):
txs = []
# create 3 assets
for asset in assets:
tx = Transaction.create([b.me], [([b.me], 1)], asset=asset)
tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset=asset)
tx.sign([alice.private_key])
txs.append(tx)
# create a `TRANSFER` transaction.
# the asset in `TRANSFER` transactions is not extracted
tx = Transaction.transfer(txs[0].to_inputs(), [([b.me], 1)],
tx = Transaction.transfer(txs[0].to_inputs(), [([alice.public_key], 1)],
asset_id=txs[0].id)
tx.sign([b.me_private])
tx.sign([alice.private_key])
txs.append(tx)
# create the block
@ -263,7 +263,7 @@ class TestBlockModel(object):
assert asset_ids == [tx.id for tx in txs[:-1]]
@pytest.mark.bdb
def test_from_db(self, b):
def test_from_db(self, b, alice):
from bigchaindb.models import Block, Transaction
assets = [
@ -275,15 +275,15 @@ class TestBlockModel(object):
txs = []
# create 3 assets
for asset in assets:
tx = Transaction.create([b.me], [([b.me], 1)], asset=asset)
tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset=asset)
tx.sign([alice.private_key])
txs.append(tx)
# create a `TRANSFER` transaction.
# the asset in `TRANSFER` transactions is not extracted
tx = Transaction.transfer(txs[0].to_inputs(), [([b.me], 1)],
tx = Transaction.transfer(txs[0].to_inputs(), [([alice.public_key], 1)],
asset_id=txs[0].id)
tx.sign([b.me_private])
tx.sign([alice.private_key])
txs.append(tx)
# create the block

View File

@ -26,15 +26,10 @@ def test_bigchain_instance_is_initialized_when_conf_provided(request):
from bigchaindb import config_utils
assert 'CONFIGURED' not in bigchaindb.config
config_utils.set_config({'keypair': {'public': 'a', 'private': 'b'}})
config_utils.set_config({'database': {'backend': 'a'}})
assert bigchaindb.config['CONFIGURED'] is True
b = bigchaindb.Bigchain()
assert b.me
assert b.me_private
def test_bigchain_instance_raises_when_not_configured(request, monkeypatch):
import bigchaindb
@ -46,7 +41,7 @@ def test_bigchain_instance_raises_when_not_configured(request, monkeypatch):
# from existing configurations
monkeypatch.setattr(config_utils, 'autoconfigure', lambda: 0)
with pytest.raises(exceptions.KeypairNotFoundException):
with pytest.raises(exceptions.ConfigurationError):
bigchaindb.Bigchain()
@ -214,15 +209,6 @@ def test_autoconfigure_read_both_from_file_and_env(monkeypatch, request, ssl_con
from bigchaindb.log.configs import SUBSCRIBER_LOGGING_CONFIG as log_config
config_utils.autoconfigure()
database_rethinkdb = {
'backend': 'rethinkdb',
'host': DATABASE_HOST,
'port': DATABASE_PORT,
'name': DATABASE_NAME,
'connection_timeout': 5000,
'max_tries': 3
}
database_mongodb = {
'backend': 'mongodb',
'host': DATABASE_HOST,
@ -262,8 +248,6 @@ def test_autoconfigure_read_both_from_file_and_env(monkeypatch, request, ssl_con
database = {}
if DATABASE_BACKEND == 'mongodb':
database = database_mongodb
elif DATABASE_BACKEND == 'rethinkdb':
database = database_rethinkdb
elif DATABASE_BACKEND == 'mongodb-ssl':
database = database_mongodb_ssl
@ -284,11 +268,10 @@ def test_autoconfigure_read_both_from_file_and_env(monkeypatch, request, ssl_con
'advertised_port': WSSERVER_ADVERTISED_PORT,
},
'database': database,
'keypair': {
'public': None,
'private': None,
'tendermint': {
'host': None,
'port': None,
},
'keyring': KEYRING.split(':'),
'log': {
'file': LOG_FILE,
'error_file': log_config['handlers']['errors']['filename'],

View File

@ -17,11 +17,6 @@ def config(request, monkeypatch):
'connection_timeout': 5000,
'max_tries': 3
},
'keypair': {
'public': 'pubkey',
'private': 'privkey',
},
'keyring': [],
'CONFIGURED': True,
}
@ -39,9 +34,6 @@ def test_bigchain_class_default_initialization(config):
assert bigchain.connection.host == config['database']['host']
assert bigchain.connection.port == config['database']['port']
assert bigchain.connection.dbname == config['database']['name']
assert bigchain.me == config['keypair']['public']
assert bigchain.me_private == config['keypair']['private']
assert bigchain.nodes_except_me == config['keyring']
assert bigchain.consensus == BaseConsensusRules
@ -49,26 +41,18 @@ def test_bigchain_class_initialization_with_parameters(config):
from bigchaindb.core import Bigchain
from bigchaindb.backend import connect
from bigchaindb.consensus import BaseConsensusRules
init_kwargs = {
'public_key': 'white',
'private_key': 'black',
'keyring': ['key_one', 'key_two'],
}
init_db_kwargs = {
'backend': 'rethinkdb',
'backend': 'localmongodb',
'host': 'this_is_the_db_host',
'port': 12345,
'name': 'this_is_the_db_name',
}
connection = connect(**init_db_kwargs)
bigchain = Bigchain(connection=connection, **init_kwargs)
bigchain = Bigchain(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']
assert bigchain.connection.dbname == init_db_kwargs['name']
assert bigchain.me == init_kwargs['public_key']
assert bigchain.me_private == init_kwargs['private_key']
assert bigchain.nodes_except_me == init_kwargs['keyring']
assert bigchain.consensus == BaseConsensusRules

View File

@ -21,18 +21,6 @@ def blockdata(b, user_pk, user2_pk):
return blocks, [b['id'] for b in blocks]
def test_filter_valid_block_ids_with_undecided(b, blockdata):
blocks, block_ids = blockdata
valid_ids = b.fastquery.filter_valid_block_ids(block_ids, include_undecided=True)
assert set(valid_ids) == {blocks[0]['id'], blocks[1]['id']}
def test_filter_valid_block_ids_only_valid(b, blockdata):
blocks, block_ids = blockdata
valid_ids = b.fastquery.filter_valid_block_ids(block_ids)
assert set(valid_ids) == {blocks[1]['id']}
def test_filter_valid_items(b, blockdata):
blocks, _ = blockdata
assert (b.fastquery.filter_valid_items(blocks, block_id_key=lambda b: b['id'])

View File

@ -1,9 +1,6 @@
import pytest
from unittest.mock import patch
from collections import Counter
from bigchaindb.core import Bigchain
from bigchaindb.exceptions import CriticalDuplicateVote
from bigchaindb.voting import Voting, INVALID, VALID, UNDECIDED
@ -116,68 +113,6 @@ def test_decide_votes_invalid(kwargs):
assert Voting.decide_votes(**kwargs) == UNDECIDED
################################################################################
# Actions - test state transitions
@pytest.mark.parametrize('n_voters', range(8))
def test_vote_actions(n_voters):
"""* Legal transitions are UNDECIDED -> [VALID|INVALID] only
* Block is never left UNDECIDED after voting
* Accomodates rogues on previous block / invalid schema
"""
class TestVoting(Voting):
@classmethod
def verify_vote_schema(cls, vote):
return type(vote['vote']['is_block_valid']) == bool
@classmethod
def verify_vote_signature(cls, vote):
return True
keyring = 'abcdefghijklmnopqrstuvwxyz'[:n_voters]
block = {'id': 'block', 'block': {'voters': keyring}}
state = UNDECIDED
todo = [(state, [], [])]
def branch(p, r):
todo.append((state, votes, votes + [{
'node_pubkey': keyring[len(votes)],
'vote': {'previous_block': p, 'is_block_valid': r}
}]))
while todo:
prev_state, prev_votes, votes = todo.pop(0)
results = Counter(v['vote']['is_block_valid'] for v in votes)
prev_blocks = Counter(v['vote']['previous_block'] for v in votes)
majority = n_voters // 2 + 1
honest = (len(votes) == majority and len(prev_blocks) == 1 and
not results['lol'] and len(results) == 1)
closed = len(votes) == n_voters
# Test legal transition
if votes:
state = TestVoting.block_election(block, votes, keyring)['status']
assert prev_state in [state, UNDECIDED]
# Test that decision has been reached
if honest or closed:
assert state != UNDECIDED or n_voters == 0
if closed:
continue
# Can accomodate more votes, add them to the todo list.
# This vote is the good case
branch('A', True)
# This vote disagrees on previous block
branch('B', True)
# This vote says the block is invalid
branch('A', False)
# This vote is invalid
branch('A', 'lol')
################################################################################
# Tests for vote signature
@ -200,48 +135,3 @@ def test_verify_vote_schema(b):
assert not Voting.verify_vote_schema(vote)
vote = b.vote('b', 'a' * 64, True)
assert not Voting.verify_vote_schema(vote)
################################################################################
# block_election tests
def test_block_election(b):
class TestVoting(Voting):
@classmethod
def verify_vote_signature(cls, vote):
return True
@classmethod
def verify_vote_schema(cls, vote):
return True
keyring = 'abc'
block = {'id': 'xyz', 'block': {'voters': 'ab'}}
votes = [{
'node_pubkey': c,
'vote': {'is_block_valid': True, 'previous_block': 'a'}
} for c in 'abc']
assert TestVoting.block_election(block, votes, keyring) == {
'status': VALID,
'block_id': 'xyz',
'counts': {'n_valid': 2, 'n_invalid': 0},
'ineligible': [votes[-1]],
'malformed': [],
'previous_block': 'a',
'other_previous_block': {},
}
@patch('bigchaindb.voting.Voting.verify_vote_signature', return_value=True)
def test_duplicate_vote_throws_critical_error(b):
keyring = 'abc'
block = {'id': 'xyz', 'block': {'voters': 'ab'}}
votes = [{
'node_pubkey': c,
'vote': {'is_block_valid': True, 'previous_block': 'a'}
} for c in 'aabc']
with pytest.raises(CriticalDuplicateVote):
Voting.block_election(block, votes, keyring)

View File

@ -13,6 +13,7 @@ from bigchaindb.common.exceptions import (AmountError,
ThresholdTooDeep)
from bigchaindb.models import Transaction
pytestmark = pytest.mark.tendermint
################################################################################
# Helper functions
@ -66,30 +67,30 @@ def test_tx_serialization_with_no_hash(signed_create_tx):
################################################################################
# Operation
def test_validate_invalid_operation(b, create_tx):
def test_validate_invalid_operation(b, create_tx, alice):
create_tx.operation = 'something invalid'
signed_tx = create_tx.sign([b.me_private])
signed_tx = create_tx.sign([alice.private_key])
validate_raises(signed_tx)
################################################################################
# Metadata
def test_validate_fails_metadata_empty_dict(b, create_tx):
def test_validate_fails_metadata_empty_dict(b, create_tx, alice):
create_tx.metadata = {'a': 1}
signed_tx = create_tx.sign([b.me_private])
signed_tx = create_tx.sign([alice.private_key])
validate(signed_tx)
create_tx._id = None
create_tx.fulfillment = None
create_tx.metadata = None
signed_tx = create_tx.sign([b.me_private])
signed_tx = create_tx.sign([alice.private_key])
validate(signed_tx)
create_tx._id = None
create_tx.fulfillment = None
create_tx.metadata = {}
signed_tx = create_tx.sign([b.me_private])
signed_tx = create_tx.sign([alice.private_key])
validate_raises(signed_tx)
@ -111,19 +112,19 @@ def test_transfer_asset_schema(user_sk, signed_transfer_tx):
validate_raises(tx)
def test_create_tx_no_asset_id(b, create_tx):
def test_create_tx_no_asset_id(b, create_tx, alice):
create_tx.asset['id'] = 'b' * 64
signed_tx = create_tx.sign([b.me_private])
signed_tx = create_tx.sign([alice.private_key])
validate_raises(signed_tx)
def test_create_tx_asset_type(b, create_tx):
def test_create_tx_asset_type(b, create_tx, alice):
create_tx.asset['data'] = 'a'
signed_tx = create_tx.sign([b.me_private])
signed_tx = create_tx.sign([alice.private_key])
validate_raises(signed_tx)
def test_create_tx_no_asset_data(b, create_tx):
def test_create_tx_no_asset_data(b, create_tx, alice):
tx_body = create_tx.to_dict()
del tx_body['asset']['data']
tx_serialized = json.dumps(
@ -135,34 +136,34 @@ def test_create_tx_no_asset_data(b, create_tx):
################################################################################
# Inputs
def test_no_inputs(b, create_tx):
def test_no_inputs(b, create_tx, alice):
create_tx.inputs = []
signed_tx = create_tx.sign([b.me_private])
signed_tx = create_tx.sign([alice.private_key])
validate_raises(signed_tx)
def test_create_single_input(b, create_tx):
def test_create_single_input(b, create_tx, alice):
from bigchaindb.common.transaction import Transaction
tx = create_tx.to_dict()
tx['inputs'] += tx['inputs']
tx = Transaction.from_dict(tx).sign([b.me_private]).to_dict()
tx = Transaction.from_dict(tx).sign([alice.private_key]).to_dict()
validate_raises(tx)
tx['id'] = None
tx['inputs'] = []
tx = Transaction.from_dict(tx).sign([b.me_private]).to_dict()
tx = Transaction.from_dict(tx).sign([alice.private_key]).to_dict()
validate_raises(tx)
def test_create_tx_no_fulfills(b, create_tx):
def test_create_tx_no_fulfills(b, create_tx, alice):
from bigchaindb.common.transaction import Transaction
tx = create_tx.to_dict()
tx['inputs'][0]['fulfills'] = {'transaction_id': 'a' * 64,
'output_index': 0}
tx = Transaction.from_dict(tx).sign([b.me_private]).to_dict()
tx = Transaction.from_dict(tx).sign([alice.private_key]).to_dict()
validate_raises(tx)
def test_transfer_has_inputs(user_sk, signed_transfer_tx):
def test_transfer_has_inputs(user_sk, signed_transfer_tx, alice):
signed_transfer_tx.inputs = []
signed_transfer_tx._id = None
signed_transfer_tx.sign([user_sk])
@ -172,8 +173,8 @@ def test_transfer_has_inputs(user_sk, signed_transfer_tx):
################################################################################
# Outputs
def test_low_amounts(b, user_sk, create_tx, signed_transfer_tx):
for sk, tx in [(b.me_private, create_tx), (user_sk, signed_transfer_tx)]:
def test_low_amounts(b, user_sk, create_tx, signed_transfer_tx, alice):
for sk, tx in [(alice.private_key, create_tx), (user_sk, signed_transfer_tx)]:
tx.outputs[0].amount = 0
tx._id = None
tx.sign([sk])
@ -184,21 +185,21 @@ def test_low_amounts(b, user_sk, create_tx, signed_transfer_tx):
validate_raises(tx)
def test_high_amounts(b, create_tx):
def test_high_amounts(b, create_tx, alice):
# Should raise a SchemaValidationError - don't want to allow ridiculously
# large numbers to get converted to int
create_tx.outputs[0].amount = 10 ** 21
create_tx.sign([b.me_private])
create_tx.sign([alice.private_key])
validate_raises(create_tx)
# Should raise AmountError
create_tx.outputs[0].amount = 9 * 10 ** 18 + 1
create_tx._id = None
create_tx.sign([b.me_private])
create_tx.sign([alice.private_key])
validate_raises(create_tx, AmountError)
# Should pass
create_tx.outputs[0].amount -= 1
create_tx._id = None
create_tx.sign([b.me_private])
create_tx.sign([alice.private_key])
validate(create_tx)
@ -236,17 +237,17 @@ def test_unsupported_condition_type():
################################################################################
# Version
def test_validate_version(b, create_tx):
def test_validate_version(b, create_tx, alice):
create_tx.version = '2.0'
create_tx.sign([b.me_private])
create_tx.sign([alice.private_key])
validate(create_tx)
create_tx.version = '0.10'
create_tx._id = None
create_tx.sign([b.me_private])
create_tx.sign([alice.private_key])
validate_raises(create_tx)
create_tx.version = '110'
create_tx._id = None
create_tx.sign([b.me_private])
create_tx.sign([alice.private_key])
validate_raises(create_tx)

View File

@ -17,78 +17,10 @@ def test_get_assets_with_missing_text_search(client):
assert res.status_code == 400
@pytest.mark.genesis
def test_get_assets(client, b):
from bigchaindb.models import Transaction
from bigchaindb.backend.localmongodb.connection import LocalMongoDBConnection
if isinstance(b.connection, LocalMongoDBConnection):
# test returns empty list when no assets are found
res = client.get(ASSETS_ENDPOINT + '?search=abc')
assert res.json == []
assert res.status_code == 200
# create asset
asset = {'msg': 'abc'}
tx = Transaction.create([b.me], [([b.me], 1)],
asset=asset).sign([b.me_private])
# create block
block = b.create_block([tx])
b.write_block(block)
# vote valid
vote = b.vote(block.id, b.get_last_voted_block().id, True)
b.write_vote(vote)
# test that asset is returned
res = client.get(ASSETS_ENDPOINT + '?search=abc')
assert res.status_code == 200
assert len(res.json) == 1
assert res.json[0] == {
'data': {'msg': 'abc'},
'id': tx.id
}
else:
# test that the correct error is returned if not running MongoDB
res = client.get(ASSETS_ENDPOINT + '?search=abc')
assert res.status_code == 400
assert res.json['message'].startswith('(OperationError)')
@pytest.mark.genesis
def test_get_assets_limit(client, b):
from bigchaindb.models import Transaction
from bigchaindb.backend.localmongodb.connection import LocalMongoDBConnection
if isinstance(b.connection, LocalMongoDBConnection):
# create two assets
asset1 = {'msg': 'abc 1'}
asset2 = {'msg': 'abc 2'}
tx1 = Transaction.create([b.me], [([b.me], 1)],
asset=asset1).sign([b.me_private])
tx2 = Transaction.create([b.me], [([b.me], 1)],
asset=asset2).sign([b.me_private])
# create block
block = b.create_block([tx1, tx2])
b.write_block(block)
# vote valid
vote = b.vote(block.id, b.get_last_voted_block().id, True)
b.write_vote(vote)
# test that both assets are returned without limit
res = client.get(ASSETS_ENDPOINT + '?search=abc')
assert res.status_code == 200
assert len(res.json) == 2
# test that only one asset is returned when using limit=1
res = client.get(ASSETS_ENDPOINT + '?search=abc&limit=1')
assert res.status_code == 200
assert len(res.json) == 1
@pytest.mark.bdb
@pytest.mark.tendermint
@pytest.mark.localmongodb
def test_get_assets_tendermint(client, tb):
def test_get_assets_tendermint(client, tb, alice):
from bigchaindb.models import Transaction
# test returns empty list when no assets are found
@ -98,8 +30,8 @@ def test_get_assets_tendermint(client, tb):
# create asset
asset = {'msg': 'abc'}
tx = Transaction.create([tb.me], [([tb.me], 1)],
asset=asset).sign([tb.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)],
asset=asset).sign([alice.private_key])
tb.store_transaction(tx)
@ -116,17 +48,17 @@ def test_get_assets_tendermint(client, tb):
@pytest.mark.bdb
@pytest.mark.tendermint
@pytest.mark.localmongodb
def test_get_assets_limit_tendermint(client, tb):
def test_get_assets_limit_tendermint(client, tb, alice):
from bigchaindb.models import Transaction
b = tb
# create two assets
asset1 = {'msg': 'abc 1'}
asset2 = {'msg': 'abc 2'}
tx1 = Transaction.create([b.me], [([b.me], 1)],
asset=asset1).sign([b.me_private])
tx2 = Transaction.create([b.me], [([b.me], 1)],
asset=asset2).sign([b.me_private])
tx1 = Transaction.create([alice.public_key], [([alice.public_key], 1)],
asset=asset1).sign([alice.private_key])
tx2 = Transaction.create([alice.public_key], [([alice.public_key], 1)],
asset=asset2).sign([alice.private_key])
b.store_transaction(tx1)
b.store_transaction(tx2)

View File

@ -10,10 +10,10 @@ pytestmark = pytest.mark.tendermint
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_block_endpoint(tb, client):
def test_get_block_endpoint(tb, client, alice):
b = tb
tx = Transaction.create([b.me], [([b.me], 1)], asset={'cycle': 'hero'})
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset={'cycle': 'hero'})
tx = tx.sign([alice.private_key])
b.store_transaction(tx)
block = Block(app_hash='random_utxo',
@ -38,10 +38,10 @@ def test_get_block_returns_404_if_not_found(client):
@pytest.mark.bdb
def test_get_block_containing_transaction(tb, client):
def test_get_block_containing_transaction(tb, client, alice):
b = tb
tx = Transaction.create([b.me], [([b.me], 1)], asset={'cycle': 'hero'})
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset={'cycle': 'hero'})
tx = tx.sign([alice.private_key])
b.store_transaction(tx)
block = Block(app_hash='random_utxo',

View File

@ -1,24 +1,8 @@
import pytest
from bigchaindb.models import Transaction
BLOCKS_ENDPOINT = '/api/v1/blocks/'
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_block_endpoint(b, client):
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
block = b.create_block([tx])
b.write_block(block)
res = client.get(BLOCKS_ENDPOINT + block.id)
assert block.to_dict() == res.json
assert res.status_code == 200
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_block_returns_404_if_not_found(client):
@ -29,116 +13,6 @@ def test_get_block_returns_404_if_not_found(client):
assert res.status_code == 404
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_blocks_by_txid_endpoint(b, client):
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
tx2 = Transaction.create([b.me], [([b.me], 10)])
tx2 = tx2.sign([b.me_private])
block_invalid = b.create_block([tx])
b.write_block(block_invalid)
res = client.get(BLOCKS_ENDPOINT + '?transaction_id=' + tx.id)
# test if block is retrieved as undecided
assert res.status_code == 200
assert block_invalid.id in res.json
assert len(res.json) == 1
# vote the block invalid
vote = b.vote(block_invalid.id, b.get_last_voted_block().id, False)
b.write_vote(vote)
res = client.get(BLOCKS_ENDPOINT + '?transaction_id=' + tx.id)
# test if block is retrieved as invalid
assert res.status_code == 200
assert block_invalid.id in res.json
assert len(res.json) == 1
# create a new block containing the same tx (and tx2 to avoid block id collision)
block_valid = b.create_block([tx, tx2])
b.write_block(block_valid)
res = client.get(BLOCKS_ENDPOINT + '?transaction_id=' + tx.id)
# test if block is retrieved as undecided
assert res.status_code == 200
assert block_valid.id in res.json
assert len(res.json) == 2
# vote the block valid
vote = b.vote(block_valid.id, block_invalid.id, True)
b.write_vote(vote)
res = client.get(BLOCKS_ENDPOINT + '?transaction_id=' + tx.id)
# test if block is retrieved as valid
assert res.status_code == 200
assert block_valid.id in res.json
assert len(res.json) == 2
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_blocks_by_txid_and_status_endpoint(b, client):
from bigchaindb import Bigchain
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
tx2 = Transaction.create([b.me], [([b.me], 10)])
tx2 = tx2.sign([b.me_private])
block_invalid = b.create_block([tx])
b.write_block(block_invalid)
# create a new block containing the same tx (and tx2 to avoid block id collision)
block_valid = b.create_block([tx, tx2])
b.write_block(block_valid)
res = client.get('{}?transaction_id={}&status={}'.format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_INVALID))
# test if no blocks are retrieved as invalid
assert res.status_code == 200
assert len(res.json) == 0
res = client.get('{}?transaction_id={}&status={}'.format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_UNDECIDED))
# test if both blocks are retrieved as undecided
assert res.status_code == 200
assert block_valid.id in res.json
assert block_invalid.id in res.json
assert len(res.json) == 2
res = client.get('{}?transaction_id={}&status={}'.format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_VALID))
# test if no blocks are retrieved as valid
assert res.status_code == 200
assert len(res.json) == 0
# vote one of the blocks invalid
vote = b.vote(block_invalid.id, b.get_last_voted_block().id, False)
b.write_vote(vote)
# vote the other block valid
vote = b.vote(block_valid.id, block_invalid.id, True)
b.write_vote(vote)
res = client.get('{}?transaction_id={}&status={}'.format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_INVALID))
# test if the invalid block is retrieved as invalid
assert res.status_code == 200
assert block_invalid.id in res.json
assert len(res.json) == 1
res = client.get('{}?transaction_id={}&status={}'.format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_UNDECIDED))
# test if no blocks are retrieved as undecided
assert res.status_code == 200
assert len(res.json) == 0
res = client.get('{}?transaction_id={}&status={}'.format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_VALID))
# test if the valid block is retrieved as valid
assert res.status_code == 200
assert block_valid.id in res.json
assert len(res.json) == 1
@pytest.mark.bdb
def test_get_blocks_by_txid_endpoint_returns_empty_list_not_found(client):
res = client.get(BLOCKS_ENDPOINT + '?transaction_id=')

View File

@ -3,7 +3,6 @@ from unittest import mock
@mock.patch('bigchaindb.version.__short_version__', 'tst')
@mock.patch('bigchaindb.version.__version__', 'tsttst')
@mock.patch('bigchaindb.config', {'keyring': ['abc'], 'keypair': {'public': 'def'}})
def test_api_root_endpoint(client, wsserver_base_url):
res = client.get('/')
docs_url = ['https://docs.bigchaindb.com/projects/server/en/vtsttst',
@ -23,8 +22,6 @@ def test_api_root_endpoint(client, wsserver_base_url):
},
'docs': 'https://docs.bigchaindb.com/projects/server/en/vtsttst/',
'version': 'tsttst',
'keyring': ['abc'],
'public_key': 'def',
'software': 'BigchainDB',
}

View File

@ -17,81 +17,9 @@ def test_get_metadata_with_missing_text_search(client):
assert res.status_code == 400
@pytest.mark.genesis
def test_get_metadata(client, b):
from bigchaindb.models import Transaction
from bigchaindb.backend.mongodb.connection import MongoDBConnection
if isinstance(b.connection, MongoDBConnection):
# test returns empty list when no assets are found
res = client.get(METADATA_ENDPOINT + '?search=abc')
assert res.json == []
assert res.status_code == 200
# create asset
asset = {'msg': 'abc'}
metadata = {'key': 'my_meta'}
tx = Transaction.create([b.me], [([b.me], 1)], metadata=metadata,
asset=asset).sign([b.me_private])
# create block
block = b.create_block([tx])
b.write_block(block)
# vote valid
vote = b.vote(block.id, b.get_last_voted_block().id, True)
b.write_vote(vote)
# test that metadata is returned
res = client.get(METADATA_ENDPOINT + '?search=my_meta')
assert res.status_code == 200
assert len(res.json) == 1
assert res.json[0] == {
'metadata': {'key': 'my_meta'},
'id': tx.id
}
else:
# test that the correct error is returned if not running MongoDB
res = client.get(METADATA_ENDPOINT + '?search=my_meta')
assert res.status_code == 400
assert res.json['message'].startswith('(OperationError)')
@pytest.mark.genesis
def test_get_metadata_limit(client, b):
from bigchaindb.models import Transaction
from bigchaindb.backend.mongodb.connection import MongoDBConnection
if isinstance(b.connection, MongoDBConnection):
# create two assets
asset1 = {'msg': 'abc 1'}
meta1 = {'key': 'meta 1'}
tx1 = Transaction.create([b.me], [([b.me], 1)], metadata=meta1,
asset=asset1).sign([b.me_private])
asset2 = {'msg': 'abc 2'}
meta2 = {'key': 'meta 2'}
tx2 = Transaction.create([b.me], [([b.me], 1)], metadata=meta2,
asset=asset2).sign([b.me_private])
# create block
block = b.create_block([tx1, tx2])
b.write_block(block)
# vote valid
vote = b.vote(block.id, b.get_last_voted_block().id, True)
b.write_vote(vote)
# test that both assets are returned without limit
res = client.get(METADATA_ENDPOINT + '?search=meta')
assert res.status_code == 200
assert len(res.json) == 2
# test that only one asset is returned when using limit=1
res = client.get(METADATA_ENDPOINT + '?search=meta&limit=1')
assert res.status_code == 200
assert len(res.json) == 1
@pytest.mark.bdb
@pytest.mark.tendermint
def test_get_metadata_tendermint(client, tb):
def test_get_metadata_tendermint(client, tb, alice):
from bigchaindb.models import Transaction
b = tb
@ -104,8 +32,8 @@ def test_get_metadata_tendermint(client, tb):
# create asset
asset = {'msg': 'abc'}
metadata = {'key': 'my_meta'}
tx = Transaction.create([b.me], [([b.me], 1)], metadata=metadata,
asset=asset).sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], metadata=metadata,
asset=asset).sign([alice.private_key])
b.store_transaction(tx)
@ -121,7 +49,7 @@ def test_get_metadata_tendermint(client, tb):
@pytest.mark.bdb
@pytest.mark.tendermint
def test_get_metadata_limit_tendermint(client, tb):
def test_get_metadata_limit_tendermint(client, tb, alice):
from bigchaindb.models import Transaction
b = tb
@ -129,14 +57,14 @@ def test_get_metadata_limit_tendermint(client, tb):
# create two assets
asset1 = {'msg': 'abc 1'}
meta1 = {'key': 'meta 1'}
tx1 = Transaction.create([b.me], [([b.me], 1)], metadata=meta1,
asset=asset1).sign([b.me_private])
tx1 = Transaction.create([alice.public_key], [([alice.public_key], 1)], metadata=meta1,
asset=asset1).sign([alice.private_key])
b.store_transaction(tx1)
asset2 = {'msg': 'abc 2'}
meta2 = {'key': 'meta 2'}
tx2 = Transaction.create([b.me], [([b.me], 1)], metadata=meta2,
asset=asset2).sign([b.me_private])
tx2 = Transaction.create([alice.public_key], [([alice.public_key], 1)], metadata=meta2,
asset=asset2).sign([alice.private_key])
b.store_transaction(tx2)
# test that both assets are returned without limit

View File

@ -30,9 +30,9 @@ def test_get_votes_endpoint(client):
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_votes_endpoint(b, client):
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
def test_get_votes_endpoint(b, client, alice):
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)])
tx = tx.sign([alice.private_key])
block = b.create_block([tx])
b.write_block(block)
@ -52,8 +52,8 @@ def test_get_votes_endpoint(b, client):
def test_get_votes_endpoint_multiple_votes(b, client):
from bigchaindb.common.crypto import generate_key_pair
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
tx = Transaction.create([alice.public_key], [([alice.public_key], 1)])
tx = tx.sign([alice.private_key])
block = b.create_block([tx])
b.write_block(block)

View File

@ -1,7 +1,6 @@
import asyncio
import json
import queue
import random
import threading
from unittest.mock import patch
@ -10,21 +9,6 @@ import pytest
pytestmark = pytest.mark.tendermint
@pytest.fixture
def _block(b, request):
from bigchaindb.models import Transaction
total = getattr(request, 'param', 1)
transactions = [
Transaction.create(
[b.me],
[([b.me], 1)],
metadata={'msg': random.random()},
).sign([b.me_private])
for _ in range(total)
]
return b.create_block(transactions)
class MockWebSocket:
def __init__(self):
self.received = []
@ -117,8 +101,7 @@ def test_websocket_string_event(test_client, loop):
@asyncio.coroutine
@pytest.mark.parametrize('_block', (10,), indirect=('_block',), ids=('block',))
def test_websocket_block_event(b, _block, test_client, loop):
def test_websocket_block_event(b, test_client, loop):
from bigchaindb import events
from bigchaindb.web.websocket_server import init_app, POISON_PILL, EVENTS_ENDPOINT
from bigchaindb.models import Transaction

View File

@ -1,6 +1,6 @@
[tox]
skipsdist = true
envlist = py{35,36}-{rethinkdb,mongodb}, flake8, docsroot, docsserver
envlist = py{35,36}, flake8, docsroot, docsserver
[base]
basepython = python3.6
@ -10,8 +10,6 @@ deps = pip>=9.0.1
usedevelop = True
setenv =
PYTHONPATH={toxinidir}:{toxinidir}/bigchaindb
rethinkdb: BIGCHAINDB_DATABASE_BACKEND=rethinkdb
mongodb: BIGCHAINDB_DATABASE_BACKEND=mongodb
deps = {[base]deps}
install_command = pip install --process-dependency-links {opts} {packages}
extras = test