mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
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:
parent
58a5959170
commit
2b39566a4b
@ -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'],
|
||||
|
@ -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))
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"""
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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']
|
||||
})
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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])
|
||||
|
@ -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])
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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'],
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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'])
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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',
|
||||
|
@ -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=')
|
||||
|
@ -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',
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
4
tox.ini
4
tox.ini
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user