def test_can_add_node_declaration_block( forced_memory_blockchain: MemoryBlockchain, user_account_key_pair: KeyPair, ): blockchain = forced_memory_blockchain user_account = user_account_key_pair.public request0 = NodeDeclarationSignedChangeRequest.create( identifier=hexstr('abcd'), network_addresses=['127.0.0.1'], fee_amount=3, signing_key=user_account_key_pair.private) block0 = Block.create_from_signed_change_request(blockchain, request0) blockchain.add_block(block0) assert blockchain.get_current_node(user_account) == request0.message.node blockchain.snapshot_blockchain_state() assert blockchain.blockchain_states[-1].get_node( user_account) == request0.message.node request1 = NodeDeclarationSignedChangeRequest.create( identifier=hexstr('abcd'), network_addresses=['127.0.0.2', '192.168.0.34'], fee_amount=3, signing_key=user_account_key_pair.private) block1 = Block.create_from_signed_change_request(blockchain, request1) blockchain.add_block(block1) assert blockchain.get_current_node(user_account) == request1.message.node blockchain.snapshot_blockchain_state() assert blockchain.blockchain_states[-1].get_node( user_account) == request1.message.node
def test_can_get_nodes_blocks_node_overrides_genesis_state_node( blockchain_directory, blockchain_genesis_state, user_account_key_pair ): blockchain = FileBlockchain(base_directory=blockchain_directory) account_number = user_account_key_pair.public blockchain_state_node = baker.make( Node, network_addresses=['https://192.168.0.32:8555/'], identifier=account_number ) blockchain_genesis_state.account_states[account_number] = AccountState(node=blockchain_state_node) blockchain.add_blockchain_state(blockchain_genesis_state) blockchain.validate() request = NodeDeclarationSignedChangeRequest.create( network_addresses=['https://127.0.0.1:8555/'], fee_amount=3, signing_key=user_account_key_pair.private ) blocks_node = request.message.node assert blocks_node.identifier block = Block.create_from_signed_change_request(blockchain, request, get_node_signing_key()) blockchain.add_block(block) assert blocks_node != blockchain_state_node assert list(blockchain.yield_nodes()) == [blocks_node]
def test_can_get_primary_validator_node(forced_memory_blockchain, api_client): blockchain = forced_memory_blockchain signing_key = get_node_signing_key() pv_node_declaration_request = NodeDeclarationSignedChangeRequest.create( network_addresses=['http://my.domain.com/'], fee_amount=3, signing_key=signing_key, ) block = Block.create_from_signed_change_request( blockchain, signed_change_request=pv_node_declaration_request, pv_signing_key=signing_key, ) blockchain.add_block(block) pv_node = pv_node_declaration_request.message.node pv_schedule_request = PrimaryValidatorScheduleSignedChangeRequest.create( 0, 99, signing_key=signing_key) block = Block.create_from_signed_change_request( blockchain, signed_change_request=pv_schedule_request, pv_signing_key=signing_key, ) blockchain.add_block(block) response = api_client.get(f'{API_V1_NODES_PREFIX}/pv/') assert response.status_code == 200 data = response.json() assert data['identifier'] == pv_node.identifier assert data['fee_amount'] == 3
def test_node_declaration_signed_change_request_valid_network_addresses( user_account_key_pair, network_address, forced_memory_blockchain): request = NodeDeclarationSignedChangeRequest.create( network_addresses=[network_address], fee_amount=3, fee_account=hexstr('be10aa7e'), signing_key=user_account_key_pair.private) request.validate(forced_memory_blockchain, block_number=0)
def test_node_declaration_signed_change_request_validate_negative_fee_amount( user_account_key_pair, forced_memory_blockchain): request = NodeDeclarationSignedChangeRequest.create( network_addresses=[], fee_amount=-3, fee_account=hexstr('be10aa7e'), signing_key=user_account_key_pair.private) with pytest.raises(ValidationError, match='Node fee_amount must be greater or equal to 0'): request.validate(forced_memory_blockchain, block_number=0)
def test_node_declaration_signed_change_request_validate_fee_account_is_hexadecimal( user_account_key_pair, forced_memory_blockchain): request = NodeDeclarationSignedChangeRequest.create( network_addresses=[], fee_amount=3, fee_account=hexstr('non-hexadecimal'), signing_key=user_account_key_pair.private) with pytest.raises(ValidationError, match='Node fee_account must be hexadecimal string'): request.validate(forced_memory_blockchain, block_number=0)
def test_node_declaration_signed_change_request_validate_network_addresses_scheme( user_account_key_pair, forced_memory_blockchain): request = NodeDeclarationSignedChangeRequest.create( network_addresses=['ftp://my.domain.com/'], fee_amount=3, fee_account=hexstr('be10aa7e'), signing_key=user_account_key_pair.private) with pytest.raises( ValidationError, match='Node network_addresses scheme must be one of http, https'): request.validate(forced_memory_blockchain, block_number=0)
def test_node_declaration_signed_change_request_validate_empty_network_addresses( user_account_key_pair, network_addresses, forced_memory_blockchain): request = NodeDeclarationSignedChangeRequest.create( network_addresses=[network_addresses], fee_amount=3, fee_account=hexstr('be10aa7e'), signing_key=user_account_key_pair.private) with pytest.raises(ValidationError, match='Node network_addresses must be not empty'): request.validate(forced_memory_blockchain, block_number=0)
def test_node_identifier_is_removed_when_node_declaration_signed_change_request_is_serialized( memory_blockchain, user_account_key_pair): request = NodeDeclarationSignedChangeRequest.create( identifier=hexstr('abcd'), network_addresses=['127.0.0.1'], fee_amount=3, fee_account=hexstr('dcba'), signing_key=user_account_key_pair.private) block = Block.create_from_signed_change_request(memory_blockchain, request) compact_dict = block.to_compact_dict() assert ck('identifier') not in compact_dict[ck('message')][ck( 'signed_change_request')][ck('message')][ck('node')]
def test_can_create_node_declaration_signed_change_request( user_account_key_pair): request = NodeDeclarationSignedChangeRequest.create( network_addresses=['127.0.0.1'], fee_amount=3, fee_account=hexstr('be10aa7e'), signing_key=user_account_key_pair.private) assert request assert request.signer assert request.signature assert request.message assert request.message.node.network_addresses == ['127.0.0.1'] assert request.message.node.fee_amount == 3 assert request.message.node.fee_account == 'be10aa7e'
def test_can_get_nodes_from_different_block_numbers( blockchain_directory, blockchain_genesis_state, user_account_key_pair ): account_number = user_account_key_pair.public blockchain = FileBlockchain(base_directory=blockchain_directory) blockchain_state_node = baker.make( Node, network_addresses=['https://192.168.0.29:8555/'], identifier=account_number ) blockchain_genesis_state.account_states[account_number] = AccountState(node=blockchain_state_node) blockchain.add_blockchain_state(blockchain_genesis_state) blockchain.validate() request = NodeDeclarationSignedChangeRequest.create( network_addresses=['https://192.168.0.30:8555/'], fee_amount=3, signing_key=user_account_key_pair.private ) node0 = request.message.node blockchain.add_block(Block.create_from_signed_change_request(blockchain, request, get_node_signing_key())) request = NodeDeclarationSignedChangeRequest.create( network_addresses=['https://192.168.0.31:8555/'], fee_amount=3, signing_key=user_account_key_pair.private ) node1 = request.message.node blockchain.add_block(Block.create_from_signed_change_request(blockchain, request, get_node_signing_key())) request = NodeDeclarationSignedChangeRequest.create( network_addresses=['https://192.168.0.32:8555/'], fee_amount=3, signing_key=user_account_key_pair.private ) node2 = request.message.node blockchain.add_block(Block.create_from_signed_change_request(blockchain, request, get_node_signing_key())) assert list(blockchain.yield_nodes()) == [node2] assert list(blockchain.yield_nodes(block_number=2)) == [node2] assert list(blockchain.yield_nodes(block_number=1)) == [node1] assert list(blockchain.yield_nodes(block_number=0)) == [node0] assert list(blockchain.yield_nodes(block_number=-1)) == [blockchain_state_node]
def test_can_get_nodes_single_node_from_blocks(blockchain_directory, blockchain_genesis_state, user_account_key_pair): blockchain = FileBlockchain(base_directory=blockchain_directory) blockchain.add_blockchain_state(blockchain_genesis_state) blockchain.validate() request = NodeDeclarationSignedChangeRequest.create( network_addresses=['https://127.0.0.1:8555/'], fee_amount=3, signing_key=user_account_key_pair.private ) node = request.message.node assert node.identifier block = Block.create_from_signed_change_request(blockchain, request, get_node_signing_key()) blockchain.add_block(block) assert list(blockchain.yield_nodes()) == [node]
def test_can_create_node_declaration_signed_change_request( user_account_key_pair): request = NodeDeclarationSignedChangeRequest.create( identifier='abcd', network_addresses=['127.0.0.1'], fee_amount=3, fee_account='fake_fee_account', signing_key=user_account_key_pair.private) assert request assert request.signer assert request.signature assert request.message assert request.message.node.network_addresses == ['127.0.0.1'] assert request.message.node.fee_amount == 3 assert request.message.node.fee_account == 'fake_fee_account'
def test_create_node_declaration_block(memory_blockchain, user_account_key_pair): request = NodeDeclarationSignedChangeRequest.create( identifier=hexstr('abcd'), network_addresses=['127.0.0.1'], fee_amount=3, fee_account=hexstr('dcba'), signing_key=user_account_key_pair.private) block = Block.create_from_signed_change_request(memory_blockchain, request) assert block assert block.message.signed_change_request assert block.message.signed_change_request.signer assert block.message.signed_change_request.signature assert block.message.signed_change_request.message assert block.message.signed_change_request.message.node.network_addresses == [ '127.0.0.1' ] assert block.message.signed_change_request.message.node.fee_amount == 3 assert block.message.signed_change_request.message.node.fee_account == hexstr( 'dcba')
def test_node_serializes_without_identifier_in_block(memory_blockchain, user_account_key_pair): account_number = user_account_key_pair.public node = baker.make(Node, identifier=account_number) request = NodeDeclarationSignedChangeRequest.create( network_addresses=['https://192.168.0.34:8555/'], fee_amount=3, signing_key=user_account_key_pair.private) block = Block.create_from_signed_change_request(memory_blockchain, request, get_node_signing_key()) serialized = block.serialize_to_dict() assert 'identifier' not in serialized['message']['updated_account_states'][ account_number]['node'] deserialized = Block.deserialize_from_dict(serialized) deserialized_node = deserialized.message.updated_account_states[ account_number].node assert deserialized_node is not node assert deserialized_node.identifier == account_number
def test_can_get_self_node(forced_memory_blockchain, api_client): blockchain = forced_memory_blockchain signing_key = get_node_signing_key() node_id = derive_public_key(signing_key) node_declaration_request = NodeDeclarationSignedChangeRequest.create( network_addresses=['http://my.domain.com/'], fee_amount=3, signing_key=signing_key, ) block = Block.create_from_signed_change_request( blockchain, signed_change_request=node_declaration_request, pv_signing_key=signing_key, ) blockchain.add_block(block) response = api_client.get(f'{API_V1_NODES_PREFIX}/self/') assert response.status_code == 200 data = response.json() assert data['identifier'] == node_id assert data['fee_amount'] == 3
def test_can_get_node(forced_memory_blockchain, api_client, user_account_key_pair): blockchain = forced_memory_blockchain node_declaration_request = NodeDeclarationSignedChangeRequest.create( network_addresses=['http://my.domain.com/'], fee_amount=3, signing_key=user_account_key_pair.private, ) block = Block.create_from_signed_change_request( blockchain, signed_change_request=node_declaration_request, pv_signing_key=user_account_key_pair.private, ) blockchain.add_block(block) node = node_declaration_request.message.node response = api_client.get(f'{API_V1_NODES_PREFIX}/{node.identifier}/') assert response.status_code == 200 data = response.json() assert data['identifier'] == node.identifier assert data['fee_amount'] == 3
def test_can_get_nodes_from_complex_blockchain(blockchain_directory, blockchain_genesis_state): key_pair1 = generate_key_pair() key_pair2 = generate_key_pair() key_pair3 = generate_key_pair() key_pair4 = generate_key_pair() key_pair5 = generate_key_pair() key_pair6 = generate_key_pair() assert len({ key_pair1.public, key_pair2.public, key_pair3.public, key_pair4.public, key_pair5.public, key_pair6.public }) == 6 blockchain = FileBlockchain(base_directory=blockchain_directory) node1 = baker.make(Node, network_addresses=['https://192.168.0.29:8555/'], identifier=key_pair1.public) blockchain_genesis_state.account_states[node1.identifier] = AccountState(node=node1) blockchain.add_blockchain_state(blockchain_genesis_state) blockchain.validate() # Block 0 request = NodeDeclarationSignedChangeRequest.create( network_addresses=['https://192.168.0.30:8555/'], fee_amount=3, signing_key=key_pair2.private ) node2 = request.message.node blockchain.add_block(Block.create_from_signed_change_request(blockchain, request, get_node_signing_key())) # Block 1 request = NodeDeclarationSignedChangeRequest.create( network_addresses=['https://192.168.0.31:8555/'], fee_amount=3, signing_key=key_pair3.private ) node3_old = request.message.node blockchain.add_block(Block.create_from_signed_change_request(blockchain, request, get_node_signing_key())) # Block 2 request = NodeDeclarationSignedChangeRequest.create( network_addresses=['https://192.168.0.32:8555/'], fee_amount=3, signing_key=key_pair4.private ) node4 = request.message.node blockchain.add_block(Block.create_from_signed_change_request(blockchain, request, get_node_signing_key())) def sort_key(value): return value.network_addresses def sort_me(list_): return sorted(list_, key=sort_key) assert sort_me(blockchain.yield_nodes(block_number=2)) == sort_me([node4, node3_old, node2, node1]) blockchain.snapshot_blockchain_state() # Block 3 request = NodeDeclarationSignedChangeRequest.create( network_addresses=['https://192.168.0.33:8555/'], fee_amount=3, signing_key=key_pair3.private ) node3 = request.message.node blockchain.add_block(Block.create_from_signed_change_request(blockchain, request, get_node_signing_key())) # Block 4 request = NodeDeclarationSignedChangeRequest.create( network_addresses=['https://192.168.0.34:8555/'], fee_amount=3, signing_key=key_pair5.private ) node5 = request.message.node blockchain.add_block(Block.create_from_signed_change_request(blockchain, request, get_node_signing_key())) # Block 5 request = NodeDeclarationSignedChangeRequest.create( network_addresses=['https://192.168.0.35:8555/'], fee_amount=3, signing_key=key_pair6.private ) node6 = request.message.node blockchain.add_block(Block.create_from_signed_change_request(blockchain, request, get_node_signing_key())) assert sort_me(blockchain.yield_nodes()) == sort_me([node6, node5, node3, node4, node2, node1]) assert sort_me(blockchain.yield_nodes(block_number=5)) == sort_me([node6, node5, node3, node4, node2, node1]) assert sort_me(blockchain.yield_nodes(block_number=4)) == sort_me([node5, node3, node4, node2, node1]) assert sort_me(blockchain.yield_nodes(block_number=3)) == sort_me([node3, node4, node2, node1]) assert sort_me(blockchain.yield_nodes(block_number=2)) == sort_me([node4, node3_old, node2, node1]) assert sort_me(blockchain.yield_nodes(block_number=1)) == sort_me([node3_old, node2, node1]) assert sort_me(blockchain.yield_nodes(block_number=0)) == sort_me([node2, node1]) assert sort_me(blockchain.yield_nodes(block_number=-1)) == sort_me([node1])