def test_validate_account_root_file_next_block_identifier_mismatch(blockchain_base): last_block_identifier = '0' * 64 block_number = 0 blockchain_genesis_state = factories.InitialBlockchainStateFactory() block_0 = factories.CoinTransferBlockFactory( message=factories.CoinTransferBlockMessageFactory( block_number=block_number, block_identifier=last_block_identifier ), hash='e' * 64, ) state_1 = factories.BlockchainStateFactory( last_block_number=block_number, last_block_identifier=last_block_identifier, next_block_identifier='f' * 64, ) blockchain_state_patch = patch_blockchain_states(blockchain_base, [blockchain_genesis_state, state_1]) block_patch = patch_blocks(blockchain_base, [block_0]) with blockchain_state_patch, block_patch: with pytest.raises( ValidationError, match='Account root file next_block_identifier does not match ' 'last_block_number message hash' ): blockchain_base.validate_account_root_files(is_partial_allowed=True)
def test_block_message_fields_are_stored_in_bytes(field_name, value): block_msg = factories.CoinTransferBlockMessageFactory(**{field_name: value}) block = factories.CoinTransferBlockFactory(message=block_msg) compact_dict = block.to_compact_dict(compact_keys=False)['message'] assert compact_dict[field_name] == bytes.fromhex(value)
def test_validate_account_root_file_next_block_identifier_mismatch(blockchain_base): last_block_identifier = '0' * 64 block_number = 0 initial_arf = factories.InitialAccountRootFileFactory() block_0 = factories.CoinTransferBlockFactory( message=factories.CoinTransferBlockMessageFactory( block_number=block_number, block_identifier=last_block_identifier ), message_hash='e' * 64, ) arf_1 = factories.BlockchainStateFactory( last_block_number=block_number, last_block_identifier=last_block_identifier, next_block_identifier='f' * 64, ) arf_patch = patch.object(blockchain_base, 'yield_blockchain_states', get_generator([initial_arf, arf_1])) block_patch = patch.object(blockchain_base, 'yield_blocks', get_generator([block_0])) with arf_patch, block_patch: with pytest.raises( ValidationError, match='Account root file next_block_identifier does not match ' 'last_block_number message hash' ): blockchain_base.validate_account_root_files(is_partial_allowed=True)
def test_signed_change_request_fields_are_stored_in_bytes(field_name, value): signed_change_request = factories.CoinTransferSignedChangeRequestFactory(**{field_name: value}) block_msg = factories.CoinTransferBlockMessageFactory(signed_change_request=signed_change_request) block = factories.CoinTransferBlockFactory(message=block_msg) compact_dict = block.to_compact_dict(compact_keys=False)['message']['signed_change_request'] assert compact_dict[field_name] == bytes.fromhex(value)
def test_validate_account_root_file_points_to_non_existing_block(blockchain_base): initial_arf = factories.InitialAccountRootFileFactory() block_0 = factories.CoinTransferBlockFactory(message=factories.CoinTransferBlockMessageFactory(block_number=0)) arf_5 = factories.BlockchainStateFactory(last_block_number=5) arf_patch = patch.object(blockchain_base, 'yield_blockchain_states', get_generator([initial_arf, arf_5])) block_patch = patch.object(blockchain_base, 'yield_blocks', get_generator([block_0])) with arf_patch, block_patch: with pytest.raises(ValidationError, match='Account root file last_block_number points to non-existing block'): blockchain_base.validate_account_root_files(is_partial_allowed=True)
def test_validate_account_root_file_points_to_non_existing_block(blockchain_base): blockchain_genesis_state = factories.InitialBlockchainStateFactory() block_0 = factories.CoinTransferBlockFactory(message=factories.CoinTransferBlockMessageFactory(block_number=0)) state_5 = factories.BlockchainStateFactory(last_block_number=5) blockchain_state_patch = patch_blockchain_states(blockchain_base, [blockchain_genesis_state, state_5]) block_patch = patch_blocks(blockchain_base, [block_0]) with blockchain_state_patch, block_patch: with pytest.raises(ValidationError, match='Account root file last_block_number points to non-existing block'): blockchain_base.validate_account_root_files(is_partial_allowed=True)
def test_add_block_is_thread_safe(forced_file_blockchain, blockchain_directory): lock_file_path = os.path.join(blockchain_directory, 'file.lock') pool = ThreadPoolExecutor() block_0 = factories.CoinTransferBlockFactory() with filelock.FileLock(lock_file_path): future = pool.submit(forced_file_blockchain.add_block, block_0, validate=False) with pytest.raises(BlockchainLockedError, match='Blockchain locked*'): future.result(timeout=1)
def test_updated_balances_keys_are_stored_in_bytes(): account = '1be4f03ab7ea1184dbb5e4ff53b8cf0fe1cc400150ca1476fcd10546c1b3cd6a' block_account_balance = factories.AccountStateFactory() updated_account_states = { account: block_account_balance, } block_msg = factories.CoinTransferBlockMessageFactory(updated_account_states=updated_account_states) block = factories.CoinTransferBlockFactory(message=block_msg) updated_balances_dict = block.to_compact_dict(compact_keys=False)['message']['updated_account_states'] assert set(updated_balances_dict.keys()) == {bytes.fromhex(account)}
def test_updated_balances_fields_are_stored_in_bytes(field_name, value): account = '1be4f03ab7ea1184dbb5e4ff53b8cf0fe1cc400150ca1476fcd10546c1b3cd6a' block_account_balance = factories.AccountStateFactory(**{field_name: value}) updated_account_states = { account: block_account_balance, } block_msg = factories.CoinTransferBlockMessageFactory(updated_account_states=updated_account_states) block = factories.CoinTransferBlockFactory(message=block_msg) account_bytes = bytes.fromhex(account) compact_dict = block.to_compact_dict(compact_keys=False)['message']['updated_account_states'][account_bytes] assert compact_dict[field_name] == bytes.fromhex(value)
def test_block_messagepack_with_compact_values_is_smaller(): signature = ( 'd1c49087103b631a58228bdf8fb70d4789259cf22d815e207660cfe8d478adad9c' '7affe587942203e08be1dc1e14c6dd5a8abd8640f328e45f667a91a7c06a06' ) message_hash = '9677f4cbd7aaf32ba9615416f7bd0991b7de1434a7fa2c31add25c3355ef3959' block = factories.CoinTransferBlockFactory(signature=signature, hash=message_hash) non_compact_size = len(block.to_messagepack(compact_keys=False, compact_values=False)) compact_size = len(block.to_messagepack(compact_keys=False, compact_values=True)) compaction_rate = (non_compact_size - compact_size) / non_compact_size assert compaction_rate > 0.3
def test_non_ascii_memo_is_serialized_correctly(): # TODO(dmu) HIGH: This test must test transaction without using outer structures memo = 'Тестовое сообщение' # Test message in Russian transaction = factories.CoinTransferTransactionFactory(memo=memo) transaction.fee = False trm = factories.CoinTransferSignedChangeRequestMessageFactory( txs=[transaction]) tr = factories.CoinTransferSignedChangeRequestFactory(message=trm) block_message = factories.CoinTransferBlockMessageFactory( signed_change_request=tr) block = factories.CoinTransferBlockFactory(message=block_message) msg_pack = block.to_messagepack() restored_block = block.from_messagepack(msg_pack) assert restored_block == block
def test_transaction_optional_keys_are_not_serialized(key, value): # TODO(dmu) HIGH: This test must test transaction without using outer structures transaction = factories.CoinTransferTransactionFactory(**{key: value}) trm = factories.CoinTransferSignedChangeRequestMessageFactory( txs=[transaction]) tr = factories.CoinTransferSignedChangeRequestFactory(message=trm) block_message = factories.CoinTransferBlockMessageFactory( signed_change_request=tr) block = factories.CoinTransferBlockFactory(message=block_message) compact_dict = block.to_compact_dict(compact_values=False, compact_keys=False) transaction_dict = compact_dict['message']['signed_change_request'][ 'message']['txs'][0] assert key not in transaction_dict
from unittest.mock import patch import pytest from thenewboston_node.business_logic.tests import factories from thenewboston_node.business_logic.utils.iter import get_generator block_0 = factories.CoinTransferBlockFactory( message=factories.CoinTransferBlockMessageFactory(block_number=0)) block_1 = factories.CoinTransferBlockFactory( message=factories.CoinTransferBlockMessageFactory(block_number=1)) block_2 = factories.CoinTransferBlockFactory( message=factories.CoinTransferBlockMessageFactory(block_number=2), message_hash='fake-message-hash', ) def test_can_get_block_count(blockchain_base): with patch.object(blockchain_base, 'yield_blocks', get_generator([block_0, block_1, block_2])): block_count = blockchain_base.get_block_count() assert block_count == 3 def test_can_yield_blocks_from(blockchain_base): with patch.object(blockchain_base, 'yield_blocks', get_generator([block_0, block_1, block_2])): blocks = list(blockchain_base.yield_blocks_from(block_number=1))
USER_ACCOUNT_1: factories.AccountStateFactory(balance=100, balance_lock=USER_ACCOUNT_1) }, ) block_0 = factories.CoinTransferBlockFactory( message=factories.CoinTransferBlockMessageFactory( block_number=0, block_identifier=BLOCK_IDENTIFIER, signed_change_request=factories.CoinTransferSignedChangeRequestFactory( signer=USER_ACCOUNT_1, message=factories.CoinTransferSignedChangeRequestMessageFactory( balance_lock=USER_ACCOUNT_1, txs=[ factories.CoinTransferTransactionFactory( recipient=USER_ACCOUNT_2, amount=11, ) ])), updated_account_states={ USER_ACCOUNT_1: factories.AccountStateFactory(balance=89, balance_lock=MESSAGE_HASH), USER_ACCOUNT_2: factories.AccountStateFactory(balance=11, balance_lock=None), }), message_hash=MESSAGE_HASH, ) def test_validate_number_of_accounts_mismatch(blockchain_base): arf_0 = factories.BlockchainStateFactory(
def block_0(): return factories.CoinTransferBlockFactory(message=factories.CoinTransferBlockMessageFactory(block_number=0))
block_0 = factories.CoinTransferBlockFactory( message=factories.CoinTransferBlockMessageFactory( block_number=0, block_identifier='fake-block-identifier-0', timestamp=datetime(2021, 1, 1), signed_change_request=factories.CoinTransferSignedChangeRequestFactory( signer=USER_ACCOUNT_1, message=factories.CoinTransferSignedChangeRequestMessageFactory( balance_lock=USER_ACCOUNT_1, txs=[ factories.CoinTransferTransactionFactory( recipient=USER_ACCOUNT_2, amount=99, ), ] ), ), updated_account_states={ USER_ACCOUNT_1: factories.AccountStateFactory( balance=901, balance_lock='user-account-1-lock', ), USER_ACCOUNT_2: factories.AccountStateFactory( balance=99, balance_lock=None, ) } ), message_hash='fake-message-hash', )
def block_2(): return factories.CoinTransferBlockFactory( message=factories.CoinTransferBlockMessageFactory(block_number=2), hash='fake-message-hash', )
def test_block_fields_are_stored_in_bytes(field_name, value): block = factories.CoinTransferBlockFactory(**{field_name: value}) compact_dict = block.to_compact_dict(compact_keys=False) assert compact_dict[field_name] == bytes.fromhex(value)
def test_generate_blockchain_state(blockchain_base): blockchain_genesis_state = factories.InitialBlockchainStateFactory( account_states={USER_ACCOUNT_1: factories.AccountStateFactory( balance=1000, balance_lock=USER_ACCOUNT_1, )} ) block_0 = factories.CoinTransferBlockFactory( message=factories.CoinTransferBlockMessageFactory( block_number=0, block_identifier='fake-block-identifier-0', timestamp=datetime(2021, 1, 1), signed_change_request=factories.CoinTransferSignedChangeRequestFactory( signer=USER_ACCOUNT_1, message=factories.CoinTransferSignedChangeRequestMessageFactory( balance_lock=USER_ACCOUNT_1, txs=[ factories.CoinTransferTransactionFactory( recipient=USER_ACCOUNT_2, amount=99, ), ] ), ), updated_account_states={ USER_ACCOUNT_1: factories.AccountStateFactory( balance=901, balance_lock='user-account-1-lock', ), USER_ACCOUNT_2: factories.AccountStateFactory( balance=99, balance_lock=None, ) } ), hash='fake-message-hash', ) blockchain_state_patch = patch_blockchain_states(blockchain_base, [blockchain_genesis_state]) block_patch = patch_blocks(blockchain_base, [block_0]) with blockchain_state_patch, block_patch: blockchain_state = blockchain_base.generate_blockchain_state() assert blockchain_state == factories.BlockchainStateFactory( account_states={ USER_ACCOUNT_1: factories.AccountStateFactory( balance=901, balance_lock='user-account-1-lock', node=None, ), USER_ACCOUNT_2: factories.AccountStateFactory( balance=99, balance_lock=None, node=None, ) }, last_block_number=0, last_block_identifier=block_0.message.block_identifier, last_block_timestamp=block_0.message.timestamp, next_block_identifier=block_0.hash, )