Giter Site home page Giter Site logo

emschwartz / ilp-protocol-paystream Goto Github PK

View Code? Open in Web Editor NEW
2.0 1.0 2.0 189 KB

Duplex payment streams over ILP (and PSK)

Home Page: https://github.com/interledger/rfcs/issues/388

JavaScript 1.56% TypeScript 98.44%
interledger ilp psk2 pskv2 payment stream chunked

ilp-protocol-paystream's Introduction

ILP Payment Sockets

Bidirectional streams of money over ILP

Work in Progress -- Nothing is finished and everything could change!

See the issues for features under development.

Trying it Out

  1. Clone the repo
  2. npm install
  3. npm run build
  4. DEBUG=ilp-protocol* node example.js

ilp-protocol-paystream's People

Contributors

emschwartz avatar

Stargazers

 avatar  avatar

Watchers

 avatar

ilp-protocol-paystream's Issues

Should generating the address and secret be separate from creating the socket object?

@adrianhopebailie raised the point that we may want to separate the generation of the destinationAccount and sharedSecret from the creation of the socket object.

The two reasons I could see for doing this would be:

  1. Different processes could create the credentials and listen for incoming socket connections
  2. Socket objects aren't created in memory until the client is connected (this is a weak argument because if someone wanted to DoS the server, they could send one connection packet and then just not send any more)

The downsides of doing this would be:

  1. The user of the library needs to connect the context where they create the credentials to the socket object when it is created (for example, to know what limits to set on the socket and to register event handlers for incoming money)
  2. Having a separate process creating credentials wouldn't work with dynamic ILP addresses (like mini accounts currently uses)
  3. Payment Sockets are different than TCP sockets in that you're not setting up a listener for all incoming connections, but rather you need to specifically create the credentials for each connection. Therefore, it may make more sense to keep the context in which you're creating the credentials together with the socket object, because creating the credentials means you're listening for one specific connection anyway

Use a single sharedSecret

Right now, each side communicates a destinationAccount and sharedSecret to the other side. We could remove one of the fields from the protocol messages if the client side could listen using the same sharedSecret as the server.

This would require a function to be added to the PSK2 module that allows you to specify an address, secret, and handler rather than just having it generate the address and corresponding secret.

Determine if limits are compatible before sending

It is possible for the two sides to set their limits such that at least one of them is going to end up unhappy. It might be better to try to determine if this is going to be the case before sending any money, to error out before money is wasted.

Should there be a pause message and method?

Should there be a way to call pause on the socket, which would let the other party know that we're not going to send or receive any more until the user unpauses the stream?

Disable refunds by default?

If you don't raise the minimum each time you get a chunk in, the other person can reverse the flow of funds and get a refund. We probably should have an option to enableRefunds that is disabled by default (so the limit will automatically go up every time you get a chunk in).

Should the API deal with sending and receiving money instead of min/max balance?

Instead of using the min/max balance, we could make the API a little more similar to normal sockets (like @adrianhopebailie suggests in #19) by having methods like send and receive on the socket object.

Use Case Min/Max Balance API Alternative
Sending client.setMinAndMaxBalance(-1000) client.add(1000); client.flush() (or client.send(1000))
Requesting server.setMinBalance(1000) server.receive(1000)
Making funds available to be requested client.setMinBalance(-1000) client.add(1000)
Enabling refunds (not modifying the min balance as money is received) server.receive(1000); server.on('chunk', (amount) => client.add(amount))

You would add and remove money from the socket, instead of setting the range you want your balance to end up in. When you call receive it would reduce the socket's balance by that amount if it's already got that much or it would request more from the sender and wait until it has reached that amount.

Thoughts? Would that be easier or harder to work with?

Paying via several sockets to one invoice

The simple logic would be to say that one socket corresponds to one invoice. But if an invoice is persistent and several people can pay to it, there should be no reason why there cannot be several sockets open and paying off one invoice.

It's not clear to me how best to manage the balance to accomplish this. Right now I'm just closing the channel when the invoice is filled, but that feels a little bit hacky. Another option would be to change the balance of all sockets related to an invoice whenever a packet comes in, but then it creates a ton of messages.

Best way to do cleanup

Currently, in an SPSP server I create a new receiver socket on every single query. After a while they close if there is no activity, but it seems like an SPSP endpoint could be overwhelmed by queries if it keeps the sockets around for a while. Also if the sender begins to send but then stops, the socket does not appear to time out.

Requesting money with exchange rate can lead to overpayment

When I call setMinAndMaxBalance(10000) on the receiving side, and pass a minimum balance of -Infinity to the sending side, 100081 ends up making it to the receiver. The sender is using USD, and the receiver is using JPY. The source amount sent is 937 at an exchange rate of 106.81.

It appears as though the receiving amount is impossible to hit exactly with these parameters, and if the receiver were to send the 81 micro-yen back, it would be too small to get one micro-dollar. Although I didn't notice anywhere where the receiver attempted to send the excess back.

What should be done in this case?

Separate message type for when the destinationAccount needs to be sent

Currently, the data that goes across the wire for every chunk includes a spot for the destinationAccount. At the moment this is only used on the first message the client sends to the server, and is left as an empty string (encoded as a single 0-byte) for every subsequent message.

We should probably make a separate message type that has the destinationAccount field.

One question related to this is whether that message should be thought of as a "connect" message, or whether you could send that later, for example if you want to change the ILP address the other party should be sending to.

Multiple packets in flight

If the Maximum Payment Size is lower than the total bandwidth, we would want to send multiple packets at the same time. Right now this is unlikely to be the case, but it may be so in the future.

Should default slippage be 1%, 0%, or something else?

When the sockets connect, they send one chunk just to figure out the exchange rate. Every subsequent will have the minDestinationAmount set so that the receiver won't accept the chunk if the exchange rate has gotten worse than the original rate by the given slippage percentage. The question is what the default slippage should be.

If the default slippage is 1%, clients and servers will tolerate the exchange rate getting worse by at most 1% before throwing an error and stopping the flow of money. If we set it to 0% by default, that increases the chances that payments will fail because of legitimate exchange rate movements but also changes the incentive for connectors who might maliciously change the exchange rate. If implementations have zero tolerance by default, changing the exchange rate while a payment is in flight will cause user-level errors that a sneaky connector would not want.

Methods to wait for specific amount to be sent or received

Working with the minBalance and maxBalance directly can be a bit unintuitive. Should we add methods like sendSourceAmount that return a Promise that resolves when the amount has been sent, or receiveAmount that resolves when an amount has been received?

One thing to figure out with such methods is how to deal with the case where the balance is not already at a limit. If the balance is 0 and the minBalance is 100 and you call receiveAmount(50), should it wait until the balance is 50 or 150? Also, what happens if you call one of these methods again before the first call has resolved? Should it add to (or subtract from) the limit and wait until the updated limit is reached?

Rename?

Should this protocol be called something other than "paystream" or "payment stream"?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.