def test_block_is_appended(file_blockchain_w_memory_storage, user_account, treasury_account_signing_key): signing_key = treasury_account_signing_key blockchain = file_blockchain_w_memory_storage filename = '00000000000000000000-00000000000000000001-block-chunk.msgpack' node_signing_key = get_node_signing_key() block1 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=10, request_signing_key=signing_key, pv_signing_key=node_signing_key, ) blockchain.add_block(block1) block2 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=30, request_signing_key=signing_key, pv_signing_key=node_signing_key, ) blockchain.add_block(block2) assert blockchain.block_storage.files.keys() == {filename} assert blockchain.block_storage.finalized == set()
def set_up(file_blockchain_w_memory_storage, user_account, treasury_account_signing_key): signing_key = treasury_account_signing_key blockchain = file_blockchain_w_memory_storage filename = '0000-0003-block-chunk.msgpack' block0 = Block.create_from_main_transaction(blockchain, user_account, 10, signing_key=signing_key) blockchain.block_storage.append(filename, block0.to_messagepack()) block1 = Block.create_from_main_transaction(blockchain, user_account, 20, signing_key=signing_key) blockchain.block_storage.append(filename, block1.to_messagepack()) block2 = Block.create_from_main_transaction(blockchain, user_account, 50, signing_key=signing_key) blockchain.block_storage.append(filename, block2.to_messagepack()) block3 = Block.create_from_main_transaction(blockchain, user_account, 70, signing_key=signing_key) blockchain.block_storage.append(filename, block3.to_messagepack())
def test_can_validate_blockchain( forced_memory_blockchain: MemoryBlockchain, treasury_account_key_pair: KeyPair, user_account_key_pair: KeyPair, ): user_account = user_account_key_pair.public treasury_account = treasury_account_key_pair.public blockchain = forced_memory_blockchain blockchain.validate(is_partial_allowed=False) block0 = Block.create_from_main_transaction( blockchain, user_account, 30, signing_key=treasury_account_key_pair.private ) blockchain.add_block(block0) blockchain.snapshot_blockchain_state() blockchain.validate(is_partial_allowed=False) block1 = Block.create_from_main_transaction( blockchain, user_account, 10, signing_key=treasury_account_key_pair.private ) blockchain.add_block(block1) blockchain.snapshot_blockchain_state() blockchain.validate(is_partial_allowed=False) block2 = Block.create_from_main_transaction( blockchain, treasury_account, 5, signing_key=user_account_key_pair.private ) blockchain.add_block(block2) blockchain.snapshot_blockchain_state() blockchain.validate(is_partial_allowed=False)
def test_can_get_account_state_by_block_number( forced_memory_blockchain: MemoryBlockchain, treasury_account_key_pair: KeyPair, user_account_key_pair: KeyPair, primary_validator, preferred_node ): blockchain = forced_memory_blockchain sender = treasury_account_key_pair.public recipient = user_account_key_pair.public total_fees = primary_validator.fee_amount + preferred_node.fee_amount sender_initial_balance = blockchain.get_account_current_balance(sender) assert sender_initial_balance == 281474976710656 assert blockchain.get_account_balance(sender, -1) == sender_initial_balance assert blockchain.get_account_balance(recipient, -1) == 0 assert blockchain.get_account_current_balance(recipient) == 0 block0 = Block.create_from_main_transaction( blockchain, recipient, 10, signing_key=treasury_account_key_pair.private ) blockchain.add_block(block0) assert blockchain.get_account_balance(sender, -1) == sender_initial_balance assert blockchain.get_account_balance(recipient, -1) == 0 assert blockchain.get_account_balance(sender, 0) == sender_initial_balance - 10 - total_fees assert blockchain.get_account_balance(recipient, 0) == 10 assert blockchain.get_account_current_balance(sender) == sender_initial_balance - 10 - total_fees assert blockchain.get_account_current_balance(recipient) == 10 block1 = Block.create_from_main_transaction( blockchain, recipient, 11, signing_key=treasury_account_key_pair.private ) blockchain.add_block(block1) assert blockchain.get_account_balance(sender, -1) == sender_initial_balance assert blockchain.get_account_balance(recipient, -1) == 0 assert blockchain.get_account_balance(sender, 0) == sender_initial_balance - 10 - total_fees assert blockchain.get_account_balance(recipient, 0) == 10 assert blockchain.get_account_balance(sender, 1) == sender_initial_balance - 10 - 11 - 2 * total_fees assert blockchain.get_account_balance(recipient, 1) == 10 + 11 assert blockchain.get_account_current_balance(sender) == sender_initial_balance - 10 - 11 - 2 * total_fees assert blockchain.get_account_current_balance(recipient) == 10 + 11 block2 = Block.create_from_main_transaction( blockchain, recipient, 12, signing_key=treasury_account_key_pair.private ) blockchain.add_block(block2) assert blockchain.get_account_balance(sender, -1) == sender_initial_balance assert blockchain.get_account_balance(recipient, -1) == 0 assert blockchain.get_account_balance(sender, 0) == sender_initial_balance - 10 - total_fees assert blockchain.get_account_balance(recipient, 0) == 10 assert blockchain.get_account_balance(sender, 1) == sender_initial_balance - 10 - 11 - 2 * total_fees assert blockchain.get_account_balance(recipient, 1) == 10 + 11 assert blockchain.get_account_balance(sender, 2) == sender_initial_balance - 10 - 11 - 12 - 3 * total_fees assert blockchain.get_account_balance(recipient, 2) == 10 + 11 + 12 assert blockchain.get_account_current_balance(sender) == sender_initial_balance - 10 - 11 - 12 - 3 * total_fees assert blockchain.get_account_current_balance(recipient) == 10 + 11 + 12
def test_get_account_lock( forced_memory_blockchain: MemoryBlockchain, treasury_account_key_pair: KeyPair, user_account_key_pair: KeyPair, ): blockchain = forced_memory_blockchain treasury_account = treasury_account_key_pair.public user_account = user_account_key_pair.public assert blockchain.get_next_block_number() == 0 assert blockchain.get_account_current_balance_lock( treasury_account) == treasury_account assert blockchain.get_account_balance_lock(treasury_account, -1) == treasury_account block0 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=30, request_signing_key=treasury_account_key_pair.private, pv_signing_key=get_node_signing_key(), ) blockchain.add_block(block0) assert blockchain.get_next_block_number() == 1 block0_treasury_account_balance = block0.message.updated_account_states.get( treasury_account) assert block0_treasury_account_balance assert blockchain.get_account_current_balance_lock( treasury_account) == block0_treasury_account_balance.balance_lock assert blockchain.get_account_balance_lock(treasury_account, -1) == treasury_account block1 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=10, request_signing_key=treasury_account_key_pair.private, pv_signing_key=get_node_signing_key(), ) blockchain.add_block(block1) assert blockchain.get_next_block_number() == 2 block1_treasury_account_balance = block1.message.updated_account_states.get( treasury_account) assert block1_treasury_account_balance assert blockchain.get_account_current_balance_lock( treasury_account) == block1_treasury_account_balance.balance_lock assert blockchain.get_account_balance_lock( treasury_account, 0) == block0_treasury_account_balance.balance_lock assert blockchain.get_account_balance_lock(treasury_account, -1) == treasury_account
def set_up(file_blockchain_w_memory_storage, user_account, treasury_account_signing_key): signing_key = treasury_account_signing_key with patch.object(file_blockchain_w_memory_storage, 'snapshot_period_in_blocks', 2): block0 = Block.create_from_main_transaction( file_blockchain_w_memory_storage, user_account, 10, signing_key) file_blockchain_w_memory_storage.add_block(block0) block1 = Block.create_from_main_transaction( file_blockchain_w_memory_storage, user_account, 20, signing_key) file_blockchain_w_memory_storage.add_block(block1)
def test_block_is_appended(file_blockchain_w_memory_storage, user_account, treasury_account_signing_key): signing_key = treasury_account_signing_key blockchain = file_blockchain_w_memory_storage filename = '00000000000000000000-00000000000000000001-block-chunk.msgpack' block1 = Block.create_from_main_transaction(blockchain, user_account, 10, signing_key) blockchain.add_block(block1) block2 = Block.create_from_main_transaction(blockchain, user_account, 30, signing_key) blockchain.add_block(block2) assert blockchain.block_storage.files.keys() == {filename} assert blockchain.block_storage.finalized == set()
def test_can_add_block( blockchain_directory, blockchain_genesis_state, treasury_account_key_pair: KeyPair, user_account_key_pair: KeyPair, primary_validator_key_pair: KeyPair, node_key_pair: KeyPair, ): blockchain = FileBlockchain(base_directory=blockchain_directory) blockchain.add_blockchain_state(blockchain_genesis_state) blockchain.validate() treasury_account = treasury_account_key_pair.public treasury_initial_balance = blockchain.get_account_current_balance(treasury_account) assert treasury_initial_balance is not None user_account = user_account_key_pair.public pv_account = primary_validator_key_pair.public node_account = node_key_pair.public total_fees = 1 + 4 block0 = Block.create_from_main_transaction( blockchain, user_account, 30, signing_key=treasury_account_key_pair.private ) blockchain.add_block(block0) assert blockchain.get_account_current_balance(user_account) == 30 assert blockchain.get_account_current_balance(treasury_account) == treasury_initial_balance - 30 - total_fees assert blockchain.get_account_current_balance(node_account) == 1 assert blockchain.get_account_current_balance(pv_account) == 4 with pytest.raises(ValidationError, match='Block number must be equal to next block number.*'): blockchain.add_block(block0) block1 = Block.create_from_main_transaction( blockchain, user_account, 10, signing_key=treasury_account_key_pair.private ) blockchain.add_block(block1) assert blockchain.get_account_current_balance(user_account) == 40 assert blockchain.get_account_current_balance(treasury_account ) == (treasury_initial_balance - 30 - 10 - 2 * total_fees) assert blockchain.get_account_current_balance(node_account) == 1 * 2 assert blockchain.get_account_current_balance(pv_account) == 4 * 2 block2 = Block.create_from_main_transaction( blockchain, treasury_account, 5, signing_key=user_account_key_pair.private ) blockchain.add_block(block2) assert blockchain.get_account_current_balance(user_account) == 40 - 5 - total_fees assert blockchain.get_account_current_balance(treasury_account ) == (treasury_initial_balance - 30 - 10 + 5 - 2 * total_fees) assert blockchain.get_account_current_balance(node_account) == 1 * 3 assert blockchain.get_account_current_balance(pv_account) == 4 * 3
def test_block_chunk_is_rotated(file_blockchain_w_memory_storage, user_account, treasury_account_signing_key): signing_key = treasury_account_signing_key blockchain = file_blockchain_w_memory_storage file1 = '00000000000000000000-00000000000000000001-block-chunk.msgpack' file2 = '00000000000000000002-00000000000000000003-block-chunk.msgpack' node_signing_key = get_node_signing_key() with patch.object(blockchain, 'block_chunk_size', 2): block0 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=10, request_signing_key=signing_key, pv_signing_key=node_signing_key, ) blockchain.add_block(block0) block1 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=10, request_signing_key=signing_key, pv_signing_key=node_signing_key, ) blockchain.add_block(block1) block2 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=30, request_signing_key=signing_key, pv_signing_key=node_signing_key, ) blockchain.add_block(block2) block3 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=50, request_signing_key=signing_key, pv_signing_key=node_signing_key, ) blockchain.add_block(block3) assert blockchain.block_storage.files.keys() == {file1, file2} assert blockchain.block_storage.finalized == {file1, file2}
def test_cannot_add_block_twice(file_blockchain_w_memory_storage, user_account, treasury_account_signing_key): signing_key = treasury_account_signing_key blockchain = file_blockchain_w_memory_storage block = Block.create_from_main_transaction(blockchain, user_account, 10, signing_key) blockchain.add_block(block) with pytest.raises(ValidationError, match='Block number must be equal to next block number.*'): blockchain.add_block(block)
def set_up(file_blockchain_w_memory_storage, user_account, treasury_account_signing_key): signing_key = treasury_account_signing_key block = Block.create_from_main_transaction( file_blockchain_w_memory_storage, recipient=user_account, amount=100, signing_key=signing_key, ) file_blockchain_w_memory_storage.add_block(block)
def set_up(file_blockchain_w_memory_storage, user_account, treasury_account_signing_key): signing_key = treasury_account_signing_key with patch.object(file_blockchain_w_memory_storage, 'snapshot_period_in_blocks', 2): block0 = Block.create_from_main_transaction( blockchain=file_blockchain_w_memory_storage, recipient=user_account, amount=10, request_signing_key=signing_key, pv_signing_key=get_node_signing_key() ) file_blockchain_w_memory_storage.add_block(block0) block1 = Block.create_from_main_transaction( blockchain=file_blockchain_w_memory_storage, recipient=user_account, amount=20, request_signing_key=signing_key, pv_signing_key=get_node_signing_key() ) file_blockchain_w_memory_storage.add_block(block1)
def set_up(file_blockchain_w_memory_storage, user_account, treasury_account_signing_key): signing_key = treasury_account_signing_key blockchain = file_blockchain_w_memory_storage filename1 = '0000-0001-block-chunk.msgpack' block0 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=10, request_signing_key=signing_key, pv_signing_key=get_node_signing_key(), ) blockchain.block_storage.append(filename1, block0.to_messagepack()) block1 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=20, request_signing_key=signing_key, pv_signing_key=get_node_signing_key(), ) blockchain.block_storage.append(filename1, block1.to_messagepack()) filename2 = '0002-0003-block-chunk.msgpack' block2 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=50, request_signing_key=signing_key, pv_signing_key=get_node_signing_key(), ) blockchain.block_storage.append(filename2, block2.to_messagepack()) block3 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=70, request_signing_key=signing_key, pv_signing_key=get_node_signing_key(), ) blockchain.block_storage.append(filename2, block3.to_messagepack())
def test_block_chunk_is_rotated(file_blockchain_w_memory_storage, user_account, treasury_account_signing_key): signing_key = treasury_account_signing_key blockchain = file_blockchain_w_memory_storage file1 = '00000000000000000000-00000000000000000001-block-chunk.msgpack' file2 = '00000000000000000002-00000000000000000003-block-chunk.msgpack' with patch.object(blockchain, 'block_chunk_size', 2): block0 = Block.create_from_main_transaction(blockchain, user_account, 10, signing_key) blockchain.add_block(block0) block1 = Block.create_from_main_transaction(blockchain, user_account, 10, signing_key) blockchain.add_block(block1) block2 = Block.create_from_main_transaction(blockchain, user_account, 30, signing_key) blockchain.add_block(block2) block3 = Block.create_from_main_transaction(blockchain, user_account, 50, signing_key) blockchain.add_block(block3) assert blockchain.block_storage.files.keys() == {file1, file2} assert blockchain.block_storage.finalized == {file1, file2}
def set_up(file_blockchain_w_memory_storage, user_account, treasury_account_signing_key, primary_validator_identifier, node_identifier): signing_key = treasury_account_signing_key pv = PrimaryValidator(identifier=primary_validator_identifier, fee_amount=primary_validator_fee, network_addresses=[]) node = RegularNode(identifier=node_identifier, fee_amount=node_fee, network_addresses=[]) block = Block.create_from_main_transaction( file_blockchain_w_memory_storage, user_account, 100, signing_key, pv, node) file_blockchain_w_memory_storage.add_block(block) file_blockchain_w_memory_storage.snapshot_blockchain_state()
def test_cannot_add_block_twice(file_blockchain_w_memory_storage, user_account, treasury_account_signing_key): signing_key = treasury_account_signing_key blockchain = file_blockchain_w_memory_storage node_signing_key = get_node_signing_key() block = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=10, request_signing_key=signing_key, pv_signing_key=node_signing_key, ) blockchain.add_block(block) with pytest.raises( ValidationError, match='Block number must be equal to next block number.*'): blockchain.add_block(block)
def test_blockchain_state_is_created_every_x_block( blockchain_path, blockchain_genesis_state, treasury_account_key_pair: KeyPair, user_account_key_pair: KeyPair, ): assert not os.path.isfile( str(blockchain_path / 'account-root-files/0/0/0/0/0/0/0/0/000000000.-arf.msgpack')) blockchain = FileBlockchain( base_directory=str(blockchain_path), snapshot_period_in_blocks=5, account_root_files_subdir='account-root-files', account_root_files_storage_kwargs={'compressors': ()}) blockchain.add_blockchain_state(blockchain_genesis_state) assert os.path.isfile( str(blockchain_path / 'account-root-files/0/0/0/0/0/0/0/0/000000000.-arf.msgpack')) blockchain.validate() user_account = user_account_key_pair.public for _ in range(4): block = Block.create_from_main_transaction( blockchain, user_account, 30, signing_key=treasury_account_key_pair.private) assert not os.path.isfile( str(blockchain_path / f'account-root-files/0/0/0/0/0/0/0/0/000000000{block.message.block_number}-arf.msgpack' )) blockchain.add_block(block) block = Block.create_from_main_transaction( blockchain, user_account, 30, signing_key=treasury_account_key_pair.private) blockchain.add_block(block) assert os.path.isfile( str(blockchain_path / f'account-root-files/0/0/0/0/0/0/0/0/000000000{block.message.block_number}-arf.msgpack' )) for _ in range(4): block = Block.create_from_main_transaction( blockchain, user_account, 30, signing_key=treasury_account_key_pair.private) assert not os.path.isfile( str(blockchain_path / f'account-root-files/0/0/0/0/0/0/0/0/000000000{block.message.block_number}-arf.msgpack' )) blockchain.add_block(block) block = Block.create_from_main_transaction( blockchain, user_account, 30, signing_key=treasury_account_key_pair.private) blockchain.add_block(block) assert os.path.isfile( str(blockchain_path / f'account-root-files/0/0/0/0/0/0/0/0/000000000{block.message.block_number}-arf.msgpack' ))
def test_can_make_blockchain_state_on_last_block( forced_memory_blockchain: BlockchainBase, blockchain_genesis_state, treasury_account_key_pair, user_account_key_pair, primary_validator, preferred_node): blockchain = forced_memory_blockchain user_account = user_account_key_pair.public treasury_account = treasury_account_key_pair.public treasury_initial_balance = blockchain.get_account_current_balance( treasury_account) assert treasury_initial_balance is not None assert blockchain.get_last_blockchain_state() == blockchain_genesis_state assert blockchain.get_blockchain_state_by_block_number( -1) == blockchain_genesis_state assert blockchain_genesis_state.account_states[ treasury_account].balance_lock == treasury_account assert blockchain.get_blockchain_states_count() == 1 blockchain.snapshot_blockchain_state() assert blockchain.get_blockchain_states_count() == 1 block0 = Block.create_from_main_transaction( blockchain=blockchain, recipient=user_account, amount=30, request_signing_key=treasury_account_key_pair.private, pv_signing_key=get_node_signing_key(), ) blockchain.add_block(block0) blockchain.snapshot_blockchain_state() assert blockchain.get_blockchain_states_count() == 2 blockchain.snapshot_blockchain_state() assert blockchain.get_blockchain_states_count() == 2 account_root_file = blockchain.get_last_blockchain_state() assert account_root_file is not None assert account_root_file.last_block_number == 0 assert account_root_file.last_block_identifier == block0.message.block_identifier assert account_root_file.next_block_identifier == block0.hash assert len(account_root_file.account_states) == 4 assert account_root_file.account_states.keys() == { user_account, treasury_account, primary_validator.identifier, preferred_node.identifier } assert account_root_file.account_states[user_account].balance == 30 assert account_root_file.account_states[user_account].balance_lock is None assert account_root_file.account_states[user_account].get_balance_lock( user_account) == user_account assert account_root_file.account_states[ treasury_account].balance == treasury_initial_balance - 30 - 4 - 1 assert account_root_file.account_states[ treasury_account].balance_lock != treasury_account assert account_root_file.account_states[ primary_validator.identifier].balance == 4 assert account_root_file.account_states[ primary_validator.identifier].balance_lock is None assert account_root_file.account_states[ primary_validator.identifier].get_balance_lock( primary_validator.identifier) == primary_validator.identifier assert account_root_file.account_states[ preferred_node.identifier].balance == 1 assert account_root_file.account_states[ preferred_node.identifier].balance_lock is None assert account_root_file.account_states[ preferred_node.identifier].get_balance_lock( preferred_node.identifier) == preferred_node.identifier block1 = Block.create_from_main_transaction( blockchain=blockchain, recipient=treasury_account, amount=20, request_signing_key=user_account_key_pair.private, pv_signing_key=get_node_signing_key(), ) blockchain.add_block(block1) block2 = Block.create_from_main_transaction( blockchain=blockchain, recipient=primary_validator.identifier, amount=2, request_signing_key=treasury_account_key_pair.private, pv_signing_key=get_node_signing_key(), ) blockchain.add_block(block2) blockchain.snapshot_blockchain_state() account_root_file = blockchain.get_last_blockchain_state() assert account_root_file is not None assert account_root_file.last_block_number == 2 assert account_root_file.last_block_identifier == block2.message.block_identifier assert account_root_file.next_block_identifier == block2.hash assert len(account_root_file.account_states) == 4 assert account_root_file.account_states.keys() == { user_account, treasury_account, primary_validator.identifier, preferred_node.identifier } assert account_root_file.account_states[user_account].balance == 5 assert account_root_file.account_states[ user_account].balance_lock != user_account assert account_root_file.account_states[ treasury_account].balance == treasury_initial_balance - 30 - 4 - 1 + 20 - 2 - 4 - 1 assert account_root_file.account_states[ treasury_account].balance_lock != treasury_account assert account_root_file.account_states[ primary_validator.identifier].balance == 4 + 4 + 4 + 2 assert account_root_file.account_states[ primary_validator.identifier].balance_lock is None assert account_root_file.account_states[ primary_validator.identifier].get_balance_lock( primary_validator.identifier) == primary_validator.identifier assert account_root_file.account_states[ preferred_node.identifier].balance == 1 + 1 + 1 assert account_root_file.account_states[ preferred_node.identifier].balance_lock is None assert account_root_file.account_states[ preferred_node.identifier].get_balance_lock( preferred_node.identifier) == preferred_node.identifier