Beispiel #1
0
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(
        network_addresses=['http://127.0.0.1'],
        fee_amount=3,
        signing_key=user_account_key_pair.private)
    block0 = Block.create_from_signed_change_request(blockchain, request0,
                                                     get_node_signing_key())
    blockchain.add_block(block0)
    assert blockchain.get_node_by_identifier(
        user_account) == request0.message.node
    blockchain.snapshot_blockchain_state()
    assert blockchain.blockchain_states[-1].get_node(
        user_account) == request0.message.node

    request1 = NodeDeclarationSignedChangeRequest.create(
        network_addresses=['http://127.0.0.2', 'http://192.168.0.34'],
        fee_amount=3,
        signing_key=user_account_key_pair.private)
    block1 = Block.create_from_signed_change_request(blockchain, request1,
                                                     get_node_signing_key())
    blockchain.add_block(block1)
    assert blockchain.get_node_by_identifier(
        user_account) == request1.message.node
    blockchain.snapshot_blockchain_state()
    assert blockchain.blockchain_states[-1].get_node(
        user_account) == request1.message.node
Beispiel #2
0
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 test_can_create_block_from_signed_change_request(
    forced_mock_blockchain, sample_signed_change_request: CoinTransferSignedChangeRequest
):

    sender = sample_signed_change_request.signer
    assert sender

    def get_account_balance(self, account, on_block_number):
        return 450 if account == sender else 0

    with patch.object(MockBlockchain, 'get_account_balance', new=get_account_balance):
        block = Block.create_from_signed_change_request(
            forced_mock_blockchain, sample_signed_change_request, get_node_signing_key()
        )

    assert block.message
    assert block.hash
    assert block.signature
    block.validate_signature()
    assert block.signer
    assert block.signer == derive_public_key(get_node_signing_key())

    block_message = block.message

    signed_change_request = block_message.signed_change_request
    assert signed_change_request == sample_signed_change_request
    assert signed_change_request is not sample_signed_change_request  # test that a copy of it was made

    assert isinstance(block_message.timestamp, datetime)
    assert block_message.timestamp.tzinfo is None
    assert block_message.timestamp - datetime.utcnow() < timedelta(seconds=1)

    assert block_message.block_number == 0
    assert block_message.block_identifier == 'next-block-identifier'
    updated_account_states = block_message.updated_account_states

    assert isinstance(updated_account_states, dict)
    assert len(updated_account_states) == 4

    assert updated_account_states[sender].balance == 450 - 425 - 4 - 1
    assert updated_account_states[sender].balance_lock

    assert updated_account_states['484b3176c63d5f37d808404af1a12c4b9649cd6f6769f35bdf5a816133623fbc'].balance == 425
    assert updated_account_states['484b3176c63d5f37d808404af1a12c4b9649cd6f6769f35bdf5a816133623fbc'
                                  ].balance_lock is None

    assert updated_account_states['ad1f8845c6a1abb6011a2a434a079a087c460657aad54329a84b406dce8bf314'].balance == 4
    assert updated_account_states['ad1f8845c6a1abb6011a2a434a079a087c460657aad54329a84b406dce8bf314'
                                  ].balance_lock is None

    assert updated_account_states['5e12967707909e62b2bb2036c209085a784fabbc3deccefee70052b6181c8ed8'].balance == 1
    assert updated_account_states['5e12967707909e62b2bb2036c209085a784fabbc3deccefee70052b6181c8ed8'
                                  ].balance_lock is None
Beispiel #4
0
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()
Beispiel #5
0
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_can_serialize_deserialize(forced_mock_blockchain, sample_signed_change_request):
    block = Block.create_from_signed_change_request(
        forced_mock_blockchain, sample_signed_change_request, get_node_signing_key()
    )
    serialized_dict = block.serialize_to_dict()
    deserialized_block = Block.deserialize_from_dict(serialized_dict)
    assert deserialized_block == block
    assert deserialized_block is not block
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=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()
    blockchain.validate(is_partial_allowed=False)

    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)
    blockchain.snapshot_blockchain_state()
    blockchain.validate(is_partial_allowed=False)

    block2 = Block.create_from_main_transaction(
        blockchain=blockchain,
        recipient=treasury_account,
        amount=10,
        request_signing_key=user_account_key_pair.private,
        pv_signing_key=get_node_signing_key(),
    )
    blockchain.add_block(block2)
    blockchain.snapshot_blockchain_state()
    blockchain.validate(is_partial_allowed=False)
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(
        blockchain=file_blockchain_w_memory_storage,
        recipient=user_account,
        amount=100,
        request_signing_key=signing_key,
        pv_signing_key=get_node_signing_key(),
    )
    file_blockchain_w_memory_storage.add_block(block)
Beispiel #10
0
 def create_from_signed_change_request(
         cls: Type[T], blockchain,
         signed_change_request: SignedChangeRequest) -> T:
     signing_key = get_node_signing_key()
     block = cls(signer=derive_verify_key(signing_key),
                 message=BlockMessage.from_signed_change_request(
                     blockchain, signed_change_request))
     block.sign(signing_key)
     block.hash_message()
     return 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())
Beispiel #13
0
def add_blocks_to_blockchain(blockchain, block_count, treasury_account_private_key):
    treasury_account_key_pair = KeyPair(
        public=derive_public_key(treasury_account_private_key), private=treasury_account_private_key
    )
    generate_blockchain(
        blockchain,
        block_count,
        get_node_signing_key(),
        add_blockchain_genesis_state=False,
        validate=False,
        treasury_account_key_pair=treasury_account_key_pair
    )
def test_node_identifier_is_removed_when_node_declaration_signed_change_request_is_serialized(
        memory_blockchain, user_account_key_pair):
    request = NodeDeclarationSignedChangeRequest.create(
        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,
                                                    get_node_signing_key())
    compact_dict = block.to_compact_dict()
    assert ck('identifier') not in compact_dict[ck('message')][ck(
        'signed_change_request')][ck('message')][ck('node')]
Beispiel #15
0
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]
Beispiel #16
0
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_normalized_block_message(forced_mock_blockchain, sample_signed_change_request):
    expected_message_template = (
        '{'
        '"block_identifier":"next-block-identifier",'
        '"block_number":0,'
        '"block_type":"ct",'
        '"signed_change_request":'
        '{"message":{"balance_lock":'
        '"4d3cf1d9e4547d324de2084b568f807ef12045075a7a01b8bec1e7f013fc3732",'
        '"txs":'
        '[{"amount":425,"recipient":"484b3176c63d5f37d808404af1a12c4b9649cd6f6769f35bdf5a816133623fbc"},'
        '{"amount":1,"is_fee":true,"recipient":"5e12967707909e62b2bb2036c209085a784fabbc3deccefee70052b6181c8ed8"},'
        '{"amount":4,"is_fee":true,"recipient":'
        '"ad1f8845c6a1abb6011a2a434a079a087c460657aad54329a84b406dce8bf314"}]},'
        '"signature":"362dc47191d5d1a33308de1f036a5e93fbaf0b05fa971d9537f954f13cd22b5ed9bee56f4701bd'
        'af9b995c47271806ba73e75d63f46084f5830cec5f5b7e9600",'
        '"signer":"4d3cf1d9e4547d324de2084b568f807ef12045075a7a01b8bec1e7f013fc3732"},'
        '"timestamp":"<replace-with-timestamp>",'
        '"updated_account_states":{'
        '"484b3176c63d5f37d808404af1a12c4b9649cd6f6769f35bdf5a816133623fbc":{"balance":425},'
        '"4d3cf1d9e4547d324de2084b568f807ef12045075a7a01b8bec1e7f013fc3732":'
        '{'
        '"balance":20,'
        '"balance_lock":"ff3127bdb408e5f3f4f07dd364ce719b2854dc28ee66aa7af839e46468761885"'
        '},'
        '"5e12967707909e62b2bb2036c209085a784fabbc3deccefee70052b6181c8ed8":{"balance":1},'
        '"ad1f8845c6a1abb6011a2a434a079a087c460657aad54329a84b406dce8bf314":{"balance":4}'
        '}'
        '}'
    )

    def get_account_balance(self, account, on_block_number):
        return 450 if account == sample_signed_change_request.signer else 0

    with patch.object(MockBlockchain, 'get_account_balance', new=get_account_balance):
        block = Block.create_from_signed_change_request(
            forced_mock_blockchain, sample_signed_change_request, get_node_signing_key()
        )

    expected_message = expected_message_template.replace(
        '<replace-with-timestamp>', block.message.timestamp.isoformat()
    ).encode('utf-8')
    assert block.message.get_normalized() == expected_message
Beispiel #18
0
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_create_node_declaration_block(memory_blockchain,
                                       user_account_key_pair):
    request = NodeDeclarationSignedChangeRequest.create(
        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,
                                                    get_node_signing_key())
    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')
Beispiel #20
0
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 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(
        blockchain=file_blockchain_w_memory_storage,
        recipient=user_account,
        amount=100,
        request_signing_key=signing_key,
        pv_signing_key=get_node_signing_key(),
        primary_validator=pv,
        node=node
    )
    file_blockchain_w_memory_storage.add_block(block)
    file_blockchain_w_memory_storage.snapshot_blockchain_state()
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
Beispiel #23
0
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]
Beispiel #24
0
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

    node_signing_key = get_node_signing_key()
    block0 = Block.create_from_main_transaction(
        blockchain=blockchain,
        recipient=user_account,
        amount=30,
        request_signing_key=treasury_account_key_pair.private,
        pv_signing_key=node_signing_key,
    )
    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=blockchain,
        recipient=user_account,
        amount=10,
        request_signing_key=treasury_account_key_pair.private,
        pv_signing_key=node_signing_key,
    )
    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=blockchain,
        recipient=treasury_account,
        amount=5,
        request_signing_key=user_account_key_pair.private,
        pv_signing_key=node_signing_key,
    )
    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
Beispiel #25
0
def test_partial_blockchain(primary_validator, preferred_node):
    account1_key_pair = generate_key_pair()
    account2_key_pair = generate_key_pair()
    account3_key_pair = generate_key_pair()
    new_account_key_pair = generate_key_pair()

    fake_lock1, _ = generate_key_pair()
    fake_lock2, _ = generate_key_pair()
    fake_lock3, _ = generate_key_pair()

    base_account_root_file = BlockchainState(
        account_states={
            account1_key_pair.public: AccountState(balance=1000, balance_lock=fake_lock1),
            account2_key_pair.public: AccountState(balance=2000, balance_lock=fake_lock2),
            account3_key_pair.public: AccountState(balance=3000, balance_lock=fake_lock3),
        },
        last_block_number=1234,
        last_block_identifier='23203d245b5e128465669223b5220b3061af1e2e72b0429ef26b07ce3a2282e7',
        last_block_timestamp=datetime.utcnow(),
        next_block_identifier='626dea61c1a6480d6a4c9cd657c7d7be52ddc38e5f2ec590b609ac01edde62fd',
    )

    blockchain = MemoryBlockchain(account_root_files=[base_account_root_file])
    assert blockchain.get_block_count() == 0
    assert blockchain.get_account_current_balance(account1_key_pair.public) == 1000
    assert blockchain.get_account_current_balance(account2_key_pair.public) == 2000
    assert blockchain.get_account_current_balance(account3_key_pair.public) == 3000
    assert blockchain.get_account_current_balance(new_account_key_pair.public) == 0
    blockchain.validate()

    signed_change_request1 = CoinTransferSignedChangeRequest.from_main_transaction(
        blockchain=blockchain,
        recipient=account2_key_pair.public,
        amount=10,
        signing_key=account1_key_pair.private,
        primary_validator=primary_validator,
        node=preferred_node
    )
    signed_change_request1.validate(blockchain, blockchain.get_next_block_number())
    blockchain.add_block_from_signed_change_request(signed_change_request1, get_node_signing_key())
    blockchain.validate()

    assert blockchain.get_block_count() == 1
    assert blockchain.get_account_current_balance(account1_key_pair.public) == 1000 - 10 - 4 - 1
    assert blockchain.get_account_current_balance(account2_key_pair.public) == 2000 + 10
    assert blockchain.get_account_current_balance(account3_key_pair.public) == 3000
    assert blockchain.get_account_current_balance(new_account_key_pair.public) == 0

    signed_change_request2 = CoinTransferSignedChangeRequest.from_main_transaction(
        blockchain=blockchain,
        recipient=new_account_key_pair.public,
        amount=20,
        signing_key=account2_key_pair.private,
        primary_validator=primary_validator,
        node=preferred_node
    )
    signed_change_request2.validate(blockchain, blockchain.get_next_block_number())
    blockchain.add_block_from_signed_change_request(signed_change_request2, get_node_signing_key())
    blockchain.validate()

    assert blockchain.get_block_count() == 2
    assert blockchain.get_account_current_balance(account1_key_pair.public) == 1000 - 10 - 4 - 1
    assert blockchain.get_account_current_balance(account2_key_pair.public) == 2000 + 10 - 20 - 4 - 1
    assert blockchain.get_account_current_balance(account3_key_pair.public) == 3000
    assert blockchain.get_account_current_balance(new_account_key_pair.public) == 20

    blockchain.snapshot_blockchain_state()
    blockchain.validate()

    assert blockchain.get_account_current_balance(account1_key_pair.public) == 1000 - 10 - 4 - 1
    assert blockchain.get_account_current_balance(account2_key_pair.public) == 2000 + 10 - 20 - 4 - 1
    assert blockchain.get_account_current_balance(account3_key_pair.public) == 3000
    assert blockchain.get_account_current_balance(new_account_key_pair.public) == 20

    signed_change_request3 = CoinTransferSignedChangeRequest.from_main_transaction(
        blockchain=blockchain,
        recipient=account2_key_pair.public,
        amount=30,
        signing_key=account3_key_pair.private,
        primary_validator=primary_validator,
        node=preferred_node
    )
    signed_change_request3.validate(blockchain, blockchain.get_next_block_number())
    blockchain.add_block_from_signed_change_request(signed_change_request3, get_node_signing_key())
    blockchain.validate()

    assert blockchain.get_account_current_balance(account1_key_pair.public) == 1000 - 10 - 4 - 1
    assert blockchain.get_account_current_balance(account2_key_pair.public) == 2000 + 10 - 20 - 4 - 1 + 30
    assert blockchain.get_account_current_balance(account3_key_pair.public) == 3000 - 30 - 4 - 1
    assert blockchain.get_account_current_balance(new_account_key_pair.public) == 20
Beispiel #26
0
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])
def test_can_create_block_from_main_transaction(
    forced_mock_blockchain, treasury_account_key_pair: KeyPair, user_account_key_pair: KeyPair,
    primary_validator_key_pair: KeyPair, node_key_pair: KeyPair
):

    def get_account_balance(self, account, on_block_number):
        return 430 if account == treasury_account_key_pair.public else 0

    with patch.object(MockBlockchain, 'get_account_balance', new=get_account_balance):
        block = Block.create_from_main_transaction(
            forced_mock_blockchain, user_account_key_pair.public, 20, signing_key=treasury_account_key_pair.private
        )

    # Assert block
    assert block.message
    assert block.hash
    assert block.signature

    block.validate_signature()
    assert block.signer
    assert block.signer == derive_verify_key(get_node_signing_key())

    # Assert block.message
    block_message = block.message
    assert block_message
    assert isinstance(block_message.timestamp, datetime)
    assert block_message.timestamp.tzinfo is None
    assert block_message.timestamp - datetime.utcnow() < timedelta(seconds=1)

    assert block_message.block_number == 0
    assert block_message.block_identifier == 'next-block-identifier'
    updated_account_states = block_message.updated_account_states

    assert isinstance(updated_account_states, dict)
    assert len(updated_account_states) == 4

    assert updated_account_states[treasury_account_key_pair.public].balance == 430 - 25
    assert updated_account_states[treasury_account_key_pair.public].balance_lock

    assert updated_account_states[user_account_key_pair.public].balance == 20
    assert updated_account_states[user_account_key_pair.public].balance_lock is None

    assert updated_account_states[primary_validator_key_pair.public].balance == 4
    assert updated_account_states[primary_validator_key_pair.public].balance_lock is None

    assert updated_account_states[node_key_pair.public].balance == 1
    assert updated_account_states[node_key_pair.public].balance_lock is None

    # Assert block_message.signed_change_request
    signed_change_request = block_message.signed_change_request
    assert signed_change_request.signer == treasury_account_key_pair.public
    assert signed_change_request.signature

    # Assert block_message.signed_change_request.message
    coin_transfer_signed_request_message = signed_change_request.message
    assert isinstance(coin_transfer_signed_request_message, CoinTransferSignedChangeRequestMessage)
    assert coin_transfer_signed_request_message.balance_lock
    assert len(coin_transfer_signed_request_message.txs) == 3
    txs_dict = {tx.recipient: tx for tx in coin_transfer_signed_request_message.txs}
    assert len(txs_dict) == 3

    assert txs_dict[user_account_key_pair.public].amount == 20
    assert txs_dict[user_account_key_pair.public].is_fee is False

    assert txs_dict[primary_validator_key_pair.public].amount == 4
    assert txs_dict[primary_validator_key_pair.public].is_fee

    assert txs_dict[node_key_pair.public].amount == 1
    assert txs_dict[node_key_pair.public].is_fee

    assert coin_transfer_signed_request_message.get_total_amount() == 25
Beispiel #28
0
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=blockchain,
        recipient=recipient,
        amount=10,
        request_signing_key=treasury_account_key_pair.private,
        pv_signing_key=get_node_signing_key(),
    )
    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=blockchain,
        recipient=recipient,
        amount=11,
        request_signing_key=treasury_account_key_pair.private,
        pv_signing_key=get_node_signing_key(),
    )
    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=blockchain,
        recipient=recipient,
        amount=12,
        request_signing_key=treasury_account_key_pair.private,
        pv_signing_key=get_node_signing_key(),
    )
    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_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
def test_can_duplicate_recipients(
    forced_mock_blockchain: MockBlockchain, treasury_account_key_pair: KeyPair, user_account_key_pair: KeyPair
):

    def get_account_balance(self, account, on_block_number):
        return 430 if account == treasury_account_key_pair.public else 10

    sender = treasury_account_key_pair.public
    recipient = user_account_key_pair.public
    message = CoinTransferSignedChangeRequestMessage(
        balance_lock=forced_mock_blockchain.get_account_current_balance_lock(sender),
        txs=[
            CoinTransferTransaction(recipient=recipient, amount=3),
            CoinTransferTransaction(recipient=recipient, amount=5),
        ]
    )
    request = CoinTransferSignedChangeRequest.create_from_signed_change_request_message(
        message, treasury_account_key_pair.private
    )

    with patch.object(MockBlockchain, 'get_account_balance', new=get_account_balance):
        block = Block.create_from_signed_change_request(forced_mock_blockchain, request, get_node_signing_key())

    updated_account_states = block.message.updated_account_states
    assert len(updated_account_states) == 2

    sender_account_state = block.message.get_account_state(treasury_account_key_pair.public)
    assert sender_account_state
    assert sender_account_state.balance == 430 - 3 - 5
    assert sender_account_state.balance_lock

    recipient_account_state = block.message.get_account_state(user_account_key_pair.public)
    assert recipient_account_state
    assert recipient_account_state.balance == 10 + 3 + 5