コード例 #1
0
 def from_dict(cls, data: Dict[str,
                               Any]) -> "ContractReceiveChannelBatchUnlock":
     return cls(
         transaction_hash=deserialize_transactionhash(
             data["transaction_hash"]),
         canonical_identifier=CanonicalIdentifier.from_dict(
             data["canonical_identifier"]),
         participant=to_canonical_address(data["participant"]),
         partner=to_canonical_address(data["partner"]),
         locksroot=deserialize_locksroot(data["locksroot"]),
         unlocked_amount=TokenAmount(int(data["unlocked_amount"])),
         returned_tokens=TokenAmount(int(data["returned_tokens"])),
         block_number=BlockNumber(int(data["block_number"])),
         block_hash=deserialize_blockhash(data["block_hash"]),
     )
コード例 #2
0
ファイル: test_startup.py プロジェクト: sekmet/raiden
def test_setup_proxies_no_service_registry_but_pfs() -> None:
    """
    Test that if no service registry is provided but a manual pfs address is given then startup
    still works

    Regression test for https://github.com/raiden-network/raiden/issues/3740
    """
    chain_id = ChainID(5)
    config = RaidenConfig(
        chain_id=chain_id,
        environment_type=Environment.DEVELOPMENT,
        services=ServiceConfig(
            pathfinding_max_fee=TokenAmount(100),
            pathfinding_iou_timeout=BlockTimeout(500),
            pathfinding_max_paths=5,
        ),
    )
    config.transport.available_servers = ["http://matrix.example.com"]
    contracts = load_deployed_contracts_data(config, chain_id)
    proxy_manager = MockProxyManager(node_address=make_address())

    PFS_INFO = PFSInfo(
        url="my-pfs",
        price=TokenAmount(12),
        chain_id=ChainID(5),
        token_network_registry_address=TokenNetworkRegistryAddress(
            to_canonical_address(contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]["address"])
        ),
        user_deposit_address=user_deposit_address_test_default,
        confirmed_block_number=BlockNumber(1),
        payment_address=pfs_payment_address_default,
        message="This is your favorite pathfinding service",
        operator="John Doe",
        version="0.0.3",
        matrix_server="http://matrix.example.com",
        matrix_room_id="!room-id:matrix.example.com",
    )
    deployed_addresses = load_deployment_addresses_from_contracts(contracts)
    with patch.object(pathfinding, "get_pfs_info", return_value=PFS_INFO):
        services_bundle = services_bundle_from_contracts_deployment(
            config=config,
            proxy_manager=proxy_manager,  # type: ignore
            deployed_addresses=deployed_addresses,
            routing_mode=RoutingMode.PFS,
            pathfinding_service_address="my-pfs",
            enable_monitoring=True,
        )
    assert services_bundle
コード例 #3
0
def test_monitor_new_balance_proof_event_handler_sets_update_status(
    context: Context, ):
    context = setup_state_with_closed_channel(context)

    new_balance_event = ReceiveMonitoringNewBalanceProofEvent(
        token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS,
        channel_identifier=DEFAULT_CHANNEL_IDENTIFIER,
        reward_amount=TokenAmount(1),
        nonce=Nonce(2),
        ms_address=Address('C'),
        raiden_node_address=DEFAULT_PARTICIPANT2,
        block_number=BlockNumber(23),
    )

    channel = context.db.get_channel(new_balance_event.token_network_address,
                                     new_balance_event.channel_identifier)
    assert channel
    assert channel.update_status is None

    monitor_new_balance_proof_event_handler(new_balance_event, context)

    assert context.db.channel_count() == 1
    channel = context.db.get_channel(new_balance_event.token_network_address,
                                     new_balance_event.channel_identifier)
    assert channel
    assert channel.update_status is not None
    assert channel.update_status.nonce == 2
    assert channel.update_status.update_sender_address == 'C'

    new_balance_event2 = ReceiveMonitoringNewBalanceProofEvent(
        token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS,
        channel_identifier=DEFAULT_CHANNEL_IDENTIFIER,
        reward_amount=TokenAmount(1),
        nonce=Nonce(5),
        ms_address=Address('D'),
        raiden_node_address=DEFAULT_PARTICIPANT2,
        block_number=BlockNumber(23),
    )

    monitor_new_balance_proof_event_handler(new_balance_event2, context)

    assert context.db.channel_count() == 1
    channel = context.db.get_channel(new_balance_event.token_network_address,
                                     new_balance_event.channel_identifier)
    assert channel
    assert channel.update_status is not None
    assert channel.update_status.nonce == 5
    assert channel.update_status.update_sender_address == 'D'
コード例 #4
0
ファイル: test_pathfinding.py プロジェクト: pinklite/raiden
def test_check_pfs_for_production(service_registry_address, private_keys, web3,
                                  contract_manager) -> None:
    chain_id = ChainID(int(web3.net.version))
    service_registry, _ = deploy_service_registry_and_set_urls(
        private_keys=private_keys,
        web3=web3,
        contract_manager=contract_manager,
        service_registry_address=service_registry_address,
    )

    # Configuring an address that doesn't match the registered url should error
    pfs_info = PFSInfo(
        url="http://ourgivenaddress",
        price=TokenAmount(0),
        chain_id=chain_id,
        token_network_registry_address=
        token_network_registry_address_test_default,
        payment_address=privatekey_to_address(private_keys[0]),
        message="",
        operator="",
        version="",
        user_deposit_address=privatekey_to_address(private_keys[1]),
        confirmed_block_number=BlockNumber(10),
        matrix_server="http://matrix.example.com",
    )
    with pytest.raises(RaidenError):
        check_pfs_for_production(service_registry=service_registry,
                                 pfs_info=pfs_info)

    # Configuring an pfs payment address that isn't registered should error
    pfs_info = PFSInfo(
        url="http://foo",
        price=TokenAmount(0),
        chain_id=chain_id,
        token_network_registry_address=
        token_network_registry_address_test_default,
        payment_address=to_canonical_address(
            "0x2222222222222222222222222222222222222221"),
        message="",
        operator="",
        version="",
        user_deposit_address=privatekey_to_address(private_keys[1]),
        confirmed_block_number=BlockNumber(10),
        matrix_server="http://matrix.example.com",
    )
    with pytest.raises(RaidenError):
        check_pfs_for_production(service_registry=service_registry,
                                 pfs_info=pfs_info)
コード例 #5
0
ファイル: test_graphs.py プロジェクト: BOR4/raiden-services
def test_routing_benchmark(token_network_model: TokenNetwork,
                           populate_token_network_random: None):
    value = TokenAmount(100)
    G = token_network_model.G
    times = []
    start = time.time()
    for _ in range(100):
        tic = time.time()
        source, target = random.sample(G.nodes, 2)
        paths = token_network_model.get_paths(source,
                                              target,
                                              value=value,
                                              max_paths=5,
                                              bias=0.0)
        toc = time.time()
        times.append(toc - tic)
    end = time.time()
    for path_object in paths:
        path = path_object["path"]
        fees = path_object["estimated_fee"]
        for node1, node2 in zip(path[:-1], path[1:]):
            view: ChannelView = G[node1][node2]["view"]
            print("fee = ", view.absolute_fee, "capacity = ", view.capacity)
        print("fee sum = ", fees)
    print("Paths: ", paths)
    print("Mean runtime: ", sum(times) / len(times))
    print("Min runtime: ", min(times))
    print("Max runtime: ", max(times))
    print("Total runtime: ", end - start)
コード例 #6
0
ファイル: test_graphs.py プロジェクト: BOR4/raiden-services
def test_edge_weight(addresses):
    channel_id = ChannelID(1)
    participant1 = addresses[0]
    participant2 = addresses[1]
    settle_timeout = 15
    view = ChannelView(TokenNetworkAddress("0x11"), channel_id, participant1,
                       participant2, settle_timeout)
    amount = TokenAmount(int(1e18))  # one RDN

    # no penalty
    assert TokenNetwork.edge_weight(dict(),
                                    dict(view=view),
                                    amount=amount,
                                    fee_penalty=0) == 1

    # channel already used in a previous route
    assert (TokenNetwork.edge_weight({channel_id: 2},
                                     dict(view=view),
                                     amount=amount,
                                     fee_penalty=0) == 3)

    # absolute fee
    view.absolute_fee = FeeAmount(int(0.03e18))
    assert TokenNetwork.edge_weight(dict(),
                                    dict(view=view),
                                    amount=amount,
                                    fee_penalty=100) == 4

    # relative fee
    view.absolute_fee = FeeAmount(0)
    view.relative_fee = 0.01
    assert TokenNetwork.edge_weight(dict(),
                                    dict(view=view),
                                    amount=amount,
                                    fee_penalty=100) == 2
コード例 #7
0
ファイル: token.py プロジェクト: ezdac/scenario-player
def userdeposit_maybe_increase_allowance(
    token_proxy: CustomToken,
    userdeposit_proxy: UserDeposit,
    orchestrator_address: Address,
    minimum_allowance: TokenAmount,
    maximum_allowance: TokenAmount,
) -> None:
    """Set the allowance of the corresponding smart contract of
    `userdeposit_proxy` to `required_allowance`.
    """
    given_token_address = token_proxy.address
    user_deposit_token_address = userdeposit_proxy.token_address("latest")

    if user_deposit_token_address != given_token_address:
        raise ValueError(
            f"The allowance for the user deposit contract must be increase on the "
            f"corresponding token. Given token: {to_hex(given_token_address)} "
            f"user deposit token: {to_hex(user_deposit_token_address)}.")

    current_allowance = token_proxy.allowance(
        orchestrator_address, Address(userdeposit_proxy.address), "latest")

    if minimum_allowance > current_allowance:
        # For the RDN token:
        #
        #     To change the approve amount you first have to reduce the addresses`
        #     allowance to zero by calling `approve(_spender, 0)` if it is not
        #     already 0 to mitigate the race condition described here:
        #     https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
        #
        token_proxy.approve(Address(userdeposit_proxy.address), TokenAmount(0))
        token_proxy.approve(Address(userdeposit_proxy.address),
                            maximum_allowance)
コード例 #8
0
def handle_unlock(
    target_state: TargetTransferState,
    state_change: ReceiveUnlock,
    channel_state: NettingChannelState,
) -> TransitionResult[Optional[TargetTransferState]]:
    """ Handles a ReceiveUnlock state change. """
    balance_proof_sender = state_change.balance_proof.sender

    is_valid, events, _ = channel.handle_unlock(channel_state, state_change)
    next_target_state: Optional[TargetTransferState] = target_state

    if is_valid:
        transfer = target_state.transfer
        payment_received_success = EventPaymentReceivedSuccess(
            token_network_registry_address=channel_state.token_network_registry_address,
            token_network_address=channel_state.token_network_address,
            identifier=transfer.payment_identifier,
            amount=TokenAmount(transfer.lock.amount),
            initiator=transfer.initiator,
        )

        unlock_success = EventUnlockClaimSuccess(
            transfer.payment_identifier, transfer.lock.secrethash
        )

        send_processed = SendProcessed(
            recipient=balance_proof_sender,
            message_identifier=state_change.message_identifier,
            canonical_identifier=CANONICAL_IDENTIFIER_UNORDERED_QUEUE,
        )

        events.extend([payment_received_success, unlock_success, send_processed])
        next_target_state = None

    return TransitionResult(next_target_state, events)
コード例 #9
0
def test_target_task_view():
    """Same as above for target tasks."""
    secret = factories.make_secret()
    transfer = factories.create(
        factories.LockedTransferSignedStateProperties(secret=secret))
    secrethash = transfer.lock.secrethash
    mediator = factories.make_address()
    mediator_channel = factories.create(
        factories.NettingChannelStateProperties(
            partner_state=factories.NettingChannelEndStateProperties(
                address=mediator, balance=TokenAmount(100))))
    transfer_state = TargetTransferState(
        from_hop=HopState(
            channel_identifier=mediator_channel.canonical_identifier.
            channel_identifier,
            node_address=mediator,
        ),
        transfer=transfer,
        secret=secret,
    )
    task = TargetTask(
        canonical_identifier=mediator_channel.canonical_identifier,
        target_state=transfer_state)
    payment_mapping = {secrethash: cast(TransferTask, task)}

    view = transfer_tasks_view(payment_mapping)

    assert len(view) == 1
    pending_transfer = view[0]
    assert pending_transfer.get("role") == "target"
    # pylint: disable=no-member
    assert pending_transfer.get("locked_amount") == str(
        transfer.balance_proof.locked_amount)
    assert pending_transfer.get("payment_identifier") == str(
        transfer.payment_identifier)
コード例 #10
0
def calc_claim_cost_rdn(web3: Web3, rdn_per_eth: float) -> TokenAmount:
    web3.eth.setGasPriceStrategy(rpc_gas_price_strategy)
    claim_cost_gas = gas_measurements()["OneToN.claim"]
    claim_cost_eth = claim_cost_gas * web3.eth.generateGasPrice(
    ) * GAS_COST_SAFETY_MARGIN
    claim_cost_rdn = TokenAmount(int(claim_cost_eth / rdn_per_eth))
    return claim_cost_rdn
コード例 #11
0
 def test_payment(iou, service_fee=TokenAmount(1)):
     process_payment(
         iou=iou,
         pathfinding_service=pfs,
         service_fee=service_fee,
         one_to_n_address=to_canonical_address(one_to_n_contract.address),
     )
コード例 #12
0
def test_pfs_rejects_capacity_update_with_impossible_other_capacity(
    pathfinding_service_web3_mock: PathfindingService,
):
    setup_channel_with_deposits(pathfinding_service_web3_mock)

    message = get_updatepfs_message(
        updating_participant=PRIVATE_KEY_1_ADDRESS,
        other_participant=PRIVATE_KEY_2_ADDRESS,
        other_capacity=TokenAmount(UINT256_MAX),
        privkey_signer=PRIVATE_KEY_1,
    )
    message.other_capacity = TokenAmount(UINT256_MAX + 1)

    with pytest.raises(InvalidCapacityUpdate) as exinfo:
        pathfinding_service_web3_mock.on_capacity_update(message)
    assert "with impossible other_capacity" in str(exinfo.value)
コード例 #13
0
def test_action_monitoring_rescheduling_when_user_lacks_funds(context: Context):
    reward_amount = TokenAmount(10)
    context = setup_state_with_closed_channel(context)
    context.db.upsert_monitor_request(
        create_signed_monitor_request(nonce=Nonce(6), reward_amount=reward_amount)
    )

    event = ActionMonitoringTriggeredEvent(
        token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS,
        channel_identifier=DEFAULT_CHANNEL_IDENTIFIER,
        non_closing_participant=DEFAULT_PARTICIPANT2,
    )
    scheduled_events_before = context.db.get_scheduled_events(max_trigger_block=BlockNumber(10000))

    # Try to call monitor when the user has insufficient funds
    with patch("monitoring_service.handlers.get_pessimistic_udc_balance", Mock(return_value=0)):
        action_monitoring_triggered_event_handler(event, context)
    assert not context.monitoring_service_contract.functions.monitor.called

    # Now the event must have been rescheduled
    # TODO: check that the event is rescheduled to trigger at the right block
    scheduled_events_after = context.db.get_scheduled_events(max_trigger_block=BlockNumber(10000))
    new_events = set(scheduled_events_after) - set(scheduled_events_before)
    assert len(new_events) == 1
    assert new_events.pop().event == event

    # With sufficient funds it must succeed
    with patch(
        "monitoring_service.handlers.get_pessimistic_udc_balance",
        Mock(return_value=reward_amount * UDC_SECURITY_MARGIN_FACTOR_MS),
    ):
        action_monitoring_triggered_event_handler(event, context)
    assert context.monitoring_service_contract.functions.monitor.called
コード例 #14
0
 def from_dict(cls, data: Dict[str, Any]) -> 'ContractReceiveChannelBatchUnlock':
     return cls(
         transaction_hash=deserialize_transactionhash(data['transaction_hash']),
         canonical_identifier=CanonicalIdentifier(
             chain_identifier=CHAIN_ID_UNSPECIFIED,
             token_network_address=to_canonical_address(data['token_network_identifier']),
             channel_identifier=CHANNEL_ID_UNSPECIFIED,
         ),
         participant=to_canonical_address(data['participant']),
         partner=to_canonical_address(data['partner']),
         locksroot=deserialize_locksroot(data['locksroot']),
         unlocked_amount=TokenAmount(int(data['unlocked_amount'])),
         returned_tokens=TokenAmount(int(data['returned_tokens'])),
         block_number=BlockNumber(int(data['block_number'])),
         block_hash=deserialize_blockhash(data['block_hash']),
     )
コード例 #15
0
def test_receive_lockedtransfer_invalidnonce(raiden_network, number_of_nodes,
                                             deposit, token_addresses,
                                             reveal_timeout, network_wait):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(app0), app0.raiden.default_registry.address,
        token_address)
    assert token_network_address
    channel0 = get_channelstate(app0, app1, token_network_address)

    amount = 10
    payment_identifier = PaymentID(1)
    secrethash = transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token_address,
        amount=PaymentAmount(10),
        identifier=payment_identifier,
        timeout=network_wait * number_of_nodes,
    )

    repeated_nonce = Nonce(1)
    expiration = reveal_timeout * 2
    mediated_transfer_message = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=make_message_identifier(),
        payment_identifier=payment_identifier,
        nonce=repeated_nonce,
        token_network_address=token_network_address,
        token=token_address,
        channel_identifier=channel0.identifier,
        transferred_amount=TokenAmount(amount),
        locked_amount=LockedAmount(amount),
        recipient=app1.raiden.address,
        locksroot=make_locksroot(),
        lock=Lock(amount=PaymentWithFeeAmount(amount),
                  expiration=expiration,
                  secrethash=UNIT_SECRETHASH),
        target=app2.raiden.address,
        initiator=app0.raiden.address,
        signature=EMPTY_SIGNATURE,
        metadata=Metadata(routes=[
            RouteMetadata(route=[app1.raiden.address, app2.raiden.address])
        ]),
    )

    sign_and_inject(mediated_transfer_message, app0.raiden.signer, app1)

    with block_timeout_for_transfer_by_secrethash(app1.raiden, secrethash):
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app0,
            deposit - amount,
            [],
            app1,
            deposit + amount,
            [],
        )
コード例 #16
0
def test_action_claim_reward_triggered_event_handler_without_update_state_doesnt_trigger_claim_call(  # noqa
        context: Context, ):
    """ Tests that `claimReward` is called when the ActionMonitoringTriggeredEvent is triggered and
    user has sufficient balance in user deposit contract
    """
    context = setup_state_with_closed_channel(context)

    context.db.upsert_monitor_request(
        get_signed_monitor_request(nonce=Nonce(6),
                                   reward_amount=TokenAmount(0)))

    trigger_event = ActionClaimRewardTriggeredEvent(
        token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS,
        channel_identifier=DEFAULT_CHANNEL_IDENTIFIER,
        non_closing_participant=DEFAULT_PARTICIPANT2,
    )

    channel = context.db.get_channel(trigger_event.token_network_address,
                                     trigger_event.channel_identifier)
    assert channel
    assert channel.claim_tx_hash is None

    # Set update state
    channel.update_status = OnChainUpdateStatus(
        update_sender_address=Address('0x' + '1' * 40), nonce=Nonce(6))
    context.db.upsert_channel(channel)

    action_claim_reward_triggered_event_handler(trigger_event, context)

    # check that the monitor call has been done
    assert context.monitoring_service_contract.functions.claimReward.called is False
コード例 #17
0
    def withdraw(self, amount: TokenAmount, given_block_identifier: BlockIdentifier) -> None:
        """ Withdraw tokens from UDC, requires a mature withdraw plan"""

        token_address = self.token_address(given_block_identifier)
        token = self.proxy_manager.token(
            token_address=token_address, block_identifier=given_block_identifier
        )

        self._withdraw_preconditions(
            amount_to_withdraw=amount, given_block_identifier=given_block_identifier
        )

        previous_token_balance = TokenAmount(
            token.balance_of(self.node_address, given_block_identifier)
        )

        # Simplify our lives by disallowing concurrent plan_withdraw / withdraw calls
        with self._withdraw_lock:
            estimated_transaction = self.client.estimate_gas(self.proxy, "withdraw", {}, amount)

            transaction_sent = None
            if estimated_transaction is not None:
                transaction_sent = self.client.transact(estimated_transaction)
            self._withdraw_check_result(
                transaction_sent=transaction_sent,
                amount_to_withdraw=amount,
                token=token,
                previous_token_balance=previous_token_balance,
            )
コード例 #18
0
def test_action_monitoring_triggered_event_handler_with_insufficient_reward_amount_does_not_trigger_monitor_call(  # noqa
        context: Context, ):
    """ Tests that `monitor` is not called when the ActionMonitoringTriggeredEvent is triggered but
    the monitor request shows an insufficient reward amount
    """
    context = setup_state_with_closed_channel(context)

    context.db.upsert_monitor_request(
        get_signed_monitor_request(nonce=Nonce(6),
                                   reward_amount=TokenAmount(0)))

    trigger_event = ActionMonitoringTriggeredEvent(
        token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS,
        channel_identifier=DEFAULT_CHANNEL_IDENTIFIER,
        non_closing_participant=DEFAULT_PARTICIPANT2,
    )

    channel = context.db.get_channel(trigger_event.token_network_address,
                                     trigger_event.channel_identifier)
    assert channel
    assert channel.closing_tx_hash is None

    context.user_deposit_contract.functions.effectiveBalance(
        DEFAULT_PARTICIPANT2).call.return_value = 21
    action_monitoring_triggered_event_handler(trigger_event, context)

    # check that the monitor call has been done
    assert context.monitoring_service_contract.functions.monitor.called is False
コード例 #19
0
def test_action_monitoring_triggered_event_handler_without_sufficient_balance_doesnt_trigger_monitor_call(  # noqa
        context: Context, ):
    """ Tests that `monitor` is not called when user has insufficient balance in user deposit contract

    Also a test for https://github.com/raiden-network/raiden-services/issues/29 , as the MR
    is sent after the channel has been closed.
    """
    context = setup_state_with_closed_channel(context)

    context.db.upsert_monitor_request(
        get_signed_monitor_request(nonce=Nonce(6),
                                   reward_amount=TokenAmount(10)))

    trigger_event = ActionMonitoringTriggeredEvent(
        token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS,
        channel_identifier=DEFAULT_CHANNEL_IDENTIFIER,
        non_closing_participant=DEFAULT_PARTICIPANT2,
    )

    channel = context.db.get_channel(trigger_event.token_network_address,
                                     trigger_event.channel_identifier)
    assert channel
    assert channel.closing_tx_hash is None

    context.user_deposit_contract.functions.effectiveBalance(
        DEFAULT_PARTICIPANT2).call.return_value = 0
    action_monitoring_triggered_event_handler(trigger_event, context)

    # check that the monitor call has been done
    assert context.monitoring_service_contract.functions.monitor.called is False
コード例 #20
0
    def _funds_remaining(self) -> TokenAmount:
        """The remaining funds after subtracting the already deposited amounts.

        Note:
            - This attribute must be accessed with the lock held.
        """
        if self.funds > 0:
            token = self.raiden.proxy_manager.token(self.token_address)
            token_balance = token.balance_of(self.raiden.address)
            sum_deposits = views.get_our_deposits_for_token_network(
                views.state_from_raiden(self.raiden), self.registry_address, self.token_address
            )

            return TokenAmount(min(self.funds - sum_deposits, token_balance))

        return TokenAmount(0)
コード例 #21
0
ファイル: test_payment.py プロジェクト: karlb/raiden-services
 def test_payment(iou, service_fee=TokenAmount(1)):
     process_payment(
         iou,
         pfs,
         service_fee=service_fee,
         one_to_n_address=decode_hex(one_to_n_contract.address),
     )
コード例 #22
0
ファイル: pathfinding.py プロジェクト: christianbrb/raiden
def update_iou(
    iou: IOU,
    privkey: bytes,
    added_amount: TokenAmount = ZERO_TOKENS,
    expiration_block: Optional[BlockNumber] = None,
) -> IOU:

    expected_signature = Signature(
        sign_one_to_n_iou(
            privatekey=to_hex(privkey),
            sender=to_checksum_address(iou.sender),
            receiver=to_checksum_address(iou.receiver),
            amount=iou.amount,
            expiration_block=iou.expiration_block,
            one_to_n_address=to_checksum_address(iou.one_to_n_address),
            chain_id=iou.chain_id,
        ))
    if iou.signature != expected_signature:
        raise ServiceRequestFailed(
            "Last IOU as given by the Pathfinding Service is invalid (signature does not match)"
        )

    iou.amount = TokenAmount(iou.amount + added_amount)
    if expiration_block:
        iou.expiration_block = expiration_block

    iou.sign(privkey)

    return iou
コード例 #23
0
ファイル: test_pythonapi.py プロジェクト: christianbrb/raiden
def test_create_monitoring_request(raiden_network, token_addresses):
    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    token_network_registry_address = app0.raiden.default_registry.address
    token_network_address = views.get_token_network_address_by_token_address(
        chain_state=chain_state,
        token_network_registry_address=token_network_registry_address,
        token_address=token_address,
    )
    assert token_network_address

    payment_identifier = create_default_identifier()
    transfer(
        initiator_app=app1,
        target_app=app0,
        token_address=token_address,
        amount=PaymentAmount(1),
        identifier=payment_identifier,
    )
    chain_state = views.state_from_raiden(app0.raiden)
    channel_state = views.get_channelstate_by_token_network_and_partner(
        chain_state, token_network_address, app1.raiden.address)
    assert channel_state
    balance_proof = cast(BalanceProofSignedState,
                         channel_state.partner_state.balance_proof)
    api = RaidenAPI(app0.raiden)
    request = api.create_monitoring_request(balance_proof=balance_proof,
                                            reward_amount=TokenAmount(1))
    assert request
    as_dict = DictSerializer.serialize(request)
    from_dict = DictSerializer.deserialize(as_dict)
    assert DictSerializer.serialize(from_dict) == as_dict
コード例 #24
0
def test_monitor_reward_claimed_event_handler(context: Context, log):
    metrics_state = save_metrics_state(metrics.REGISTRY)

    context = setup_state_with_closed_channel(context)

    claim_event = ReceiveMonitoringRewardClaimedEvent(
        ms_address=context.ms_state.address,
        amount=TokenAmount(1),
        reward_identifier="REWARD",
        block_number=BlockNumber(23),
    )

    monitor_reward_claim_event_handler(claim_event, context)

    assert (metrics_state.get_delta(
        "economics_reward_claims_successful_total",
        labels=metrics.Who.US.to_label_dict()) == 1.0)
    assert (metrics_state.get_delta(
        "economics_reward_claims_token_total",
        labels=metrics.Who.US.to_label_dict()) == 1.0)

    assert log.has("Successfully claimed reward")

    claim_event.ms_address = Address(bytes([3] * 20))
    monitor_reward_claim_event_handler(claim_event, context)

    assert (metrics_state.get_delta(
        "economics_reward_claims_successful_total",
        labels=metrics.Who.THEY.to_label_dict()) == 1.0)
    assert (metrics_state.get_delta(
        "economics_reward_claims_token_total",
        labels=metrics.Who.THEY.to_label_dict()) == 1.0)

    assert log.has("Another MS claimed reward")
コード例 #25
0
def test_get_ious_via_debug_endpoint(
    api_sut_with_debug: ServiceApi, api_url: str, addresses: List[Address]
):
    hex_addrs = [to_checksum_address(addr) for addr in addresses]
    iou = IOU(
        sender=addresses[0],
        receiver=addresses[4],
        amount=TokenAmount(111),
        expiration_block=BlockNumber(7619644),
        signature=Signature(
            decode_hex("118a93e9fd0a3a1c3d6edbad194b5c9d95715c754881d80e23e985793b1e13de")
        ),
        claimed=False,
        chain_id=ChainID(1),
        one_to_n_address=api_sut_with_debug.one_to_n_address,
    )
    api_sut_with_debug.pathfinding_service.database.upsert_iou(iou)

    # now there must be an iou debug endpoint for a request of a sender in the database
    url_iou_debug = api_url + f"/_debug/ious/{hex_addrs[0]}"
    response_debug = requests.get(url_iou_debug)
    assert response_debug.status_code == 200
    response_iou = response_debug.json()
    assert response_iou == {"sender": hex_addrs[0], "amount": 111, "expiration_block": 7619644}

    # but there is no iou debug endpoint for a request of a sender not in the database
    url_iou_debug = api_url + f"/_debug/ious/{hex_addrs[1]}"
    response_debug = requests.get(url_iou_debug)
    assert response_debug.status_code == 200
    ious = response_debug.json()
    assert ious == {}
コード例 #26
0
ファイル: claim_fees.py プロジェクト: BOR4/raiden-services
def main(
    private_key: str,
    state_db: str,
    web3: Web3,
    contracts: Dict[str, Contract],
    start_block: BlockNumber,
    rdn_per_eth: float,
    expires_within: BlockNumber,
) -> None:
    pfs_address = private_key_to_address(private_key)
    chain_id = ChainID(int(web3.net.version))
    database = PFSDatabase(filename=state_db,
                           chain_id=chain_id,
                           pfs_address=pfs_address)

    one_to_n_contract = contracts[CONTRACT_ONE_TO_N]

    claim_cost_eth = 90897
    claim_cost_rdn = TokenAmount(int(claim_cost_eth / rdn_per_eth))
    ious = list(
        get_claimable_ious(
            database,
            expires_before=web3.eth.blockNumber + expires_within,
            claim_cost_rdn=claim_cost_rdn,
        ))
    print(f"Found {len(ious)} claimable IOUs")
    _, failures = claim_ious(ious, claim_cost_rdn, one_to_n_contract, web3,
                             database)
    if failures:
        sys.exit(1)
コード例 #27
0
    def f():
        contract_address = get_random_address()
        channel_identifier = get_random_identifier()

        balance_hash_data = '%d' % random.randint(0, UINT64_MAX)
        additional_hash_data = '%d' % random.randint(0, UINT64_MAX)

        balance_hash = encode_hex((balance_hash_data.encode()))
        nonce = random.randint(0, UINT64_MAX)
        additional_hash = encode_hex(keccak(additional_hash_data.encode()))
        chain_id = 1

        privkey = get_random_privkey()
        privkey_non_closing = get_random_privkey()

        bp = HashedBalanceProof(  # type: ignore
            channel_identifier=channel_identifier,
            token_network_address=contract_address,
            chain_id=chain_id,
            balance_hash=balance_hash,
            nonce=nonce,
            additional_hash=additional_hash,
            priv_key=privkey,
        )
        monitor_request = UnsignedMonitorRequest.from_balance_proof(
            bp, reward_amount=TokenAmount(0)).sign(privkey_non_closing)
        return monitor_request, privkey, privkey_non_closing
コード例 #28
0
def test_update_fee(order, pathfinding_service_mock, token_network_model):
    metrics_state = save_metrics_state(metrics.REGISTRY)

    pathfinding_service_mock.database.insert(
        "token_network", dict(address=token_network_model.address))
    if order == "normal":
        setup_channel(pathfinding_service_mock, token_network_model)
        exception_expected = False
    else:
        exception_expected = True

    fee_schedule = FeeScheduleState(
        flat=FeeAmount(1),
        proportional=ProportionalFeeAmount(int(0.1e9)),
        imbalance_penalty=[(TokenAmount(0), FeeAmount(0)),
                           (TokenAmount(10), FeeAmount(10))],
    )
    fee_update = PFSFeeUpdate(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=ChainID(61),
            token_network_address=token_network_model.address,
            channel_identifier=ChannelID(1),
        ),
        updating_participant=PARTICIPANT1,
        fee_schedule=fee_schedule,
        timestamp=datetime.utcnow(),
        signature=EMPTY_SIGNATURE,
    )
    fee_update.sign(LocalSigner(PARTICIPANT1_PRIVKEY))
    pathfinding_service_mock.handle_message(fee_update)

    # Test for metrics having seen the processing of the message
    assert (metrics_state.get_delta(
        "messages_processing_duration_seconds_sum",
        labels={"message_type": "PFSFeeUpdate"},
    ) > 0.0)
    assert metrics_state.get_delta("messages_exceptions_total",
                                   labels={"message_type": "PFSFeeUpdate"
                                           }) == float(exception_expected)

    if order == "fee_update_before_channel_open":
        setup_channel(pathfinding_service_mock, token_network_model)

    cv = token_network_model.G[PARTICIPANT1][PARTICIPANT2]["view"]
    for key in ("flat", "proportional", "imbalance_penalty"):
        assert getattr(cv.fee_schedule_sender,
                       key) == getattr(fee_schedule, key)
コード例 #29
0
def test_imbalance_penalty():
    r""" Test an imbalance penalty by moving back and forth

    The imbalance fee looks like

    20 |         /
       |        /
    10 |\.     /
       |  \.  /
     0 |    \/
    ---------------
       0    50  100

    For each input, we first assume the channel is used to forward tokens to a
    payee, which moves the capacity from x1 to x2. The we assume the same
    amount is mediated in the opposite direction (moving from x2 to x1) and
    check that the calculated fee is the same as before just with the opposite
    sign.
    """
    v_schedule = FeeScheduleState(imbalance_penalty=[
        (TokenAmount(0), FeeAmount(10)),
        (TokenAmount(50), FeeAmount(0)),
        (TokenAmount(100), FeeAmount(20)),
    ])

    for x1, amount, expected_fee_payee, expected_fee_payer in [
        (0, 50, -6, 10),
        (50, 50, 12, -20),
        (0, 10, -2, 2),
        (10, 10, -2, 2),
        (0, 20, -5, 4),
        (40, 15, 0, 0),
    ]:
        x2 = x1 + amount
        assert v_schedule.fee_payee(
            balance=Balance(100 - x1), amount=PaymentWithFeeAmount(
                amount)) == FeeAmount(expected_fee_payee)
        assert v_schedule.fee_payer(
            balance=Balance(100 - x2), amount=PaymentWithFeeAmount(
                amount)) == FeeAmount(expected_fee_payer)

    with pytest.raises(UndefinedMediationFee):
        v_schedule.fee_payee(balance=Balance(0),
                             amount=PaymentWithFeeAmount(1))
    with pytest.raises(UndefinedMediationFee):
        v_schedule.fee_payer(balance=Balance(100),
                             amount=PaymentWithFeeAmount(1))
コード例 #30
0
    def _withdraw_check_result(
        self,
        transaction_sent: Optional[TransactionSent],
        amount_to_withdraw: TokenAmount,
        token: Token,
        previous_token_balance: TokenAmount,
    ) -> None:
        if transaction_sent is None:
            failed_at = self.client.get_block(BLOCK_ID_LATEST)
            failed_at_blocknumber = failed_at["number"]

            self.client.check_for_insufficient_eth(
                transaction_name="withdraw",
                transaction_executed=False,
                required_gas=self.gas_measurements["UserDeposit.withdraw"],
                block_identifier=failed_at_blocknumber,
            )
            raise RaidenRecoverableError(
                "Withdraw transaction failed to be sent for an unknown reason."
            )

        transaction_mined = self.client.poll_transaction(transaction_sent)

        if not was_transaction_successfully_mined(transaction_mined):
            failed_at_blocknumber = BlockNumber(transaction_mined.receipt["blockNumber"])

            withdraw_plan = self.get_withdraw_plan(
                withdrawer_address=self.node_address, block_identifier=failed_at_blocknumber
            )
            whole_balance = self.whole_balance(block_identifier=failed_at_blocknumber)

            if amount_to_withdraw > withdraw_plan.withdraw_amount:
                raise RaidenRecoverableError(
                    f"Couldn't withdraw {amount_to_withdraw}, "
                    f"current withdraw plan only allows for {withdraw_plan.withdraw_amount}."
                )

            if withdraw_plan.withdraw_block > failed_at_blocknumber:
                raise RaidenRecoverableError(
                    f"Couldn't withdraw at block {failed_at_blocknumber}. "
                    f"The current withdraw plan requires block number "
                    f"{withdraw_plan.withdraw_block}."
                )

            if whole_balance - amount_to_withdraw < 0:
                raise RaidenRecoverableError(
                    f"The current whole balance is {whole_balance}. "
                    f"The withdraw of {amount_to_withdraw} would have lead to an underflow."
                )

            current_token_balance = TokenAmount(
                token.balance_of(self.node_address, block_identifier=failed_at_blocknumber)
            )
            # FIXME: This seems fishy. The token balance could have an unexpected value for
            #        unrelated reasons (e.g. concurrent token transfers via transferFrom).
            if current_token_balance != previous_token_balance + amount_to_withdraw:
                raise RaidenRecoverableError("Token transfer during withdraw failed.")

            raise RaidenRecoverableError("Withdraw failed for an unknown reason.")