mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00

* Planning release * Clean up after move * Add exceptions.py * Add crypto.py * Adjust setup to package structure * Fix tests * Add test coverage * Comply to flake8 * Add test coverage * Transfer-tx fulfillments validation * Remove condition and fulfillment ids * Fix signing logic Specifically for transfer-tx with multiple inputs and outputs. * Compliance to legacy BDB models * Adjust fulfillment validation interface * Add serialization validation for txids * Use __eq__ to compare objects * Heavy refactor to comply with current implementation * Add Transaction.create * Correct fulfillment validation logic * Add Transaction.create for hashlock conditions * Add hashlock condition serialization * Transaction.transfer add single input and outputs * Small adjustments to transfer-tx interface * Create transfer-tx interface * Increase test coverage * Adjust fulfillment (de)serialization * Catch CC Error for Fulfillment * Allow custom thresholds * PR feedback * Fix tests * Rename Data to Metadata * Add Asset exceptions * Add basic Asset model * More renaming of payload => data * Add Asset into work-flow-functions * Add Asset amount to condition * add fulfillment exception * initial integration of asset * Make transaction.py compy to 79 chars * Make util.py comply to 79 chars * Make exceptions.py comply to 80 chars * Renaming inp to input_ * fix pep8 issues * Correct raised error * Remove resolved TODOs * prevent adding None as fulfillment / condition to Transaction * Small modifications to support new cryptoconditions * Improve documentation (#42) * Add doc strings for Fulfillment cls * Add doc strings for TransactionLink cls * Add doc strings for Condition cls * Add doc strings for Data cls * Add doc strings for Transaction cls * Add doc strings for Asset cls * Extract common implementation * Tx model: Add test for empty inputs * WIP: Implement sign tx * Add tests for: - Conditions; and - Fulfillments Mostly on the (de)serialization part. * Finalize serialization logic for tx class * Add Tests for tx serialization logic * Add fulfillment validation * Add ThresholdCondition support * WIP transfer * Clean up after move * Adjust setup to package structure * Fix tests * Add test coverage * Add test coverage * Transfer-tx fulfillments validation * Remove condition and fulfillment ids * Fix signing logic Specifically for transfer-tx with multiple inputs and outputs. * Fix test case * Compliance to legacy BDB models * Adjust fulfillment validation interface * Add serialization validation for txids * Use __eq__ to compare objects * Heavy refactor to comply with current implementation * Add Transaction.create * Add validation tests * Add Transaction.create for hashlock conditions * Add hashlock condition serialization * Transaction.transfer add single input and outputs * Small adjustments to transfer-tx interface * Create transfer-tx interface * Increase test coverage * Adjust fulfillment (de)serialization * Catch CC Error for Fulfillment * Allow custom thresholds * Rename Data to Metadata * Add basic Asset model * Add Asset into work-flow-functions * Add Asset amount to condition * initial integration of asset * Make tests comply to 79 chars per line * Fixed tests * fix pep8 issues * Correct raised error * Add test for asset initialization * Remove resolved TODOs * prevent adding None as fulfillment / condition to Transaction * Small modifications to support new cryptoconditions * Extract common tests * Copy conftest from bigchaindb-common - by @timdaub * Replace bigchaindb_common pkg by bigchaindb.common
171 lines
5.6 KiB
Python
171 lines
5.6 KiB
Python
import time
|
|
from unittest.mock import patch
|
|
|
|
from bigchaindb.common import crypto
|
|
import rethinkdb as r
|
|
from multipipes import Pipe, Pipeline
|
|
|
|
from bigchaindb import Bigchain
|
|
from bigchaindb.pipelines import election
|
|
|
|
|
|
def test_check_for_quorum_invalid(b, user_vk):
|
|
from bigchaindb.models import Transaction
|
|
|
|
e = election.Election()
|
|
|
|
# create blocks with transactions
|
|
tx1 = Transaction.create([b.me], [user_vk])
|
|
test_block = b.create_block([tx1])
|
|
|
|
# simulate a federation with four voters
|
|
key_pairs = [crypto.generate_key_pair() for _ in range(4)]
|
|
test_federation = [Bigchain(public_key=key_pair[1], private_key=key_pair[0])
|
|
for key_pair in key_pairs]
|
|
|
|
# add voters to block and write
|
|
test_block.voters = [key_pair[1] for key_pair in key_pairs]
|
|
test_block = test_block.sign(b.me_private)
|
|
b.write_block(test_block)
|
|
|
|
# split_vote (invalid)
|
|
votes = [member.vote(test_block.id, 'abc', True) for member in test_federation[:2]] + \
|
|
[member.vote(test_block.id, 'abc', False) for member in test_federation[2:]]
|
|
|
|
# cast votes
|
|
b.connection.run(r.table('votes').insert(votes, durability='hard'))
|
|
|
|
# since this block is now invalid, should pass to the next process
|
|
assert e.check_for_quorum(votes[-1]) == test_block
|
|
|
|
|
|
def test_check_for_quorum_invalid_prev_node(b, user_vk):
|
|
from bigchaindb.models import Transaction
|
|
e = election.Election()
|
|
|
|
# create blocks with transactions
|
|
tx1 = Transaction.create([b.me], [user_vk])
|
|
test_block = b.create_block([tx1])
|
|
|
|
# simulate a federation with four voters
|
|
key_pairs = [crypto.generate_key_pair() for _ in range(4)]
|
|
test_federation = [Bigchain(public_key=key_pair[1], private_key=key_pair[0])
|
|
for key_pair in key_pairs]
|
|
|
|
# add voters to block and write
|
|
test_block.voters = [key_pair[1] for key_pair in key_pairs]
|
|
test_block = test_block.sign(b.me_private)
|
|
b.write_block(test_block)
|
|
|
|
# split vote over prev node
|
|
votes = [member.vote(test_block.id, 'abc', True) for member in test_federation[:2]] + \
|
|
[member.vote(test_block.id, 'def', True) for member in test_federation[2:]]
|
|
|
|
# cast votes
|
|
b.connection.run(r.table('votes').insert(votes, durability='hard'))
|
|
|
|
# since nodes cannot agree on prev block, the block is invalid
|
|
assert e.check_for_quorum(votes[-1]) == test_block
|
|
|
|
|
|
def test_check_for_quorum_valid(b, user_vk):
|
|
from bigchaindb.models import Transaction
|
|
|
|
e = election.Election()
|
|
|
|
# create blocks with transactions
|
|
tx1 = Transaction.create([b.me], [user_vk])
|
|
test_block = b.create_block([tx1])
|
|
|
|
# simulate a federation with four voters
|
|
key_pairs = [crypto.generate_key_pair() for _ in range(4)]
|
|
test_federation = [Bigchain(public_key=key_pair[1], private_key=key_pair[0])
|
|
for key_pair in key_pairs]
|
|
|
|
# add voters to block and write
|
|
test_block.voters = [key_pair[1] for key_pair in key_pairs]
|
|
test_block = test_block.sign(b.me_private)
|
|
b.write_block(test_block)
|
|
|
|
# votes for block one
|
|
votes = [member.vote(test_block.id, 'abc', True)
|
|
for member in test_federation]
|
|
# cast votes
|
|
b.connection.run(r.table('votes').insert(votes, durability='hard'))
|
|
|
|
# since this block is valid, should go nowhere
|
|
assert e.check_for_quorum(votes[-1]) is None
|
|
|
|
|
|
def test_check_requeue_transaction(b, user_vk):
|
|
from bigchaindb.models import Transaction
|
|
|
|
e = election.Election()
|
|
|
|
# create blocks with transactions
|
|
tx1 = Transaction.create([b.me], [user_vk])
|
|
test_block = b.create_block([tx1])
|
|
|
|
e.requeue_transactions(test_block)
|
|
backlog_tx = b.connection.run(r.table('backlog').get(tx1.id))
|
|
backlog_tx.pop('assignee')
|
|
backlog_tx.pop('assignment_timestamp')
|
|
assert backlog_tx == tx1.to_dict()
|
|
|
|
|
|
@patch.object(Pipeline, 'start')
|
|
def test_start(mock_start):
|
|
# TODO: `block.election` is just a wrapper around `block.create_pipeline`,
|
|
# that is tested by `test_full_pipeline`.
|
|
# If anyone has better ideas on how to test this, please do a PR :)
|
|
election.start()
|
|
mock_start.assert_called_with()
|
|
|
|
|
|
def test_full_pipeline(b, user_vk):
|
|
import random
|
|
from bigchaindb.models import Transaction
|
|
|
|
outpipe = Pipe()
|
|
|
|
# write two blocks
|
|
txs = []
|
|
for i in range(100):
|
|
tx = Transaction.create([b.me], [user_vk], {'msg': random.random()})
|
|
tx = tx.sign([b.me_private])
|
|
txs.append(tx)
|
|
|
|
valid_block = b.create_block(txs)
|
|
b.write_block(valid_block)
|
|
|
|
txs = []
|
|
for i in range(100):
|
|
tx = Transaction.create([b.me], [user_vk], {'msg': random.random()})
|
|
tx = tx.sign([b.me_private])
|
|
txs.append(tx)
|
|
|
|
invalid_block = b.create_block(txs)
|
|
b.write_block(invalid_block)
|
|
|
|
pipeline = election.create_pipeline()
|
|
pipeline.setup(indata=election.get_changefeed(), outdata=outpipe)
|
|
pipeline.start()
|
|
time.sleep(1)
|
|
# vote one block valid, one invalid
|
|
vote_valid = b.vote(valid_block.id, 'abc', True)
|
|
vote_invalid = b.vote(invalid_block.id, 'abc', False)
|
|
|
|
b.connection.run(r.table('votes').insert(vote_valid, durability='hard'))
|
|
b.connection.run(r.table('votes').insert(vote_invalid, durability='hard'))
|
|
|
|
outpipe.get()
|
|
pipeline.terminate()
|
|
|
|
# only transactions from the invalid block should be returned to
|
|
# the backlog
|
|
assert b.connection.run(r.table('backlog').count()) == 100
|
|
# NOTE: I'm still, I'm still tx from the block.
|
|
tx_from_block = set([tx.id for tx in invalid_block.transactions])
|
|
tx_from_backlog = set([tx['id'] for tx in list(b.connection.run(r.table('backlog')))])
|
|
assert tx_from_block == tx_from_backlog
|