mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
UUID is added even if payload is None
Prevent the creation of empty blocks Created and updated tests
This commit is contained in:
parent
a694efd9dc
commit
6d41f6971d
@ -386,6 +386,10 @@ class Bigchain(object):
|
||||
dict: created block.
|
||||
"""
|
||||
|
||||
# Prevent the creation of empty blocks
|
||||
if len(validated_transactions) == 0:
|
||||
raise exceptions.OperationError('Empty block creation is not allowed')
|
||||
|
||||
# Create the new block
|
||||
block = {
|
||||
'timestamp': util.timestamp(),
|
||||
|
@ -221,14 +221,13 @@ def create_tx(current_owners, new_owners, inputs, operation, payload=None):
|
||||
|
||||
# handle payload
|
||||
data = None
|
||||
if payload is not None:
|
||||
if isinstance(payload, dict):
|
||||
data = {
|
||||
'uuid': str(uuid.uuid4()),
|
||||
'payload': payload
|
||||
}
|
||||
else:
|
||||
raise TypeError('`payload` must be an dict instance')
|
||||
if isinstance(payload, (dict, type(None))):
|
||||
data = {
|
||||
'uuid': str(uuid.uuid4()),
|
||||
'payload': payload
|
||||
}
|
||||
else:
|
||||
raise TypeError('`payload` must be an dict instance or None')
|
||||
|
||||
# handle inputs
|
||||
fulfillments = []
|
||||
|
@ -22,6 +22,20 @@ def test_remove_unclosed_sockets():
|
||||
pass
|
||||
|
||||
|
||||
# Some util functions
|
||||
def dummy_tx():
|
||||
b = bigchaindb.Bigchain()
|
||||
tx = b.create_transaction(b.me, b.me, None, 'CREATE')
|
||||
tx_signed = b.sign_transaction(tx, b.me_private)
|
||||
return tx_signed
|
||||
|
||||
|
||||
def dummy_block():
|
||||
b = bigchaindb.Bigchain()
|
||||
block = b.create_block([dummy_tx()])
|
||||
return block
|
||||
|
||||
|
||||
class TestBigchainApi(object):
|
||||
def test_create_transaction_create(self, b, user_sk):
|
||||
tx = b.create_transaction(b.me, user_sk, None, 'CREATE')
|
||||
@ -33,6 +47,17 @@ class TestBigchainApi(object):
|
||||
with pytest.raises(TypeError):
|
||||
b.create_transaction('a', 'b', 'c', 'd', payload=[])
|
||||
|
||||
def test_create_transaction_payload_none(self, b, user_vk):
|
||||
tx = b.create_transaction(b.me, user_vk, None, 'CREATE')
|
||||
assert len(tx['transaction']['data']['uuid']) == 36
|
||||
assert tx['transaction']['data']['payload'] is None
|
||||
|
||||
def test_create_transaction_payload(self, b, user_vk):
|
||||
payload = {'msg': 'Hello BigchainDB!'}
|
||||
tx = b.create_transaction(b.me, user_vk, None, 'CREATE', payload=payload)
|
||||
assert len(tx['transaction']['data']['uuid']) == 36
|
||||
assert tx['transaction']['data']['payload'] == payload
|
||||
|
||||
@pytest.mark.usefixtures('inputs')
|
||||
def test_create_transaction_transfer(self, b, user_vk, user_sk):
|
||||
input_tx = b.get_owned_ids(user_vk).pop()
|
||||
@ -200,7 +225,8 @@ class TestBigchainApi(object):
|
||||
assert prev_block_id == last_block['id']
|
||||
|
||||
def test_create_new_block(self, b):
|
||||
new_block = b.create_block([])
|
||||
tx = dummy_tx()
|
||||
new_block = b.create_block([tx])
|
||||
block_hash = crypto.hash_data(util.serialize(new_block['block']))
|
||||
|
||||
assert new_block['block']['voters'] == [b.me]
|
||||
@ -209,6 +235,12 @@ class TestBigchainApi(object):
|
||||
assert new_block['id'] == block_hash
|
||||
assert new_block['votes'] == []
|
||||
|
||||
def test_create_empty_block(self, b):
|
||||
with pytest.raises(exceptions.OperationError) as excinfo:
|
||||
b.create_block([])
|
||||
|
||||
assert excinfo.value.args[0] == 'Empty block creation is not allowed'
|
||||
|
||||
def test_get_last_voted_block_returns_genesis_if_no_votes_has_been_casted(self, b):
|
||||
b.create_genesis_block()
|
||||
genesis = list(r.table('bigchain')
|
||||
@ -221,9 +253,9 @@ class TestBigchainApi(object):
|
||||
|
||||
assert b.get_last_voted_block() == genesis
|
||||
|
||||
block_1 = b.create_block([])
|
||||
block_2 = b.create_block([])
|
||||
block_3 = b.create_block([])
|
||||
block_1 = dummy_block()
|
||||
block_2 = dummy_block()
|
||||
block_3 = dummy_block()
|
||||
|
||||
b.write_block(block_1, durability='hard')
|
||||
b.write_block(block_2, durability='hard')
|
||||
@ -241,7 +273,7 @@ class TestBigchainApi(object):
|
||||
def test_no_vote_written_if_block_already_has_vote(self, b):
|
||||
b.create_genesis_block()
|
||||
|
||||
block_1 = b.create_block([])
|
||||
block_1 = dummy_block()
|
||||
|
||||
b.write_block(block_1, durability='hard')
|
||||
|
||||
@ -387,7 +419,7 @@ class TestTransactionValidation(object):
|
||||
|
||||
class TestBlockValidation(object):
|
||||
def test_wrong_block_hash(self, b):
|
||||
block = b.create_block([])
|
||||
block = dummy_block()
|
||||
|
||||
# change block hash
|
||||
block.update({'id': 'abc'})
|
||||
@ -428,7 +460,7 @@ class TestBlockValidation(object):
|
||||
assert excinfo.value.args[0] == 'current_owner `a` does not own the input `{}`'.format(valid_input)
|
||||
|
||||
def test_invalid_block_id(self, b):
|
||||
block = b.create_block([])
|
||||
block = dummy_block()
|
||||
|
||||
# change block hash
|
||||
block.update({'id': 'abc'})
|
||||
@ -450,7 +482,7 @@ class TestBlockValidation(object):
|
||||
|
||||
def test_invalid_signature(self, b):
|
||||
# create a valid block
|
||||
block = b.create_block([])
|
||||
block = dummy_block()
|
||||
|
||||
# replace the block signature with an invalid one
|
||||
block['signature'] = crypto.SigningKey(b.me_private).sign(b'wrongdata')
|
||||
@ -462,7 +494,7 @@ class TestBlockValidation(object):
|
||||
def test_invalid_node_pubkey(self, b):
|
||||
# blocks can only be created by a federation node
|
||||
# create a valid block
|
||||
block = b.create_block([])
|
||||
block = dummy_block()
|
||||
|
||||
# create some temp keys
|
||||
tmp_sk, tmp_vk = crypto.generate_key_pair()
|
||||
@ -488,7 +520,7 @@ class TestBigchainVoter(object):
|
||||
|
||||
genesis = b.create_genesis_block()
|
||||
# create valid block
|
||||
block = b.create_block([])
|
||||
block = dummy_block()
|
||||
# assert block is valid
|
||||
assert b.is_valid_block(block)
|
||||
b.write_block(block, durability='hard')
|
||||
@ -560,7 +592,7 @@ class TestBigchainVoter(object):
|
||||
|
||||
def test_vote_creation_valid(self, b):
|
||||
# create valid block
|
||||
block = b.create_block([])
|
||||
block = dummy_block()
|
||||
# retrieve vote
|
||||
vote = b.vote(block, 'abc', True)
|
||||
|
||||
@ -574,7 +606,7 @@ class TestBigchainVoter(object):
|
||||
|
||||
def test_vote_creation_invalid(self, b):
|
||||
# create valid block
|
||||
block = b.create_block([])
|
||||
block = dummy_block()
|
||||
# retrieve vote
|
||||
vote = b.vote(block, 'abc', False)
|
||||
|
||||
@ -786,9 +818,9 @@ class TestBigchainBlock(object):
|
||||
def test_revert_delete_block(self, b):
|
||||
b.create_genesis_block()
|
||||
|
||||
block_1 = b.create_block([])
|
||||
block_2 = b.create_block([])
|
||||
block_3 = b.create_block([])
|
||||
block_1 = dummy_block()
|
||||
block_2 = dummy_block()
|
||||
block_3 = dummy_block()
|
||||
|
||||
b.write_block(block_1, durability='hard')
|
||||
b.write_block(block_2, durability='hard')
|
||||
@ -2088,7 +2120,7 @@ class TestCryptoconditions(object):
|
||||
assert b.is_valid_transaction(escrow_tx_transfer) == escrow_tx_transfer
|
||||
assert b.validate_transaction(escrow_tx_transfer) == escrow_tx_transfer
|
||||
|
||||
time.sleep(time_sleep)
|
||||
time.sleep(time_sleep + 1)
|
||||
|
||||
assert b.is_valid_transaction(escrow_tx_transfer) is False
|
||||
with pytest.raises(exceptions.InvalidSignature):
|
||||
@ -2223,7 +2255,7 @@ class TestCryptoconditions(object):
|
||||
block = b.create_block([escrow_tx_transfer])
|
||||
b.write_block(block, durability='hard')
|
||||
|
||||
time.sleep(time_sleep)
|
||||
time.sleep(time_sleep + 1)
|
||||
|
||||
assert b.is_valid_transaction(escrow_tx_transfer) is False
|
||||
with pytest.raises(exceptions.InvalidSignature):
|
||||
|
@ -9,6 +9,20 @@ from bigchaindb.voter import Voter, Election, BlockStream
|
||||
from bigchaindb import crypto, Bigchain
|
||||
|
||||
|
||||
# Some util functions
|
||||
def dummy_tx():
|
||||
b = Bigchain()
|
||||
tx = b.create_transaction(b.me, b.me, None, 'CREATE')
|
||||
tx_signed = b.sign_transaction(tx, b.me_private)
|
||||
return tx_signed
|
||||
|
||||
|
||||
def dummy_block():
|
||||
b = Bigchain()
|
||||
block = b.create_block([dummy_tx()])
|
||||
return block
|
||||
|
||||
|
||||
class TestBigchainVoter(object):
|
||||
|
||||
def test_valid_block_voting(self, b):
|
||||
@ -17,7 +31,9 @@ class TestBigchainVoter(object):
|
||||
genesis = b.create_genesis_block()
|
||||
|
||||
# create valid block
|
||||
block = b.create_block([])
|
||||
# sleep so that `block` as a higher timestamp then genesis
|
||||
time.sleep(1)
|
||||
block = dummy_block()
|
||||
# assert block is valid
|
||||
assert b.is_valid_block(block)
|
||||
b.write_block(block, durability='hard')
|
||||
@ -59,6 +75,8 @@ class TestBigchainVoter(object):
|
||||
assert b.is_valid_transaction(tx_signed)
|
||||
|
||||
# create valid block
|
||||
# sleep so that block as a higher timestamp then genesis
|
||||
time.sleep(1)
|
||||
block = b.create_block([tx_signed])
|
||||
# assert block is valid
|
||||
assert b.is_valid_block(block)
|
||||
@ -172,6 +190,8 @@ class TestBigchainVoter(object):
|
||||
genesis = b.create_genesis_block()
|
||||
|
||||
# create invalid block
|
||||
# sleep so that `block` as a higher timestamp then `genesis`
|
||||
time.sleep(1)
|
||||
block = b.create_block([transaction_signed])
|
||||
# change transaction id to make it invalid
|
||||
block['block']['transactions'][0]['id'] = 'abc'
|
||||
@ -201,7 +221,7 @@ class TestBigchainVoter(object):
|
||||
|
||||
def test_vote_creation_valid(self, b):
|
||||
# create valid block
|
||||
block = b.create_block([])
|
||||
block = dummy_block()
|
||||
# retrieve vote
|
||||
vote = b.vote(block, 'abc', True)
|
||||
|
||||
@ -215,7 +235,7 @@ class TestBigchainVoter(object):
|
||||
|
||||
def test_vote_creation_invalid(self, b):
|
||||
# create valid block
|
||||
block = b.create_block([])
|
||||
block = dummy_block()
|
||||
# retrieve vote
|
||||
vote = b.vote(block, 'abc', False)
|
||||
|
||||
@ -233,9 +253,9 @@ class TestBigchainVoter(object):
|
||||
|
||||
# insert blocks in the database while the voter process is not listening
|
||||
# (these blocks won't appear in the changefeed)
|
||||
block_1 = b.create_block([])
|
||||
block_1 = dummy_block()
|
||||
b.write_block(block_1, durability='hard')
|
||||
block_2 = b.create_block([])
|
||||
block_2 = dummy_block()
|
||||
b.write_block(block_2, durability='hard')
|
||||
|
||||
# voter is back online, we simulate that by creating a queue and a Voter instance
|
||||
@ -243,7 +263,7 @@ class TestBigchainVoter(object):
|
||||
voter = Voter(q_new_block)
|
||||
|
||||
# create a new block that will appear in the changefeed
|
||||
block_3 = b.create_block([])
|
||||
block_3 = dummy_block()
|
||||
b.write_block(block_3, durability='hard')
|
||||
|
||||
# put the last block in the queue
|
||||
@ -266,9 +286,12 @@ class TestBigchainVoter(object):
|
||||
|
||||
def test_voter_chains_blocks_with_the_previous_ones(self, b):
|
||||
b.create_genesis_block()
|
||||
block_1 = b.create_block([])
|
||||
# sleep so that `block_*` as a higher timestamp then `genesis`
|
||||
time.sleep(1)
|
||||
block_1 = dummy_block()
|
||||
b.write_block(block_1, durability='hard')
|
||||
block_2 = b.create_block([])
|
||||
time.sleep(1)
|
||||
block_2 = dummy_block()
|
||||
b.write_block(block_2, durability='hard')
|
||||
|
||||
q_new_block = mp.Queue()
|
||||
@ -294,7 +317,7 @@ class TestBigchainVoter(object):
|
||||
|
||||
def test_voter_checks_for_previous_vote(self, b):
|
||||
b.create_genesis_block()
|
||||
block_1 = b.create_block([])
|
||||
block_1 = dummy_block()
|
||||
b.write_block(block_1, durability='hard')
|
||||
|
||||
q_new_block = mp.Queue()
|
||||
@ -326,7 +349,7 @@ class TestBlockElection(object):
|
||||
|
||||
def test_quorum(self, b):
|
||||
# create a new block
|
||||
test_block = b.create_block([])
|
||||
test_block = dummy_block()
|
||||
|
||||
# simulate a federation with four voters
|
||||
key_pairs = [crypto.generate_key_pair() for _ in range(4)]
|
||||
@ -393,7 +416,7 @@ class TestBlockElection(object):
|
||||
def test_quorum_odd(self, b):
|
||||
# test partial quorum situations for odd numbers of voters
|
||||
# create a new block
|
||||
test_block = b.create_block([])
|
||||
test_block = dummy_block()
|
||||
|
||||
# simulate a federation with four voters
|
||||
key_pairs = [crypto.generate_key_pair() for _ in range(5)]
|
||||
@ -476,7 +499,7 @@ class TestBlockStream(object):
|
||||
b.federation_nodes.append(crypto.generate_key_pair()[1])
|
||||
new_blocks = mp.Queue()
|
||||
bs = BlockStream(new_blocks)
|
||||
block_1 = b.create_block([])
|
||||
block_1 = dummy_block()
|
||||
new_blocks.put(block_1)
|
||||
assert block_1 == bs.get()
|
||||
|
||||
@ -485,8 +508,8 @@ class TestBlockStream(object):
|
||||
bs = BlockStream(new_blocks)
|
||||
|
||||
# create two blocks
|
||||
block_1 = b.create_block([])
|
||||
block_2 = b.create_block([])
|
||||
block_1 = dummy_block()
|
||||
block_2 = dummy_block()
|
||||
|
||||
# write the blocks
|
||||
b.write_block(block_1, durability='hard')
|
||||
@ -502,8 +525,8 @@ class TestBlockStream(object):
|
||||
|
||||
def test_if_old_blocks_get_should_return_old_block_first(self, b):
|
||||
# create two blocks
|
||||
block_1 = b.create_block([])
|
||||
block_2 = b.create_block([])
|
||||
block_1 = dummy_block()
|
||||
block_2 = dummy_block()
|
||||
|
||||
# write the blocks
|
||||
b.write_block(block_1, durability='hard')
|
||||
@ -520,8 +543,8 @@ class TestBlockStream(object):
|
||||
# pp(block_2)
|
||||
|
||||
# create two new blocks that will appear in the changefeed
|
||||
block_3 = b.create_block([])
|
||||
block_4 = b.create_block([])
|
||||
block_3 = dummy_block()
|
||||
block_4 = dummy_block()
|
||||
|
||||
# simulate a changefeed
|
||||
new_blocks.put(block_3)
|
||||
|
Loading…
x
Reference in New Issue
Block a user