Exemplo n.º 1
0
    def __init__(
            self,
            sender_privkey: str,
            httpclient: DefaultHTTPClient = None
    ):
        self.root = tkinter.Tk()
        ttk.Frame.__init__(self, self.root)
        self.root.title('µRaiden ETH Ticker')
        self.root.protocol('WM_DELETE_WINDOW', self.close)
        self.pack()
        self.pricevar = tkinter.StringVar(value='0.00 USD')
        ttk.Label(self, textvariable=self.pricevar, font=('Helvetica', '72')).pack()

        if httpclient:
            self.httpclient = httpclient
            self.client = httpclient.client
        else:
            self.client = Client(sender_privkey)
            self.httpclient = DefaultHTTPClient(
                self.client,
                'localhost',
                5000,
                initial_deposit=lambda x: 10 * x,
                topup_deposit=lambda x: 5 * x
            )

        self.active_query = False
        self.running = False
Exemplo n.º 2
0
def client(sender_privkey: str, client_contract_proxy: ChannelContractProxy,
           client_token_proxy: ContractProxy, datadir: str):
    client = Client(privkey=sender_privkey,
                    channel_manager_proxy=client_contract_proxy,
                    token_proxy=client_token_proxy,
                    datadir=datadir)
    yield client
    client.close()
Exemplo n.º 3
0
def close_all_channels_cooperatively(
        client: Client, privkey_receiver: str, contract_address: str, balance: int=None
):
    receiver_addr = privkey_to_addr(privkey_receiver)
    client.sync_channels()
    channels = [c for c in client.channels
                if c.state != Channel.State.closed and c.receiver == receiver_addr]
    for channel in channels:
        close_channel_cooperatively(channel, privkey_receiver, contract_address, balance)
def client(sender_privkey, client_contract_proxy, client_token_proxy, datadir,
           channel_manager_contract_address, token_contract_address):
    client = Client(privkey=sender_privkey,
                    channel_manager_proxy=client_contract_proxy,
                    token_proxy=client_token_proxy,
                    datadir=datadir,
                    channel_manager_address=channel_manager_contract_address,
                    token_address=token_contract_address)
    yield client
    client.close()
Exemplo n.º 5
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
Exemplo n.º 6
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 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
Exemplo n.º 7
0
def test_reorg(
        web3: Web3,
        channel_manager: ChannelManager,
        client: Client,
        receiver_address: str,
        wait_for_blocks,
        use_tester: bool
):
    if not use_tester:
        pytest.skip('Chain reorg tests only work in tester chain')
    wait_for_blocks(10)
    # create unconfirmed channel
    channel_manager.wait_sync()
    snapshot_id = web3.testing.snapshot()
    channel = client.open_channel(receiver_address, 10)
    wait_for_blocks(0)
    assert (channel.sender, channel.block) in channel_manager.unconfirmed_channels

    # remove unconfirmed channel opening with reorg
    web3.testing.revert(snapshot_id)
    snapshot_id = web3.testing.snapshot()
    wait_for_blocks(0)
    assert (channel.sender, channel.block) not in channel_manager.unconfirmed_channels
    web3.testing.mine(channel_manager.n_confirmations)
    assert (channel.sender, channel.block) not in channel_manager.channels

    # leave confirmed channel opening
    web3.testing.revert(snapshot_id)
    channel = client.open_channel(receiver_address, 10)
    wait_for_blocks(channel_manager.n_confirmations)
    assert (channel.sender, channel.block) in channel_manager.channels
    confirmed_snapshot_id = web3.testing.snapshot()
    wait_for_blocks(3)
    web3.testing.revert(confirmed_snapshot_id)
    assert (channel.sender, channel.block) in channel_manager.channels

    # remove unconfirmed topup
    channel = client.open_channel(receiver_address, 10)
    wait_for_blocks(channel_manager.n_confirmations)
    assert (channel.sender, channel.block) in channel_manager.channels
    topup_snapshot_id = web3.testing.snapshot()
    channel.topup(5)
    wait_for_blocks(0)
    channel_rec = channel_manager.channels[channel.sender, channel.block]
    assert len(channel_rec.unconfirmed_topups) == 1
    web3.testing.revert(topup_snapshot_id)
    wait_for_blocks(0)
    assert (channel.sender, channel.block) in channel_manager.channels
    channel_rec = channel_manager.channels[channel.sender, channel.block]
    assert len(channel_rec.unconfirmed_topups) == 0
def test_reorg(
        web3: Web3,
        channel_manager: ChannelManager,
        client: Client,
        receiver_address: str,
        wait_for_blocks,
        use_tester: bool
):
    if not use_tester:
        pytest.skip('Chain reorg tests only work in tester chain')
    wait_for_blocks(10)
    # create unconfirmed channel
    channel_manager.wait_sync()
    snapshot_id = web3.testing.snapshot()
    channel = client.open_channel(receiver_address, 10)
    wait_for_blocks(0)
    assert (channel.sender, channel.block) in channel_manager.unconfirmed_channels

    # remove unconfirmed channel opening with reorg
    web3.testing.revert(snapshot_id)
    snapshot_id = web3.testing.snapshot()
    wait_for_blocks(0)
    assert (channel.sender, channel.block) not in channel_manager.unconfirmed_channels
    web3.testing.mine(channel_manager.n_confirmations)
    assert (channel.sender, channel.block) not in channel_manager.channels

    # leave confirmed channel opening
    web3.testing.revert(snapshot_id)
    channel = client.open_channel(receiver_address, 10)
    wait_for_blocks(channel_manager.n_confirmations)
    assert (channel.sender, channel.block) in channel_manager.channels
    confirmed_snapshot_id = web3.testing.snapshot()
    wait_for_blocks(3)
    web3.testing.revert(confirmed_snapshot_id)
    assert (channel.sender, channel.block) in channel_manager.channels

    # remove unconfirmed topup
    channel = client.open_channel(receiver_address, 10)
    wait_for_blocks(channel_manager.n_confirmations)
    assert (channel.sender, channel.block) in channel_manager.channels
    topup_snapshot_id = web3.testing.snapshot()
    channel.topup(5)
    wait_for_blocks(0)
    channel_rec = channel_manager.channels[channel.sender, channel.block]
    assert len(channel_rec.unconfirmed_topups) == 1
    web3.testing.revert(topup_snapshot_id)
    wait_for_blocks(0)
    assert (channel.sender, channel.block) in channel_manager.channels
    channel_rec = channel_manager.channels[channel.sender, channel.block]
    assert len(channel_rec.unconfirmed_topups) == 0
Exemplo n.º 9
0
def close_all_channels_cooperatively(
        client: Client, private_keys: List[str], contract_address: str, balance: int=None
):
    addresses_to_keys = {
        to_checksum_address(privkey_to_addr(private_key)): private_key
        for private_key in private_keys
    }
    client.sync_channels()
    closable_channels = [c for c in client.channels if c.state != Channel.State.closed]
    log.info('Closing {} channels.'.format(len(closable_channels)))
    for channel in closable_channels:
        private_key = addresses_to_keys.get(to_checksum_address(channel.receiver))
        if private_key is not None:
            close_channel_cooperatively(channel, private_key, contract_address, balance)
Exemplo n.º 10
0
def test_challenge(
        channel_manager: ChannelManager,
        confirmed_open_channel: Channel,
        receiver_address: str,
        sender_address: str,
        wait_for_blocks,
        web3: Web3,
        client: Client
):
    blockchain = channel_manager.blockchain
    channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block)
    sig = encode_hex(confirmed_open_channel.create_transfer(5))
    channel_manager.register_payment(sender_address, confirmed_open_channel.block, 5, sig)
    # hack channel to decrease balance
    confirmed_open_channel.update_balance(0)
    sig = confirmed_open_channel.create_transfer(3)
    block_before = web3.eth.blockNumber
    confirmed_open_channel.close()
    # should challenge and immediately settle
    for waited_blocks in count():
        logs = get_logs(client.context.token, 'Transfer', from_block=block_before - 1)
        if logs:
            break
        wait_for_blocks(1)
        assert waited_blocks < 10

    assert len([l for l in logs
                if is_same_address(l['args']['_to'], receiver_address) and
                l['args']['_value'] == 5]) == 1
    assert len([l for l in logs
                if is_same_address(l['args']['_to'], sender_address) and
                l['args']['_value'] == 5]) == 1
    wait_for_blocks(blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    assert channel_id not in channel_manager.channels

    # update channel state so that it will not be closed twice
    client.sync_channels()
    new_state = None
    for channel in client.channels:
        if all(channel.sender == confirmed_open_channel.sender,
               channel.receiver == confirmed_open_channel.receiver,
               channel.block == confirmed_open_channel.block):
            new_state = channel.state
    if new_state is None:
        confirmed_open_channel.state = confirmed_open_channel.State.closed
    else:
        confirmed_open_channel.state = new_state
Exemplo n.º 11
0
def test_challenge(
        channel_manager: ChannelManager,
        confirmed_open_channel: Channel,
        receiver_address: str,
        sender_address: str,
        wait_for_blocks,
        web3: Web3,
        client: Client
):
    blockchain = channel_manager.blockchain
    channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block)
    sig = encode_hex(confirmed_open_channel.create_transfer(5))
    channel_manager.register_payment(sender_address, confirmed_open_channel.block, 5, sig)
    # hack channel to decrease balance
    confirmed_open_channel.update_balance(0)
    sig = confirmed_open_channel.create_transfer(3)
    block_before = web3.eth.blockNumber
    confirmed_open_channel.close()
    # should challenge and immediately settle
    for waited_blocks in count():
        logs = get_logs(client.context.token, 'Transfer', from_block=block_before - 1)
        if logs:
            break
        wait_for_blocks(1)
        assert waited_blocks < 10

    assert len([l for l in logs
                if is_same_address(l['args']['_to'], receiver_address) and
                l['args']['_value'] == 5]) == 1
    assert len([l for l in logs
                if is_same_address(l['args']['_to'], sender_address) and
                l['args']['_value'] == 5]) == 1
    wait_for_blocks(blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    assert channel_id not in channel_manager.channels

    # update channel state so that it will not be closed twice
    client.sync_channels()
    new_state = None
    for channel in client.channels:
        if all(channel.sender == confirmed_open_channel.sender,
               channel.receiver == confirmed_open_channel.receiver,
               channel.block == confirmed_open_channel.block):
            new_state = channel.state
    if new_state is None:
        confirmed_open_channel.state = confirmed_open_channel.State.closed
    else:
        confirmed_open_channel.state = new_state
Exemplo n.º 12
0
def init(privkey: str = None,
         key_path: str = None,
         key_password_path: str = None,
         channel_manager_address: str = CHANNEL_MANAGER_ADDRESS,
         web3: Web3 = None,
         channel_manager_proxy: ChannelContractProxy = None,
         token_proxy: ContractProxy = None,
         contract_metadata: dict = CONTRACT_METADATA,
         retry_interval: float = 5,
         initial_deposit: Callable[[int], int] = lambda price: 10 * price,
         topup_deposit: Callable[[int], int] = lambda price: 5 * price):
    global client
    global http_client
    client = Client(privkey=privkey,
                    key_path=key_path,
                    key_password_path=key_password_path,
                    channel_manager_address=channel_manager_address,
                    web3=web3,
                    channel_manager_proxy=channel_manager_proxy,
                    token_proxy=token_proxy,
                    contract_metadata=contract_metadata)
    http_client = DefaultHTTPClient(client=client,
                                    retry_interval=retry_interval,
                                    initial_deposit=initial_deposit,
                                    topup_deposit=topup_deposit)
Exemplo n.º 13
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)
Exemplo n.º 14
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)
Exemplo n.º 15
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)
Exemplo n.º 16
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')
Exemplo n.º 17
0
def test_withdraw_above_minimum(
        client: Client,
        channel_manager: ChannelManager,
        web3: Web3,
        wait_for_blocks
):
    sender = client.context.address
    receiver = channel_manager.receiver

    channel = client.open_channel(receiver, 10)
    wait_for_blocks(channel_manager.n_confirmations + 1)
    channel_manager.register_payment(sender, channel.block, 4,
                                     encode_hex(channel.create_transfer(4)))

    channel_manager.stop()  # don't update state from this point on
    channel_manager.join()
    state = channel_manager.state
    tx_count_before = web3.eth.getTransactionCount(receiver)
    withdraw_from_channels(
        channel_manager.private_key,
        state,
        channel_manager.channel_manager_contract,
        3,
        wait=lambda: wait_for_blocks(1)
    )
    tx_count_after = web3.eth.getTransactionCount(receiver)
    assert tx_count_after == tx_count_before + 1

    channel_id = (channel.sender, channel.receiver, channel.block)
    channel_info = channel_manager.channel_manager_contract.call().getChannelInfo(*channel_id)
    _, deposit, settle_block_number, closing_balance, transferred_tokens = channel_info
    assert transferred_tokens == 4

    wait_for_blocks(1)
Exemplo n.º 18
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}
Exemplo n.º 19
0
def test_close_settled(client: Client, channel_manager: ChannelManager,
                       web3: Web3, wait_for_blocks):
    sender = client.context.address
    receiver = channel_manager.receiver

    channel = client.open_channel(receiver, 10)
    wait_for_blocks(channel_manager.n_confirmations + 1)
    channel_manager.register_payment(sender, channel.block, 2,
                                     encode_hex(channel.create_transfer(2)))
    receiver_sig = channel_manager.sign_close(sender, channel.block, 2)
    channel.close_cooperatively(receiver_sig)
    wait_for_blocks(channel_manager.n_confirmations + 1)

    channel_manager.stop()  # don't update state from this point on
    channel_manager.join()
    state = channel_manager.state

    tx_count_before = web3.eth.getTransactionCount(receiver)
    close_open_channels(channel_manager.private_key,
                        state,
                        channel_manager.channel_manager_contract,
                        wait=lambda: wait_for_blocks(1))
    tx_count_after = web3.eth.getTransactionCount(receiver)
    assert tx_count_after == tx_count_before
    wait_for_blocks(1)
Exemplo n.º 20
0
def test_channel_opening(client: Client, web3: Web3, make_account,
                         private_keys: List[str], channel_manager_contract,
                         token_contract, mine_sync_event, wait_for_blocks,
                         use_tester, state_db_path):
    receiver1_privkey = make_account(RECEIVER_ETH_ALLOWANCE,
                                     RECEIVER_TOKEN_ALLOWANCE, private_keys[2])
    receiver2_privkey = make_account(RECEIVER_ETH_ALLOWANCE,
                                     RECEIVER_TOKEN_ALLOWANCE, private_keys[3])
    receiver_address = privkey_to_addr(receiver1_privkey)
    # make sure channel_manager1 is terminated properly, otherwise Blockchain will be running
    #  in the background, ruining other tests' results
    channel_manager1 = ChannelManager(web3,
                                      channel_manager_contract,
                                      token_contract,
                                      receiver1_privkey,
                                      n_confirmations=5,
                                      state_filename=state_db_path)
    start_channel_manager(channel_manager1, use_tester, mine_sync_event)

    channel_manager2 = ChannelManager(web3,
                                      channel_manager_contract,
                                      token_contract,
                                      receiver2_privkey,
                                      n_confirmations=5,
                                      state_filename=state_db_path)
    start_channel_manager(channel_manager2, use_tester, mine_sync_event)
    channel_manager1.wait_sync()
    channel_manager2.wait_sync()
    blockchain = channel_manager1.blockchain
    channel = client.open_channel(receiver_address, 10)
    # should be in unconfirmed channels
    wait_for_blocks(1)
    gevent.sleep(blockchain.poll_interval)
    assert (channel.sender, channel.block) not in channel_manager1.channels
    assert (channel.sender,
            channel.block) in channel_manager1.unconfirmed_channels
    channel_rec = channel_manager1.unconfirmed_channels[channel.sender,
                                                        channel.block]
    assert is_same_address(channel_rec.receiver, receiver_address)
    assert is_same_address(channel_rec.sender, channel.sender)
    assert channel_rec.mtime == channel_rec.ctime

    # should be confirmed after n blocks
    wait_for_blocks(blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    assert (channel.sender, channel.block) in channel_manager1.channels
    channel_rec = channel_manager1.channels[channel.sender, channel.block]
    assert is_same_address(channel_rec.receiver, receiver_address)
    assert is_same_address(channel_rec.sender, channel.sender)
    assert channel_rec.balance == 0
    assert channel_rec.last_signature is None
    assert channel_rec.is_closed is False
    assert channel_rec.settle_timeout == -1

    # should not appear in other channel manager
    assert (channel.sender, channel.block) not in channel_manager2.channels
    assert (channel.sender,
            channel.block) not in channel_manager2.unconfirmed_channels
    channel_manager1.stop()
    channel_manager2.stop()
Exemplo n.º 21
0
def test_close_valid_close(client: Client, channel_manager: ChannelManager,
                           web3: Web3, wait_for_blocks):
    sender = client.context.address
    receiver = channel_manager.receiver

    channel = client.open_channel(receiver, 10)
    wait_for_blocks(channel_manager.n_confirmations + 1)
    channel_manager.register_payment(sender, channel.block, 2,
                                     encode_hex(channel.create_transfer(2)))
    channel.close()

    channel_manager.stop()  # don't update state from this point on
    channel_manager.join()
    state = channel_manager.state

    tx_count_before = web3.eth.getTransactionCount(receiver)
    close_open_channels(channel_manager.private_key,
                        state,
                        channel_manager.channel_manager_contract,
                        wait=lambda: wait_for_blocks(1))
    tx_count_after = web3.eth.getTransactionCount(receiver)
    assert tx_count_after == tx_count_before + 1

    with pytest.raises((BadFunctionCallOutput, TransactionFailed)):
        channel_id = (channel.sender, channel.receiver, channel.block)
        channel_manager.channel_manager_contract.call().getChannelInfo(
            *channel_id)
    wait_for_blocks(1)
Exemplo n.º 22
0
def test_open_channel_insufficient_tokens(client: Client, web3: Web3, receiver_address: str):
    balance_of = client.context.token.call().balanceOf(client.context.address)
    tx_count_pre = web3.eth.getTransactionCount(client.context.address)
    channel = client.open_channel(receiver_address, balance_of + 1)
    tx_count_post = web3.eth.getTransactionCount(client.context.address)
    assert channel is None
    assert tx_count_post == tx_count_pre
Exemplo n.º 23
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')
Exemplo n.º 24
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}
Exemplo n.º 25
0
def run(key_path, key_password_path, resource):
    # create the client
    with Client(key_path=key_path, key_password_path=key_password_path) as client:
        m2mclient = DefaultHTTPClient(
            client,
            'localhost',
            5000
        )

        # Get the resource. If payment is required, client will attempt to create
        # a channel or will use existing one.
        status, headers, body = m2mclient.run(resource)
        if status == requests.codes.OK:
            if re.match('^text\/', headers['Content-Type']):
                logging.info("got the resource %s type=%s\n%s" % (
                    resource,
                    headers.get('Content-Type', '???'),
                    body))
            else:
                logging.info("got the resource %s type=%s" % (
                    resource,
                    headers.get('Content-Type', '???')))
        else:
            logging.error("error getting the resource. code=%d body=%s" %
                          (status, body.decode().strip()))
Exemplo n.º 26
0
def init(http_client: HTTPClient = None,
         client: Client = None,
         privkey: str = None,
         key_path: str = None,
         key_password_path: str = None,
         channel_manager_address: str = CHANNEL_MANAGER_ADDRESS,
         web3: Web3 = None,
         retry_interval: float = 5,
         initial_deposit: Callable[[int], int] = lambda price: 10 * price,
         topup_deposit: Callable[[int], int] = lambda price: 5 * price):
    """
    TODO: document which of these arguments are actually needed in different use cases.
    """
    global _http_client

    if http_client is None:
        if client is None:
            client = Client(private_key=privkey,
                            key_path=key_path,
                            key_password_path=key_password_path,
                            channel_manager_address=channel_manager_address,
                            web3=web3)
        _http_client = DefaultHTTPClient(client=client,
                                         retry_interval=retry_interval,
                                         initial_deposit=initial_deposit,
                                         topup_deposit=topup_deposit)
    else:
        _http_client = http_client
Exemplo n.º 27
0
def openChannel():
    global channel_object
    with Client(config.privkey) as client:
        channel_object = client.get_suitable_channel(
            config.receiver, int(utils.convert_to_utf(request.get_data())))
        if not channel_object:
            return json.dumps(utils.error)
        return json.dumps(utils.ok)
Exemplo n.º 28
0
def confirmed_open_channel(channel_manager: ChannelManager, client: Client,
                           receiver_address: str, wait_for_blocks):
    channel = client.open_channel(receiver_address, 10)
    wait_for_blocks(channel_manager.n_confirmations + 1)
    gevent.sleep(channel_manager.blockchain.poll_interval)
    assert (channel.sender, channel.block) in channel_manager.channels

    return channel
Exemplo n.º 29
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'
    }]
Exemplo n.º 30
0
def test_topup_channel_insufficient_tokens(client: Client, web3: Web3,
                                           receiver_address: str):
    balance_of = client.token_proxy.contract.call().balanceOf(client.account)
    channel = client.open_channel(receiver_address, 1)

    tx_count_pre = web3.eth.getTransactionCount(client.account)
    assert channel.topup(balance_of) is None
    tx_count_post = web3.eth.getTransactionCount(client.account)
    assert tx_count_post == tx_count_pre
Exemplo n.º 31
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
Exemplo n.º 33
0
def close_all_channels_cooperatively(client: Client,
                                     private_keys: List[str],
                                     contract_address: str,
                                     balance: int = None):
    addresses_to_keys = {
        to_checksum_address(privkey_to_addr(private_key)): private_key
        for private_key in private_keys
    }
    client.sync_channels()
    closable_channels = [
        c for c in client.channels if c.state != Channel.State.closed
    ]
    log.info('Closing {} channels.'.format(len(closable_channels)))
    for channel in closable_channels:
        private_key = addresses_to_keys.get(
            to_checksum_address(channel.receiver))
        if private_key is not None:
            close_channel_cooperatively(channel, private_key, contract_address,
                                        balance)
Exemplo n.º 34
0
def confirmed_open_channel(
        channel_manager: ChannelManager,
        client: Client,
        receiver_address: str,
        wait_for_blocks
):
    channel = client.open_channel(receiver_address, 10)
    wait_for_blocks(channel_manager.n_confirmations + 1)
    gevent.sleep(channel_manager.blockchain.poll_interval)
    assert (channel.sender, channel.block) in channel_manager.channels

    return channel
Exemplo n.º 35
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'
Exemplo n.º 36
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
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
Exemplo n.º 38
0
def test_client(client: Client, receiver_address):
    """test if contract calls go through"""

    c = client.open_channel(receiver_address, 10)
    assert c is not None

    sig = c.create_transfer(5)
    assert sig is not None

    ev = c.topup(10)
    assert ev is not None
    assert c.deposit == 20

    ev = c.close()
    assert ev is not None
Exemplo n.º 39
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)
Exemplo n.º 40
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
Exemplo n.º 41
0
def test_unconfirmed_topup(
        channel_manager: ChannelManager,
        client: Client,
        receiver_address: str,
        wait_for_blocks
):
    blockchain = channel_manager.blockchain
    channel_manager.wait_sync()
    channel = client.open_channel(receiver_address, 10)
    wait_for_blocks(1)
    gevent.sleep(blockchain.poll_interval)
    assert (channel.sender, channel.block) in channel_manager.unconfirmed_channels
    channel.topup(5)
    wait_for_blocks(channel_manager.blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    assert (channel.sender, channel.block) in channel_manager.channels
    channel_rec = channel_manager.channels[channel.sender, channel.block]
    assert channel_rec.deposit == 15
Exemplo n.º 42
0
def test_close_unconfirmed_event(
        channel_manager: ChannelManager,
        client: Client,
        receiver_address: str,
        wait_for_blocks
):
    channel_manager.wait_sync()
    blockchain = channel_manager.blockchain
    # if unconfirmed channel is closed it should simply be forgotten
    channel = client.open_channel(receiver_address, 10)
    wait_for_blocks(1)
    gevent.sleep(blockchain.poll_interval)
    assert (channel.sender, channel.block) in channel_manager.unconfirmed_channels
    assert (channel.sender, channel.block) not in channel_manager.channels
    channel.close()
    wait_for_blocks(channel_manager.blockchain.n_confirmations)  # opening confirmed
    gevent.sleep(blockchain.poll_interval)
    assert (channel.sender, channel.block) not in channel_manager.unconfirmed_channels
    assert (channel.sender, channel.block) in channel_manager.channels
    wait_for_blocks(1)  # closing confirmed
    gevent.sleep(blockchain.poll_interval)
    assert (channel.sender, channel.block) not in channel_manager.unconfirmed_channels
    assert (channel.sender, channel.block) in channel_manager.channels
Exemplo n.º 43
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'
Exemplo n.º 44
0
def test_different_receivers(
        web3: Web3,
        make_account,
        private_keys: List[str],
        channel_manager_contract: Contract,
        token_contract: Contract,
        mine_sync_event,
        client: Client,
        sender_address: str,
        wait_for_blocks,
        use_tester: bool,
        state_db_path: str
):
    if not use_tester:
        pytest.skip('This test takes several hours on real blockchains.')

    receiver1_privkey = make_account(
        RECEIVER_ETH_ALLOWANCE,
        RECEIVER_TOKEN_ALLOWANCE,
        private_keys[2]
    )
    receiver2_privkey = make_account(
        RECEIVER_ETH_ALLOWANCE,
        RECEIVER_TOKEN_ALLOWANCE,
        private_keys[3]
    )
    receiver1_address = privkey_to_addr(receiver1_privkey)
    channel_manager1 = ChannelManager(
        web3,
        channel_manager_contract,
        token_contract,
        receiver1_privkey,
        n_confirmations=5,
        state_filename=state_db_path
    )
    start_channel_manager(channel_manager1, use_tester, mine_sync_event)

    channel_manager2 = ChannelManager(
        web3,
        channel_manager_contract,
        token_contract,
        receiver2_privkey,
        n_confirmations=5,
        state_filename=state_db_path
    )
    start_channel_manager(channel_manager2, use_tester, mine_sync_event)
    channel_manager1.wait_sync()
    channel_manager2.wait_sync()
    blockchain = channel_manager1.blockchain

    assert channel_manager2.blockchain.n_confirmations == blockchain.n_confirmations
    assert channel_manager2.blockchain.poll_interval == blockchain.poll_interval

    # unconfirmed open
    channel = client.open_channel(receiver1_address, 10)
    wait_for_blocks(1)
    gevent.sleep(blockchain.poll_interval)

    assert (sender_address, channel.block) in channel_manager1.unconfirmed_channels
    assert (sender_address, channel.block) not in channel_manager2.unconfirmed_channels

    # confirmed open
    wait_for_blocks(blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    assert (sender_address, channel.block) in channel_manager1.channels
    assert (sender_address, channel.block) not in channel_manager2.channels

    # unconfirmed topup
    channel.topup(5)
    wait_for_blocks(1)
    gevent.sleep(blockchain.poll_interval)
    channel_rec = channel_manager1.channels[sender_address, channel.block]
    assert len(channel_rec.unconfirmed_topups) == 1
    assert channel_rec.deposit == 10

    # confirmed topup
    wait_for_blocks(blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    channel_rec = channel_manager1.channels[sender_address, channel.block]
    assert len(channel_rec.unconfirmed_topups) == 0
    assert channel_rec.deposit == 15

    # closing
    channel.close()
    wait_for_blocks(blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    channel_rec = channel_manager1.channels[sender_address, channel.block]
    assert channel_rec.is_closed is True

    # settlement
    block_before = web3.eth.blockNumber
    wait_for_blocks(channel_rec.settle_timeout - block_before)
    channel.settle()
    wait_for_blocks(blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    assert (sender_address, channel.block) not in channel_manager1.channels
    channel_manager1.stop()
    channel_manager2.stop()
Exemplo n.º 45
0
def test_channel_opening(
        client: Client,
        web3: Web3,
        make_account,
        private_keys: List[str],
        channel_manager_contract,
        token_contract,
        mine_sync_event,
        wait_for_blocks,
        use_tester,
        state_db_path
):
    receiver1_privkey = make_account(
        RECEIVER_ETH_ALLOWANCE,
        RECEIVER_TOKEN_ALLOWANCE,
        private_keys[2]
    )
    receiver2_privkey = make_account(
        RECEIVER_ETH_ALLOWANCE,
        RECEIVER_TOKEN_ALLOWANCE,
        private_keys[3]
    )
    receiver_address = privkey_to_addr(receiver1_privkey)
    # make sure channel_manager1 is terminated properly, otherwise Blockchain will be running
    #  in the background, ruining other tests' results
    channel_manager1 = ChannelManager(
        web3,
        channel_manager_contract,
        token_contract,
        receiver1_privkey,
        n_confirmations=5,
        state_filename=state_db_path
    )
    start_channel_manager(channel_manager1, use_tester, mine_sync_event)

    channel_manager2 = ChannelManager(
        web3,
        channel_manager_contract,
        token_contract,
        receiver2_privkey,
        n_confirmations=5,
        state_filename=state_db_path
    )
    start_channel_manager(channel_manager2, use_tester, mine_sync_event)
    channel_manager1.wait_sync()
    channel_manager2.wait_sync()
    blockchain = channel_manager1.blockchain
    channel = client.open_channel(receiver_address, 10)
    # should be in unconfirmed channels
    wait_for_blocks(1)
    gevent.sleep(blockchain.poll_interval)
    assert (channel.sender, channel.block) not in channel_manager1.channels
    assert (channel.sender, channel.block) in channel_manager1.unconfirmed_channels
    channel_rec = channel_manager1.unconfirmed_channels[channel.sender, channel.block]
    assert is_same_address(channel_rec.receiver, receiver_address)
    assert is_same_address(channel_rec.sender, channel.sender)
    assert channel_rec.mtime == channel_rec.ctime

    # should be confirmed after n blocks
    wait_for_blocks(blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    assert (channel.sender, channel.block) in channel_manager1.channels
    channel_rec = channel_manager1.channels[channel.sender, channel.block]
    assert is_same_address(channel_rec.receiver, receiver_address)
    assert is_same_address(channel_rec.sender, channel.sender)
    assert channel_rec.balance == 0
    assert channel_rec.last_signature is None
    assert channel_rec.is_closed is False
    assert channel_rec.settle_timeout == -1

    # should not appear in other channel manager
    assert (channel.sender, channel.block) not in channel_manager2.channels
    assert (channel.sender, channel.block) not in channel_manager2.unconfirmed_channels
    channel_manager1.stop()
    channel_manager2.stop()