def test_sync(client: Client, receiver_address, receiver_privkey):
    c = client.get_suitable_channel(receiver_address, 5, initial_deposit=lambda x: x)
    assert c is not None
    assert c in client.channels
    assert c.deposit == 5
    assert len(client.channels) == 1

    # Check if channel is still valid after sync.
    client.sync_channels()
    assert c in client.channels
    assert len(client.channels) == 1

    # Check if client handles topup events on sync.
    c_topup = client.get_suitable_channel(receiver_address, 7, topup_deposit=lambda x: 2)
    assert c is not None
    assert c_topup == c
    assert len(client.channels) == 1
    assert c.deposit == 7

    # Check if channel can be resynced after data loss.
    client.channels = []
    client.sync_channels()
    assert len(client.channels) == 1
    c = client.channels[0]
    assert c.deposit == 7

    # Check if channel is forgotten on resync after closure.
    close_channel_cooperatively(c, receiver_privkey, client.context.channel_manager.address)

    client.sync_channels()
    assert c not in client.channels
Exemple #2
0
def test_sync(client: Client, receiver_address, receiver_privkey):
    c = client.get_suitable_channel(receiver_address,
                                    5,
                                    initial_deposit=lambda x: x)
    assert c in client.channels
    assert c.deposit == 5
    assert len(client.channels) == 1

    # Check if channel is still valid after sync.
    client.sync_channels()
    assert c in client.channels
    assert len(client.channels) == 1

    # Check if client handles topup events on sync.
    c_topup = client.get_suitable_channel(receiver_address,
                                          7,
                                          topup_deposit=lambda x: 2)
    assert c_topup == c
    assert len(client.channels) == 1
    assert c.deposit == 7

    # Check if channel can be resynced after data loss.
    client.channels = []
    client.sync_channels()
    assert len(client.channels) == 1
    c = client.channels[0]
    assert c.deposit == 7

    # Check if channel is forgotten on resync after closure.
    close_channel_cooperatively(c, receiver_privkey,
                                client.context.channel_manager.address)

    client.sync_channels()
    assert c not in client.channels
Exemple #3
0
def test_static_price(empty_proxy: PaywalledProxy, api_endpoint_address: str,
                      client: Client, wait_for_blocks, receiver_privkey: str):
    proxy = empty_proxy
    endpoint_url = "http://" + api_endpoint_address

    content = PaywalledContent(
        'resource',
        price=3,
        get_fn=lambda url: ('SUCCESS', 200),
    )
    proxy.add_content(content)

    response = requests.get(endpoint_url + '/resource')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 3

    channel = client.get_suitable_channel(headers.receiver_address, 3)
    wait_for_blocks(6)
    channel.balance = 3

    headers = Munch()
    headers.balance = str(channel.balance)
    headers.balance_signature = encode_hex(channel.balance_sig)
    headers.sender_address = channel.sender
    headers.open_block = str(channel.block)
    headers = HTTPHeaders.serialize(headers)

    response = requests.get(endpoint_url + '/resource', headers=headers)
    assert response.status_code == 200
    assert response.text.strip() == '"SUCCESS"'

    close_channel_cooperatively(channel, receiver_privkey,
                                client.channel_manager_address, 0)
Exemple #4
0
def test_integrity(client: Client, receiver_address):
    c = client.get_suitable_channel(receiver_address, 5)
    assert c is not None
    assert c.balance == 0
    assert c.balance_sig == sign_balance_proof(
        client.context.private_key,
        receiver_address,
        c.block,
        0,
        client.context.channel_manager.address
    )
    assert c.is_valid()

    # Balance update without sig update.
    c._balance = 2
    assert not c.is_valid()

    # Proper balance update with sig update.
    c.update_balance(2)
    assert c.is_valid()

    # Random sig.
    c._balance_sig = b'wrong'
    assert not c.is_valid()

    # Balance exceeds deposit.
    c.update_balance(100)
    assert not c.is_valid()

    c.update_balance(0)
Exemple #5
0
def test_explicit_json(
        empty_proxy: PaywalledProxy,
        api_endpoint_address: str,
        client: Client,
        wait_for_blocks
):
    proxy = empty_proxy
    endpoint_url = "http://" + api_endpoint_address

    proxy.add_paywalled_resource(JSONResource, '/resource', 3)

    # test GET
    response = requests.get(endpoint_url + '/resource')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 3

    channel = client.get_suitable_channel(headers.receiver_address, int(headers.price) * 4)
    wait_for_blocks(6)
    channel.update_balance(int(headers.price))

    headers = Munch()
    headers.balance = str(channel.balance)
    headers.balance_signature = encode_hex(channel.balance_sig)
    headers.sender_address = channel.sender
    headers.open_block = str(channel.block)
    headers = HTTPHeaders.serialize(headers)

    response = requests.get(endpoint_url + '/resource', headers=headers)
    assert response.status_code == 200
    # If headers don't merge properly, this results in 'application/json,application/json'.
    assert response.headers['Content-Type'] == 'application/json'
    assert response.json() == {'GET': 1}
Exemple #6
0
def test_explicit_json(empty_proxy: PaywalledProxy, api_endpoint_address: str,
                       client: Client, wait_for_blocks):
    proxy = empty_proxy
    endpoint_url = "http://" + api_endpoint_address

    proxy.add_paywalled_resource(JSONResource, '/resource', 3)

    # test GET
    response = requests.get(endpoint_url + '/resource')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 3

    channel = client.get_suitable_channel(headers.receiver_address,
                                          int(headers.price) * 4)
    wait_for_blocks(6)
    channel.update_balance(int(headers.price))

    headers = Munch()
    headers.balance = str(channel.balance)
    headers.balance_signature = encode_hex(channel.balance_sig)
    headers.sender_address = channel.sender
    headers.open_block = str(channel.block)
    headers = HTTPHeaders.serialize(headers)

    response = requests.get(endpoint_url + '/resource', headers=headers)
    assert response.status_code == 200
    # If headers don't merge properly, this results in 'application/json,application/json'.
    assert response.headers['Content-Type'] == 'application/json'
    assert response.json() == {'GET': 1}
Exemple #7
0
def test_static_price(empty_proxy: PaywalledProxy, api_endpoint_address: str,
                      client: Client, wait_for_blocks):
    proxy = empty_proxy
    endpoint_url = "http://" + api_endpoint_address

    proxy.add_paywalled_resource(StaticPriceResource, '/resource', 3)

    # test GET
    response = requests.get(endpoint_url + '/resource')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 3

    channel = client.get_suitable_channel(headers.receiver_address,
                                          int(headers.price) * 4)
    wait_for_blocks(6)
    channel.update_balance(int(headers.price))

    headers = Munch()
    headers.balance = str(channel.balance)
    headers.balance_signature = encode_hex(channel.balance_sig)
    headers.sender_address = channel.sender
    headers.open_block = str(channel.block)
    headers = HTTPHeaders.serialize(headers)

    response = requests.get(endpoint_url + '/resource', headers=headers)
    assert response.status_code == 200
    assert response.text.strip() == 'GET'

    assert_method(requests.post, endpoint_url + '/resource', headers, channel,
                  'POST')
    assert_method(requests.put, endpoint_url + '/resource', headers, channel,
                  'PUT')
    assert_method(requests.delete, endpoint_url + '/resource', headers,
                  channel, 'DEL')
Exemple #8
0
def test_static_price(
        empty_proxy: PaywalledProxy,
        api_endpoint_address: str,
        client: Client,
        wait_for_blocks
):
    proxy = empty_proxy
    endpoint_url = "http://" + api_endpoint_address

    proxy.add_paywalled_resource(StaticPriceResource, '/resource', 3)

    # test GET
    response = requests.get(endpoint_url + '/resource')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 3

    channel = client.get_suitable_channel(headers.receiver_address, int(headers.price) * 4)
    wait_for_blocks(6)
    channel.update_balance(int(headers.price))

    headers = Munch()
    headers.balance = str(channel.balance)
    headers.balance_signature = encode_hex(channel.balance_sig)
    headers.sender_address = channel.sender
    headers.open_block = str(channel.block)
    headers = HTTPHeaders.serialize(headers)

    response = requests.get(endpoint_url + '/resource', headers=headers)
    assert response.status_code == 200
    assert response.text.strip() == 'GET'

    assert_method(requests.post, endpoint_url + '/resource', headers, channel, 'POST')
    assert_method(requests.put, endpoint_url + '/resource', headers, channel, 'PUT')
    assert_method(requests.delete, endpoint_url + '/resource', headers, channel, 'DEL')
Exemple #9
0
def test_dynamic_price(empty_proxy: PaywalledProxy, api_endpoint_address: str,
                       client: Client, wait_for_blocks, receiver_privkey: str):
    proxy = empty_proxy
    endpoint_url = "http://" + api_endpoint_address

    price_cycle = cycle([1, 2, 3, 4, 5])
    url_to_price = {}

    def price_fn(url: str):
        if url in url_to_price:
            price = url_to_price[url]
        else:
            price = next(price_cycle)
            url_to_price[url] = price
        return price

    content = PaywalledContent(
        'resource_\d',
        price=price_fn,
        get_fn=lambda url: (url.split("_")[1], 200),
    )
    proxy.add_content(content)

    response = requests.get(endpoint_url + '/resource_3')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 1

    response = requests.get(endpoint_url + '/resource_5')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 2

    response = requests.get(endpoint_url + '/resource_2')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 3

    response = requests.get(endpoint_url + '/resource_3')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 1

    channel = client.get_suitable_channel(headers.receiver_address, 2)
    wait_for_blocks(6)
    channel.balance = 2

    headers = Munch()
    headers.balance = str(channel.balance)
    headers.balance_signature = encode_hex(channel.balance_sig)
    headers.sender_address = channel.sender
    headers.open_block = str(channel.block)
    headers = HTTPHeaders.serialize(headers)

    response = requests.get(endpoint_url + '/resource_5', headers=headers)
    assert response.status_code == 200
    assert response.text.strip() == '"5"'

    close_channel_cooperatively(channel, receiver_privkey,
                                client.channel_manager_address, 0)
Exemple #10
0
def test_get_expired(empty_proxy: PaywalledProxy, api_endpoint_address: str,
                     sender_address: str, receiver_address: str,
                     client: Client, wait_for_blocks):
    """
    Test with manual client interaction for isolated server testing.
    Note: Debug in microraiden.proxy.resources.expensive for most of the server response logic.
    """
    es_mock = ElasticsearchBackend(None)
    es_mock.search = mock.Mock(return_value=Resource(
        price=5, content='success', expires_at=time.time() + 0.05))
    APIServer(empty_proxy, es=es_mock)
    api_path = 'http://' + api_endpoint_address

    # Request price (and cache resource).
    body = {'query': 'query something'}
    url = api_path + '/some_index/some_type/_search'
    response = requests.get(url, json=body)
    assert response.status_code == 402

    # Perform payment and request same resource again. Include payment information in headers.
    channel = client.get_suitable_channel(receiver_address, 5)
    # Server requires some confirmations, so mine some blocks.
    wait_for_blocks(10)
    channel.create_transfer(5)

    headers = Munch()
    headers.balance = str(channel.balance)
    headers.balance_signature = encode_hex(channel.balance_sig)
    headers.sender_address = sender_address
    headers.receiver_address = receiver_address
    headers.open_block = str(channel.block)
    headers = HTTPHeaders.serialize(headers)

    # Make sure the price changes for the next request.
    es_mock.search = mock.Mock(return_value=Resource(
        price=3, content='success', expires_at=time.time() + 0.05))
    # Let former query expire.
    gevent.sleep(0.1)

    # Query same resource again with the old expired price.
    response = requests.get(url, headers=headers, json=body)

    assert response.status_code == 402
    assert response.headers[HTTPHeaders.PRICE] == '3'

    channel.update_balance(3)
    headers[HTTPHeaders.BALANCE] = str(channel.balance)
    headers[HTTPHeaders.BALANCE_SIGNATURE] = encode_hex(channel.balance_sig)

    response = requests.get(url, headers=headers, json=body)

    assert response.json() == 'success'

    es_mock.search.call_args_list == [{
        'query': 'query something'
    }, {
        'query': 'query something'
    }]
Exemple #11
0
def test_get(empty_proxy: PaywalledProxy, api_endpoint_address: str,
             channel_manager_address: str, token_address: str,
             sender_address: str, receiver_address: str, client: Client,
             wait_for_blocks):
    """
    Test with manual client interaction for isolated server testing.
    Note: Debug in microraiden.proxy.resources.expensive for most of the server response logic.
    """
    es_mock = ElasticsearchBackend(None)
    es_mock.search = mock.Mock(return_value=Resource(
        price=5, content='success', expires_at=time.time() + 30))
    server = APIServer(empty_proxy, es=es_mock)
    api_path = 'http://' + api_endpoint_address

    # Request price (and cache resource).
    body = {'query': 'query something'}
    url = api_path + '/some_index/some_type/_search'
    response = requests.get(url, json=body)

    print(response.content)
    assert response.status_code == 402

    headers = HTTPHeaders.deserialize(response.headers)
    assert headers.token_address == token_address
    assert headers.contract_address == channel_manager_address
    assert headers.receiver_address == receiver_address
    price = int(headers.price)
    assert price == 5
    assert len(server.resource_cache) == 1

    # Perform payment and request same resource again. Include payment information in headers.
    channel = client.get_suitable_channel(receiver_address, price)
    # Server requires some confirmations, so mine some blocks.
    wait_for_blocks(10)
    channel.create_transfer(price)

    headers = Munch()
    headers.balance = str(channel.balance)
    headers.balance_signature = encode_hex(channel.balance_sig)
    headers.sender_address = sender_address
    headers.receiver_address = receiver_address
    headers.open_block = str(channel.block)
    headers = HTTPHeaders.serialize(headers)

    response = requests.get(url, headers=headers, json=body)
    headers = HTTPHeaders.deserialize(response.headers)

    assert 'nonexisting_channel' not in headers, 'Server should acknowledge the created channel.'
    assert 'insuf_confs' not in headers, 'Server should acknowledge the created channel.'
    assert 'invalid_amount' not in headers, 'The correct amount should have been sent.'
    assert response.status_code == 200
    assert response.json() == 'success'
    assert len(server.resource_cache) == 1

    es_mock.search.assert_called_once_with(index='some_index',
                                           doc_type='some_type',
                                           body={'query': 'query something'})
def test_cooperative_close(client: Client, receiver_privkey, receiver_address):
    c = client.get_suitable_channel(receiver_address, 3)
    c.create_transfer(3)

    assert c.deposit >= 3
    assert c.balance == 3

    sig = sign_balance_proof(receiver_privkey, c.receiver, c.block, c.balance)
    assert c.close_cooperatively(sig)
    assert c.state == Channel.State.closed
Exemple #13
0
def test_cooperative_close(client: Client, receiver_privkey, receiver_address):
    c = client.get_suitable_channel(receiver_address, 3)
    assert c is not None
    c.create_transfer(3)

    assert c.deposit >= 3
    assert c.balance == 3

    sig = sign_close(receiver_privkey, c.sender, c.block, c.balance,
                     client.context.channel_manager.address)
    assert c.close_cooperatively(sig)
    assert c.state == Channel.State.closed
Exemple #14
0
def test_dynamic_price(empty_proxy: PaywalledProxy, api_endpoint_address: str,
                       client: Client, wait_for_blocks):
    proxy = empty_proxy
    endpoint_url = "http://" + api_endpoint_address

    price_cycle = cycle([1, 2, 3, 4, 5])
    url_to_price = {}  # type: Dict

    def price_fn(url: str):
        if url in url_to_price:
            price = url_to_price[url]
        else:
            price = next(price_cycle)
            url_to_price[url] = price
        return price

    proxy.add_paywalled_resource(DynamicPriceResource,
                                 '/resource_<int:res_id>', price_fn)

    response = requests.get(endpoint_url + '/resource_3')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 1

    response = requests.get(endpoint_url + '/resource_5')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 2

    response = requests.get(endpoint_url + '/resource_2')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 3

    response = requests.get(endpoint_url + '/resource_3')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 1

    channel = client.get_suitable_channel(headers.receiver_address, 2)
    wait_for_blocks(6)
    channel.update_balance(2)

    headers = Munch()
    headers.balance = str(channel.balance)
    headers.balance_signature = encode_hex(channel.balance_sig)
    headers.sender_address = channel.sender
    headers.open_block = str(channel.block)
    headers = HTTPHeaders.serialize(headers)

    response = requests.get(endpoint_url + '/resource_5', headers=headers)
    assert response.status_code == 200
    assert response.text.strip() == '5'
Exemple #15
0
def test_method_price(empty_proxy: PaywalledProxy, api_endpoint_address: str,
                      client: Client, wait_for_blocks):
    proxy = empty_proxy
    endpoint_url = "http://" + api_endpoint_address

    proxy.add_paywalled_resource(DynamicMethodResource,
                                 '/resource',
                                 resource_class_args=(42, ),
                                 resource_class_kwargs={'bar': 9814072356})

    # test GET
    response = requests.get(endpoint_url + '/resource')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 1

    channel = client.get_suitable_channel(headers.receiver_address,
                                          1 + 2 + 3 + 4)
    wait_for_blocks(6)
    channel.update_balance(int(headers.price))

    headers = Munch()
    headers.balance = str(channel.balance)
    headers.balance_signature = encode_hex(channel.balance_sig)
    headers.sender_address = channel.sender
    headers.open_block = str(channel.block)
    headers = HTTPHeaders.serialize(headers)

    response = requests.get(endpoint_url + '/resource', headers=headers)
    assert response.status_code == 200
    assert response.text.strip() == 'GET'

    assert_method(requests.post,
                  endpoint_url + '/resource',
                  headers,
                  channel,
                  'POST',
                  expected_price=2)
    assert_method(requests.put,
                  endpoint_url + '/resource',
                  headers,
                  channel,
                  'PUT',
                  expected_price=3)
    assert_method(requests.delete,
                  endpoint_url + '/resource',
                  headers,
                  channel,
                  'DEL',
                  expected_price=4)
Exemple #16
0
def test_method_price(
        empty_proxy: PaywalledProxy,
        api_endpoint_address: str,
        client: Client,
        wait_for_blocks
):
    proxy = empty_proxy
    endpoint_url = "http://" + api_endpoint_address

    proxy.add_paywalled_resource(
        DynamicMethodResource,
        '/resource',
        resource_class_args=(42,),
        resource_class_kwargs={'bar': 9814072356})

    # test GET
    response = requests.get(endpoint_url + '/resource')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 1

    channel = client.get_suitable_channel(headers.receiver_address, 1 + 2 + 3 + 4)
    wait_for_blocks(6)
    channel.update_balance(int(headers.price))

    headers = Munch()
    headers.balance = str(channel.balance)
    headers.balance_signature = encode_hex(channel.balance_sig)
    headers.sender_address = channel.sender
    headers.open_block = str(channel.block)
    headers = HTTPHeaders.serialize(headers)

    response = requests.get(endpoint_url + '/resource', headers=headers)
    assert response.status_code == 200
    assert response.text.strip() == 'GET'

    assert_method(requests.post,
                  endpoint_url + '/resource',
                  headers, channel, 'POST',
                  expected_price=2)
    assert_method(requests.put,
                  endpoint_url + '/resource',
                  headers, channel, 'PUT',
                  expected_price=3)
    assert_method(requests.delete,
                  endpoint_url + '/resource',
                  headers, channel, 'DEL',
                  expected_price=4)
Exemple #17
0
def test_cooperative_close(client: Client, receiver_privkey, receiver_address):
    c = client.get_suitable_channel(receiver_address, 3)
    assert c is not None
    c.create_transfer(3)

    assert c.deposit >= 3
    assert c.balance == 3

    sig = sign_close(
        receiver_privkey,
        c.sender,
        c.block,
        c.balance,
        client.context.channel_manager.address
    )
    assert c.close_cooperatively(sig)
    assert c.state == Channel.State.closed
Exemple #18
0
def test_integrity(client: Client, receiver_address):
    c = client.get_suitable_channel(receiver_address, 5)
    assert c.balance == 0
    assert c.balance_sig == sign_balance_proof(client.privkey, receiver_address, c.block, 0)
    assert c.is_valid()

    # Balance update without sig update.
    c._balance = 2
    assert not c.is_valid()

    # Proper balance update with sig update.
    c.balance = 2
    assert c.is_valid()

    # Random sig.
    c._balance_sig = b'wrong'
    assert not c.is_valid()

    # Balance exceeds deposit.
    c.balance = 100
    assert not c.is_valid()
def test_sync(client: Client, receiver_address, receiver_privkey):
    c = client.get_suitable_channel(receiver_address, 5)
    assert c in client.channels
    assert len(client.channels) == 1

    # Check if channel is still valid after sync.
    client.sync_channels()
    assert c in client.channels
    assert len(client.channels) == 1

    # Check if channel can be resynced after data loss.
    client.channels = []
    client.store_channels()
    client.sync_channels()

    # Check if channel is forgotten on resync after closure.
    assert len(client.channels) == 1
    c = client.channels[0]
    close_channel_cooperatively(c, receiver_privkey)

    client.sync_channels()
    assert c not in client.channels
Exemple #20
0
def test_dynamic_price(
        empty_proxy: PaywalledProxy,
        api_endpoint_address: str,
        client: Client,
        wait_for_blocks
):
    proxy = empty_proxy
    endpoint_url = "http://" + api_endpoint_address

    price_cycle = cycle([1, 2, 3, 4, 5])
    url_to_price = {}  # type: Dict

    def price_fn():
        url = request.path
        if int(url.split('_')[-1]) == 0:
            return 0
        if url in url_to_price:
            price = url_to_price[url]
        else:
            price = next(price_cycle)
            url_to_price[url] = price
        return price

    proxy.add_paywalled_resource(
        DynamicPriceResource,
        '/resource_<int:res_id>',
        price=price_fn
    )

    response = requests.get(endpoint_url + '/resource_3')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 1

    response = requests.get(endpoint_url + '/resource_5')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 2

    response = requests.get(endpoint_url + '/resource_2')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 3

    response = requests.get(endpoint_url + '/resource_3')
    assert response.status_code == 402
    headers = HTTPHeaders.deserialize(response.headers)
    assert int(headers.price) == 1

    response = requests.get(endpoint_url + '/resource_0')
    assert response.status_code == 200
    assert response.text.strip() == '0'

    channel = client.get_suitable_channel(headers.receiver_address, 2)
    wait_for_blocks(6)
    channel.update_balance(2)

    headers = Munch()
    headers.balance = str(channel.balance)
    headers.balance_signature = encode_hex(channel.balance_sig)
    headers.sender_address = channel.sender
    headers.open_block = str(channel.block)
    headers = HTTPHeaders.serialize(headers)

    response = requests.get(endpoint_url + '/resource_5', headers=headers)
    assert response.status_code == 200
    assert response.text.strip() == '5'