Skip to content

Instantly share code, notes, and snippets.

@emschwartz
Last active January 31, 2018 17:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emschwartz/235ac5bdfcd0a6b07315a248c0cd84ee to your computer and use it in GitHub Desktop.
Save emschwartz/235ac5bdfcd0a6b07315a248c0cd84ee to your computer and use it in GitHub Desktop.
PSK2 take 2

Motivation for changing PSK2 Draft 1

Draft 1 of PSK2 attempts to support both streaming and chunked payments. However, it includes some features that are only useful for chunked payments and does not include some others that would be needed for a proper chunked payments implementation.

Based on a conversation with @sharafian, this proposes narrowing the scope of PSK2 while making it easier to build use cases like streaming and chunked payments on top.

For context, @justmoon had the idea to use PSK2 for "payment sockets", which I started implementing yesterday. However, @sharafian made the point that for many receiver use cases, it's better for the PSK2 receiver not to keep state but to simply call a callback for every chunk it gets. Applications will figure out their own logic for which chunks to accept and how to track the balance for different users or interactions. Therefore, PSK2 doesn't need the fields that are specifically for correlating multiple chunks -- and we shouldn't necessarily think of PSK2 packets as "chunks".

Overview of changes

PSK2 should now be thought of as a protocol for paid requests and (unpaid) responses that encrypts and authenticates the data, and handles condition and fulfillment generation. It does NOT implement features specifically for chunked payments but may be used by applications or higher-level protocols that do implement chunking and chunk reassembly.

  1. Remove Payment ID - If higher level protocols want to include an ID in the Application Data, they can do so and it's up to them to determine how to correlate requests that are part of one larger interaction.
  2. Remove Payment Amount - This is unnecessary because if applications want to track the total amount received, senders can simply keep a running total of the Chunk Amounts the receiver says they received.
  3. Specify errors - The protocol should specify the error codes that should be used in specific circumstances (for example, if the receiver is unable to decrypt the PSK request, either because it has been tampered with or because it does not understand the cipher used)
  4. Specify that the encrypted PSK response packet should be sent back on every error (so that failed payments can be used for end-to-end quoting, no matter what order the receiver applies their checks to incoming packets)

New packet format

(encryption envelope remains the same)

Field Type Rationale
Type UInt8 If the receiver fulfills a payment with a certain PSK response as the data, an intermediate connector should not be able to trick the sender into thinking the receiver actually rejected it (by attaching the same response to an ILP Reject packet). (Why a connector would do this is less clear, but it seems like if we're going to say the data is authenticated we should include an indication of whether it was a successful response or an error.)
Request ID (formerly Sequence) UInt32 (?) Used to correlate requests and responses and ensure that a malicious connector could not exchange the receiver's response for an earlier response they sent back. This should not be thought of as a sequence number anymore, because the receiver will NOT keep track of them to ensure uniqueness, they will only be required to respond with the same ID as the request.
Chunk / Request Amount UInt64 In the request this is the minimum amount the receiver should accept, and in the response it is the amount that the receiver got. This gives senders the ability to lock in some exchange rate and prevent connectors from taking most of the value of the packet without the sender and receiver knowing.
Applicaiton Data Var Octet String Reason is obvious, but now we'll actually implement this because we don't need to worry about data reassembly on the PSK2 layer (higher level protocols can implement if they want to)
Extensions Var Octet String Right now this will be empty but it's useful to have the ability to add more fields later if we need them. Senders MUST set this to 0 if there are no extensions, especially if they are sending Junk Data so that receivers who do implement extensions won't be confused if the first bytes of the junk happen to match a valid extension.
Junk Data Extra bytes, no format Senders and receivers SHOULD ignore additional bytes after the Extensions. This is useful if senders or receivers want to ensure all packets are the same size, in case variable sizes disclose information the connectors should not learn about the application.

Open questions

  1. Should there be a Type to indicate that a given request or response is the last one? (In draft 1 there is a type to indicate a packet is the last the sender will send, but there is no way for the receiver to indicate it's done) -- Arguably we do not need this, because if we're not thinking of PSK2 as a connection-oriented protocol anymore, it would be up to higher layers to indicate "this interaction is done, don't send/expect any more"
  2. Do we need the Chunk Amount? Is that useful in all cases?
  3. Is there anything else we might want to add?

UDP and TCP over ILP

Basic PSK2 will support sending data but will not handle ordering, reassembly, or retransmission for you, like UDP.

We can (and I'm probably going to try this next) build a proper TCP implementation on top of PSK2 that does segmentation and reassembly of money and data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment