Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

One to N payment system for PFS #38

Closed
karlb opened this issue Jan 22, 2019 · 1 comment
Closed

One to N payment system for PFS #38

karlb opened this issue Jan 22, 2019 · 1 comment
Labels
Contracts 🛂 Requires Smart Contract changes

Comments

@karlb
Copy link
Contributor

karlb commented Jan 22, 2019

Overview

After discussing different options to pay the PFS, the currently favored approach has the following properties

  • easy to implement
  • low initial gas cost even when fees are paid to many PFSs
  • a certain risk of double spends is accepted

The concept is based on the idea to use a user's single deposit in the UDC as a security deposit for off-chain payments to all PFSs.
The client sends an IOU consisting of (sender, receiver, amount, expiration, signature) to the PFS with every path finding request. The PFS verifies the IOU and checks that amount >= prev_amount + pfs_fee. At any time, the PFS can claim the payment by submitting the IOU on-chain. Afterwards, no further IOU with the same (sender, receiver, expiration) can be claimed.

Related:

Requirements

  • low latency (<1s)
  • reliability, high probability of success (P > 0.99)
  • low cost overhead (<5% of transferred amount)
  • low fraud rate (< 3%, i.e. some fraud is tolerable)
  • can be implemented quickly

Communication between client and PFS

When requesting a route, the IOU is added as five separate arguments to the existing HTTP query params (https://raiden-network-specification.readthedocs.io/en/latest/pathfinding_service.html#arguments):

Field NameField TypeDescription
senderaddress
receiveraddress
amountuint256
expiration_blockuint256last block in which the IOU can be claimed
signaturebytesSignature over (`\x19Ethereum Signed Message:\n`, message_length, sender, receiver, amount, expiration_block) signed by sender's private key

The PFS then thoroughly checks the IOU:

  • Is the PFS the receiver
  • Did the amount increase enough to make the request profitable for the PFS (amount >= prev_amount + pfs_fee)
  • Is expiration_block far enough in the future to potentially accumulate a reasonable amount of fees and claim the payment
  • Is the IOU for (sender, receiver, expiration) still unclaimed
  • Did the client create too many small IOU instead of increasing the value of an existing one? This would make claiming the IOU unprofitable for the PFS
  • Is the signature valid
  • Is the deposit much larger than amount

If one of the conditions is not met, a corresponding error message is returned and the client can try to submit a request with a proper IOU or try a different PFS. Otherwise, the PFS returns the requested routes as described in the current spec and saves the latest IOU for this (sender, expiration_block).

Claiming the IOU

A OneToN contract (OTNC) which is trusted by the UDC accepts IOUs (see table above for parameters) and uses the UDC to transfer amount from sender to receiver. The OTNC stores a mapping hash(receiver, sender, expiration_block) => expiration_block to make sure that each IOU can only be claimed once.
To make claims more gas efficient, multiple claims can be done in a single transaction and expired claims can be removed from the storage.

Expiration

Having the field expiration_block as part of the IOU serves multiple purposes:

  • Combined with the sender and receiver fields it identifies a single payment session. Under this identifier, multiple payments are aggregated by continuously increasing the amount and only a single on-chain transaction is needed to claim the total payment sum. After claiming, the identifier is stored on-chain and used to prevent the receiver from claiming the same payments, again.
  • When old IOUs have expired (current_block > expiration_block), the sender can be sure that he won't have to pay this IOU. So after waiting for expiry, the sender knows that IOUs which have been lost for some reason (e.g. disk failure) won't be redeemed and does not have to prepare for unpredictable claims of very old IOUs.
  • Entries can be deleted from the hash(receiver, sender, expiration_block) => expiration_block mapping which is used to prevent double claims after expiry. This frees blockchain storage and thereby reduces gas costs.

Double Spending

Since the same deposit is used for payments to multiple parties, it is possible that the deposit is drained before each party has been paid. This is an accepted trade-off, because the amounts are small and low gas costs are more important, as long as the actual double spending does not reach a high level. To somewhat reduce the risks of double spends, the following precautions are taken:

  • Users can't immediately withdraw tokens from the UDC. They first have to announce their intention and then wait until a withdraw delay has elapsed.
  • The PFS demands a higher deposit than it's currently owed amount to give it some safety margin when other parties claim tokens
  • Only PFSs registered in the RSBC are allowed to claim IOUs. This is important because claims allow circumventing the UDC's withdraw delay.

A user and a PFS can theoretically collude to quickly withdraw the complete deposit (via a claim) before other services are paid. This should be unlikely due to the following aspects:

  • The savings achieved by cheating the other services are low compared to the coordination cost for the collusion
  • The PFS is itself a party receiving payments of services and does not want to promote cheating against services
  • If this becomes widespread, cheating users can theoretically be blacklisted by PFSs. This will require them to close their existing channels and reopen new channels at a cost which will most likely be higher than the profit gained by cheating

Specification State

First draft, awaiting comments. I plan to move this into the Raiden spec as soon as the discussion dies down and the comments are worked in.

@palango palango added Enhancement 🌟 New feature or request Contracts 🛂 Requires Smart Contract changes and removed Enhancement 🌟 New feature or request labels Jan 22, 2019
karlb added a commit to karlb/spec that referenced this issue Jan 29, 2019
This is raiden-network/raiden-services#38 with
only few changes. Spefic functions will be documented as the
implemenation makes progress.
palango pushed a commit to raiden-network/spec that referenced this issue Jan 29, 2019
This is raiden-network/raiden-services#38 with
only few changes. Spefic functions will be documented as the
implemenation makes progress.
@karlb
Copy link
Contributor Author

karlb commented Feb 26, 2019

The spec contains the latest information about the PFS payments. Please refer to https://raiden-network-specification.readthedocs.io/en/latest/service_contracts.html#oneton instead of this ticket.

@karlb karlb closed this as completed Feb 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Contracts 🛂 Requires Smart Contract changes
Projects
None yet
Development

No branches or pull requests

2 participants