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

Add STREAM receipts #570

Merged
merged 20 commits into from
Apr 22, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: The Simple Payment Setup Protocol (SPSP)
draft: 9
draft: 10
---
# Simple Payment Setup Protocol (SPSP)

Expand All @@ -24,6 +24,7 @@ SPSP provides for exchanging basic server details needed by a client to set up a
* **SPSP Server** - The application that handles incoming SPSP requests from the SPSP Client.
* **SPSP Endpoint** - The specific HTTPS endpoint on the SPSP Server used for setting up a payment.
* **STREAM Module** - Software included in the SPSP Client and Server that implements the [STREAM](../0029-stream/0029-stream.md) protocol.
* **STREAM Receipt** - Proof provided by the payment recipient of the total amount received on a stream.
sappenin marked this conversation as resolved.
Show resolved Hide resolved

### Interfaces

Expand Down Expand Up @@ -62,6 +63,17 @@ Host: example.com
Accept: application/spsp4+json, application/spsp+json
```

##### Request Headers
wilsonianb marked this conversation as resolved.
Show resolved Hide resolved

The request MAY contain at least the following headers in order to pre-share STREAM Receipt details between the SPSP Server and a party verifying payments sent to the SPSP Server:
sappenin marked this conversation as resolved.
Show resolved Hide resolved

| Header | Description |
|:----------------|:-----------------------------------------------------------|
| `Receipt-Nonce` | A base64-encoded 16-byte random nonce used to identify the STREAM connection in STREAM Receipts. |
| `Receipt-Secret` | A base64-encoded 32-byte key used to generate a STREAM Receipt's HMAC. |
kincaidoneil marked this conversation as resolved.
Show resolved Hide resolved

The SPSP Client MAY be provided with an SPSP Endpoint belonging to the receipt verifier, which would add the receipt headers and proxy the query to the SPSP Server.
wilsonianb marked this conversation as resolved.
Show resolved Hide resolved

#### Response
``` http
HTTP/1.1 200 OK
Expand Down
28 changes: 27 additions & 1 deletion 0029-stream/0029-stream.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: STREAM - A Multiplexed Money and Data Transport for ILP
draft: 8
draft: 9
---

# STREAM: A Multiplexed Money and Data Transport for ILP
Expand Down Expand Up @@ -55,6 +55,7 @@ This document specifies the STREAM Interledger Transport protocol, which provide
- [5.3.12. `StreamMaxData` Frame](#5312-streammaxdata-frame)
- [5.3.13. `StreamDataBlocked` Frame](#5313-streamdatablocked-frame)
- [5.3.14. `ConnectionAssetDetails` Frame](#5314-connectionassetdetails-frame)
- [5.3.15. `StreamReceipt` Frame](#5315-streamreceipt-frame)
- [5.4. Error Codes](#54-error-codes)
- [6. Condition and Fulfillment Generation](#6-condition-and-fulfillment-generation)
- [6.1. Unfulfillable Condition](#61-unfulfillable-condition)
Expand Down Expand Up @@ -158,6 +159,8 @@ A server MUST communicate the following values to a client using an **authentica

To avoid storing a 32 byte secret for each connection, a server MAY deterministically generate the shared secret for each connection from a single server secret and a nonce appended to the ILP Address given to a particular client, for example by using an HMAC.

For each new connection, a server MAY be provided with a pre-shared 32 byte Receipt Secret to generate receipts and 16 byte Receipt Nonce to include in those receipts. To avoid storing these for each connection, a server MAY deterministically append them to the ILP Address given to a particular client. If doing so, the server MUST encrypt the Receipt Secret.
wilsonianb marked this conversation as resolved.
Show resolved Hide resolved

### 4.2. Matching Packets to Connections

Incoming packets can either be associated with an existing connection, or, for servers, potentially create a new connection. Endpoints MAY append extra segments to the ILP addresses assigned to them by their upstream connectors to help direct incoming packets.
Expand Down Expand Up @@ -192,6 +195,10 @@ Client streams MUST be odd-numbered starting with 1 and server-initiated streams

Money can be sent for a given stream by sending an ILP Prepare packet with a non-zero `amount` and a `StreamMoney` frame in the STREAM packet to indicate which stream the money is for. A single ILP Prepare can carry value destined for multiple streams and the `shares` field in each of the `StreamMoney` frames indicates what portion of the Prepare amount should go to each stream.

The receiver SHOULD include `StreamReceipt` frames in the ILP Fulfill packet indicating the total amount of money received in each stream, unless a Receipt Secret and Receipt Nonce were not pre-shared with the receiver.

To use STREAM receipts, the Receipt Secret and Receipt Nonce are pre-shared between the receiver and a receipt verifier party. Receipts are generated by the receiver and passed to the sender, who may submit the receipts directly or indirectly to the verifier. This allows the verifier to confirm the payment, as only the receiver and the verifier know the Receipt Secret.

#### 4.4.3. Sending Data

Data can be sent for a given stream by sending an ILP Prepare packet with a `StreamData` frame in the STREAM packet. A single ILP Prepare can carry data destined for multiple streams.
Expand Down Expand Up @@ -313,6 +320,7 @@ The frame types are as follows and each is described in greater detail below:
| `0x14` | Stream Data |
| `0x15` | Stream Data Max |
| `0x16` | Stream Data Blocked |
| `0x17` | Stream Receipt |

#### 5.3.1. `ConnectionClose` Frame

Expand Down Expand Up @@ -436,6 +444,24 @@ In other words, if a sender resends data (e.g. because a packet was lost), it MU

Asset details exposed by this frame MUST NOT change during the lifetime of a Connection.

#### 5.3.15. `StreamReceipt` Frame

| Field | Type | Description |
|---|---|---|
| Stream ID | VarUInt | Identifier of the stream this frame refers to. |
| Receipt | 65-Byte OctetString | Proof provided by the receiver of the total amount received on this stream |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why doesn't the frame individually enumerate the fields of the receipt? Are they not intended to be exposed at the STREAM layer...?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The receipt is kinda treated as a whole object that's passed around, for instance the receipt would be emitted in WM. So I think "grouping" like this can be helpful

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why mandate the exact size of the receipt instead of leaving it open-ended for possible extension?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍
Should we also consider including a receipt version number?
Or could the receipt size be used to check compatibility, such as with receipt support discovery (#570 (comment))?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the receipt itself could have a version byte? Size might not be good enough if a future version is variable length. And if the receipt contains its own version info then STREAM doesn't need to emit extra information about receipt version

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed receipt to VarOctetString and added version number: 1633e86


The `Receipt` MUST contain the following fields encoded using the [Octet Encoding Rules (OER)](http://www.oss.com/asn1/resources/books-whitepapers-pubs/Overview_of_OER.pdf):
wilsonianb marked this conversation as resolved.
Show resolved Hide resolved

| Field | Type | Description |
|---|---|---|
| HMAC | UInt256 | HMAC-SHA256 over all other fields using the 32 byte Receipt Secret, which is pre-shared between the verifying party and the receiver. |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we explain the inputs to the MAC more precisely, e.g., "the message is the concatenation of each of the following fields, in this order"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the description in 8df9304

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: if the HMAC was the last field instead of the first, it would be easy to implement serialization with one fewer allocation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I put the hmac first with verification in mind, but it makes sense to me to optimize the serialization.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in 8df9304

| Receipt Nonce | UInt128 | A random nonce pre-shared between the verifying party and the receiver used to identify the STREAM connection. |
| Stream ID | UInt8 | Identifier of the stream this receipt refers to. |
wilsonianb marked this conversation as resolved.
Show resolved Hide resolved
| Total Received | UInt64 | Total amount, denominated in the units of the receiver, that the receiver has received on this stream thus far. |
| Stream Start Time | UInt64 | A UNIX timestamp referring to the time that the stream was established at the receiver. |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth considering whether we should use an InterledgerTimestamp here. It still is fixed length, and although it is a little trickier to parse it solves things like leap seconds. That said a unix timestamp is gonna be easier to use in a lot of different environments.

wilsonianb marked this conversation as resolved.
Show resolved Hide resolved


### 5.4. Error Codes

Error codes are sent in `StreamClose` and `ConnectionClose` frames to indicate what caused the stream or connection to be closed.
Expand Down
17 changes: 17 additions & 0 deletions 0029-stream/test-vectors/StreamPacketFixtures.json
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,23 @@
},
"buffer": "AQwBAAEAAQEWCwF7CP//////////"
},
{
"name": "frame:stream_receipt",
"packet": {
"sequence": "0",
"packetType": 12,
"amount": "0",
"frames": [
{
"type": 23,
"name": "StreamReceipt",
"streamId": "123",
"receipt": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
}
]
},
"buffer": "AQwBAAEAAQEXQwF7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
},
{
"name": "frame:stream_max_money:receive_max:too_big",
"packet": {
Expand Down
11 changes: 10 additions & 1 deletion asn1/Stream.asn
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ FrameSet FRAME ::= {
{19 StreamMoneyBlocked} |
{20 StreamData} |
{21 StreamMaxData} |
{22 StreamDataBlocked}
{22 StreamDataBlocked} |
{23 StreamReceipt]}
}

StreamFrame ::= SEQUENCE {
Expand Down Expand Up @@ -174,4 +175,12 @@ StreamDataBlocked ::= SEQUENCE {
maxOffset VarUInt
}

StreamReceipt ::= SEQUENCE {
-- Identifier of the stream
streamId VarUInt,

-- Receipt for verifying the total amount received on this stream
receipt OCTET STRING (SIZE(65))
}

END