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_generate_blockchain_state(blockchain_base): arf_patch = patch.object(blockchain_base, 'yield_blockchain_states', get_generator([blockchain_genesis_state])) block_patch = patch.object(blockchain_base, 'yield_blocks', get_generator([block_0])) with arf_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.message_hash, )
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_yield_blocks_till_snapshot_with_no_account_root_file(blockchain_base): iter_arf_patch = patch.object(blockchain_base, 'yield_blockchain_states', get_generator([])) yield_blocks_patch = patch.object( blockchain_base, 'yield_blocks', get_generator([block_0, block_1, block_2])) with yield_blocks_patch, iter_arf_patch: blocks = list(blockchain_base.yield_blocks_till_snapshot()) assert blocks == []
def test_closest_account_root_file_not_found(blockchain_base, excludes_block_number): with mock.patch.object(blockchain_base, 'yield_blockchain_states', new=get_generator([arf_1, arf_2])): retrieved_arf = blockchain_base.get_closest_blockchain_state_snapshot( excludes_block_number=excludes_block_number ) assert retrieved_arf is None
def test_get_block_by_number_returns_none_if_block_doesnt_exist( blockchain_base): with patch.object(blockchain_base, 'yield_blocks', get_generator([block_0, block_2])): block = blockchain_base.get_block_by_number(block_number=1) assert block is None
def test_get_expected_block_identifier_from_last_block( blockchain_base, blockchain_genesis_state): with patch.object(blockchain_base, 'yield_blocks', get_generator([block_0, block_1, block_2])): block_identifier = blockchain_base.get_expected_block_identifier( block_number=3) assert block_identifier == block_2.message_hash
def test_get_expected_block_identifier_with_blockchain_genesis_state( blockchain_base, blockchain_genesis_state): with patch.object(blockchain_base, 'yield_blockchain_states', get_generator([blockchain_genesis_state])): block_identifier = blockchain_base.get_expected_block_identifier( block_number=0) assert block_identifier == blockchain_genesis_state.get_hash()
def test_validate_number_of_accounts_mismatch(blockchain_base): arf_0 = factories.BlockchainStateFactory( account_states={ USER_ACCOUNT_1: factories.AccountStateFactory(balance=89, balance_lock=MESSAGE_HASH) }) arf_patch = patch.object(blockchain_base, 'yield_blockchain_states', get_generator([initial_arf, arf_0])) block_patch = patch.object(blockchain_base, 'yield_blocks', get_generator([block_0])) with arf_patch, block_patch: with pytest.raises( ValidationError, match='Expected 2 accounts, but got 1 in the account root file' ): blockchain_base.validate_account_root_files()
def test_can_yield_blocks_till_snapshot(blockchain_base, blockchain_genesis_state, account_root_file_block_number, from_block_number, expected_blocks): iter_arf_patch = patch.object( blockchain_base, 'yield_blockchain_states', get_generator([ blockchain_genesis_state, factories.BlockchainStateFactory( last_block_number=account_root_file_block_number), ])) yield_blocks_patch = patch.object( blockchain_base, 'yield_blocks', get_generator([block_0, block_1, block_2])) with yield_blocks_patch, iter_arf_patch: blocks = list( blockchain_base.yield_blocks_till_snapshot( from_block_number=from_block_number)) assert blocks == expected_blocks
def test_validate_balance_value(blockchain_base): wrong_balance = 0 arf_0 = factories.BlockchainStateFactory( account_states={ USER_ACCOUNT_1: factories.AccountStateFactory(balance=wrong_balance, balance_lock=MESSAGE_HASH), USER_ACCOUNT_2: factories.AccountStateFactory(balance=11, balance_lock=USER_ACCOUNT_2), }) arf_patch = patch.object(blockchain_base, 'yield_blockchain_states', get_generator([initial_arf, arf_0])) block_patch = patch.object(blockchain_base, 'yield_blocks', get_generator([block_0])) with arf_patch, block_patch: with pytest.raises( ValidationError, match=f'Expected 89 balance value, but got 0 balance value for ' f'account {USER_ACCOUNT_1}'): blockchain_base.validate_account_root_files()
def test_validate_non_existent_account(blockchain_base): non_existent_account = 'f' * 64 arf_0 = factories.BlockchainStateFactory( account_states={ USER_ACCOUNT_1: factories.AccountStateFactory(balance=89, balance_lock=MESSAGE_HASH), non_existent_account: factories.AccountStateFactory(balance=11, balance_lock=non_existent_account), }) arf_patch = patch.object(blockchain_base, 'yield_blockchain_states', get_generator([initial_arf, arf_0])) block_patch = patch.object(blockchain_base, 'yield_blocks', get_generator([block_0])) with arf_patch, block_patch: with pytest.raises( ValidationError, match= f'Could not find {USER_ACCOUNT_2} account in the account root file' ): blockchain_base.validate_account_root_files()
def test_first_account_root_file_is_none(blockchain_base): with mock.patch.object(blockchain_base, 'yield_blockchain_states', new=get_generator([])): first_arf = blockchain_base.get_first_blockchain_state() assert first_arf is None
def test_can_get_first_blockchain_state(blockchain_base): with mock.patch.object(blockchain_base, 'yield_blockchain_states', new=get_generator([arf_1, arf_2])): first_arf = blockchain_base.get_first_blockchain_state() assert first_arf == arf_1
def test_can_yield_blockchain_states_reversed(blockchain_base): with mock.patch.object(blockchain_base, 'yield_blockchain_states', new=get_generator([arf_1, arf_2])): account_root_files = list(blockchain_base.yield_blockchain_states_reversed()) assert account_root_files == [arf_2, arf_1]
def test_can_get_account_root_file_count(blockchain_base): with mock.patch.object(blockchain_base, 'yield_blockchain_states', new=get_generator([arf_1, arf_2])): arf_count = blockchain_base.get_account_root_file_count() assert arf_count == 2
def test_blockchain_blockchain_genesis_state_is_validated(blockchain_base): initial_arf = factories.InitialAccountRootFileFactory() with patch.object(blockchain_base, 'yield_blockchain_states', get_generator([initial_arf])): blockchain_base.validate_account_root_files(is_partial_allowed=False)
def patch_blockchain_states(blockchain, blockchain_states): return mock.patch.object(blockchain, 'yield_blockchain_states', new=get_generator(blockchain_states))
def test_blockchain_must_start_with_blockchain_genesis_state(blockchain_base): non_initial_arf = factories.BlockchainStateFactory() with patch.object(blockchain_base, 'yield_blockchain_states', get_generator([non_initial_arf])): with pytest.raises(ValidationError, match='Blockchain must start with initial account root file'): blockchain_base.validate_account_root_files(is_partial_allowed=False)
def test_blockchain_genesis_state_not_found(blockchain_base): with mock.patch.object(blockchain_base, 'yield_blockchain_states', new=get_generator([])): initial_arf = blockchain_base.get_closest_blockchain_state_snapshot(excludes_block_number=-1) assert initial_arf is None
def test_exclude_non_existing_account_root_file_from_closest(blockchain_base): with mock.patch.object(blockchain_base, 'yield_blockchain_states', new=get_generator([arf_1, arf_2])): retrieved_arf = blockchain_base.get_closest_blockchain_state_snapshot(excludes_block_number=21) assert retrieved_arf == arf_2
def test_can_get_last_block_at_init(blockchain_base): with patch.object(blockchain_base, 'yield_blocks', get_generator([])): last_block = blockchain_base.get_last_block() assert last_block is None
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_get_block_by_number(blockchain_base): with patch.object(blockchain_base, 'yield_blocks', get_generator([block_0, block_1, block_2])): block = blockchain_base.get_block_by_number(block_number=1) assert block == block_1
def test_can_yield_blocks_reversed(blockchain_base): with patch.object(blockchain_base, 'yield_blocks', get_generator([block_0, block_1, block_2])): blocks = list(blockchain_base.yield_blocks_reversed()) assert blocks == [block_2, block_1, block_0]
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)) assert blocks == [block_1, block_2]
def test_can_get_blockchain_genesis_state(blockchain_base, blockchain_genesis_state): arf_generator = get_generator([blockchain_genesis_state, arf_1]) with mock.patch.object(blockchain_base, 'yield_blockchain_states', new=arf_generator): retrieved_arf = blockchain_base.get_closest_blockchain_state_snapshot(excludes_block_number=-1) assert retrieved_arf == blockchain_genesis_state
def test_blockchain_without_blockchain_genesis_state_is_validated(blockchain_base): non_initial_arf = factories.BlockchainStateFactory() with patch.object(blockchain_base, 'yield_blockchain_states', get_generator([non_initial_arf])): blockchain_base.validate_account_root_files(is_partial_allowed=True)
def test_can_get_last_block(blockchain_base): with patch.object(blockchain_base, 'yield_blocks', get_generator([block_0, block_1, block_2])): last_block = blockchain_base.get_last_block() assert last_block == block_2
def test_blockchain_must_have_at_least_blockchain_genesis_state(blockchain_base): with patch.object(blockchain_base, 'yield_blockchain_states', get_generator([])): with pytest.raises(ValidationError, match='Blockchain must contain at least one account root file'): blockchain_base.validate_account_root_files()