-
Notifications
You must be signed in to change notification settings - Fork 234
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
IPIP-378: Delegated Routing HTTP POST API #378
base: main
Are you sure you want to change the base?
Changes from 4 commits
6336689
68c0dff
5bc8b14
4db804a
d9287e5
0f74972
82aa9d9
921b0b6
94429a5
05b000e
30a5e3b
7b32f53
fbefb1b
f6f0d9b
cf83c02
da12e11
05dceba
ccbc085
a69d2b8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# IPIP-378: Delegated Content Routing HTTP Provide Records API | ||
|
||
- Start Date: 2023-02-14 | ||
- Related Issues: | ||
- https://github.com/ipfs/specs/pull/378 | ||
|
||
## Summary | ||
|
||
This IPIP extends the [IPIP-337 HTTP Delegated Routing API](0337-delegated-routing-http-api.md) to provide records over `PUT` requests. | ||
|
||
The work here was originally proposed as part of IPIP-337, and eventually was separated into its own IPIP in order to reduce the scope of original work, while enabling iterative release of the HTTP delegated routing APIs. | ||
|
||
## Motivation | ||
|
||
The IPFS interaction with DHT includes both read and write operations. | ||
A user can provide records, advertising the presence of content, as well as looking up providers for a given CID. | ||
The specification proposed by [IPIP-337](0337-delegated-routing-http-api.md) offers an idiomatic first-class support for offloading the lookup portion of this interaction onto other processes and/or servers. | ||
Following the same motivations that inspired [IPIP-337](0337-delegated-routing-http-api.md), this document expands the HTTP APIs to also | ||
offload the ability to provide records noto a third-party system. | ||
|
||
## Detailed design | ||
|
||
The API extensions are added to the [Delegated Content Routing HTTP API spec/`PUT`](../routing/DELEGATED_CONTENT_ROUTING_HTTP.md#put-routingv1providers) section, along with complimentary sections that outline known formats followed by example payload. | ||
|
||
## Design rationale | ||
|
||
The rationale for the design of `PUT` operations closely follows the reasoning listed in [IPIP-337](0337-delegated-routing-http-api.md#design-rationale). | ||
The design uses a human-readable request/response structure with extensibility in mind. | ||
The specification imposes no restrictions on the schema nor the protocol advertised in provider records. | ||
The hope is that such extensibility will encourage and inspire innovation for better transfer protocols. | ||
In order to reduce barrier for adoption, the existing | ||
|
||
### User benefit | ||
|
||
Expanding the user benefits listed as part of [IPIP-337](0337-delegated-routing-http-api.md#user-benefit), in the context of content routing write operations are typically more expensive than read operations. They involve book keeping such as TTL, gossip propagation, etc. | ||
Therefore, it is highly desirable to reduce the burden of advertising provider records onto the network by means of delegation through simple to use HTTP APIs. | ||
|
||
### Compatibility | ||
|
||
#### Backwards Compatibility | ||
|
||
##### DHT | ||
|
||
The `PUT` APIs proposed here require a new data format for specifying provider records. | ||
Since the records must include a valid signature, records published through HTTP delegated routing must be resigned. | ||
|
||
##### Reframe | ||
|
||
See [IPIP-337/Backwards Compatibility](0337-delegated-routing-http-api.md#backwards-compatibility). | ||
|
||
#### Forwards Compatibility | ||
|
||
See [IPIP-337/Forwads Compatibility](0337-delegated-routing-http-api.md#forwards-compatibility). | ||
|
||
### Security | ||
|
||
See [IPIP-337/Security](0337-delegated-routing-http-api.md#security). | ||
|
||
### Alternatives | ||
|
||
- Reframe (general-purpose RPC) was evaluated, see "Design rationale" section for rationale why it was not selected. | ||
|
||
### Copyright | ||
|
||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -66,13 +66,13 @@ Specifications for some transfer protocols are provided in the "Transfer Protoco | |||||||||||||
|
||||||||||||||
### `GET /routing/v1/providers/{CID}` | ||||||||||||||
|
||||||||||||||
#### Response codes | ||||||||||||||
#### `GET` Response codes | ||||||||||||||
|
||||||||||||||
- `200` (OK): the response body contains 0 or more records | ||||||||||||||
- `404` (Not Found): must be returned if no matching records are found | ||||||||||||||
- `422` (Unprocessable Entity): request does not conform to schema or semantic constraints | ||||||||||||||
|
||||||||||||||
#### Response Body | ||||||||||||||
#### `GET` Response Body | ||||||||||||||
|
||||||||||||||
```json | ||||||||||||||
{ | ||||||||||||||
|
@@ -90,6 +90,47 @@ Response limit: 100 providers | |||||||||||||
|
||||||||||||||
Each object in the `Providers` list is a *read provider record*. | ||||||||||||||
|
||||||||||||||
### `PUT /routing/v1/providers` | ||||||||||||||
|
||||||||||||||
#### `PUT` Response codes | ||||||||||||||
|
||||||||||||||
- `200` (OK): the server processed the full list of provider records (possibly unsuccessfully, depending on the semantics of the particular records) | ||||||||||||||
- `400` (Bad Request): the server deems the request to be invalid and cannot process it | ||||||||||||||
- `422` (Unprocessable Entity): request does not conform to schema or semantic constraints | ||||||||||||||
- `501` (Not Implemented): the server does not support providing records | ||||||||||||||
|
||||||||||||||
#### `PUT` Request Body | ||||||||||||||
|
||||||||||||||
```json | ||||||||||||||
{ | ||||||||||||||
"Providers": [ | ||||||||||||||
{ | ||||||||||||||
"Protocol": "<protocol_name>", | ||||||||||||||
"Schema": "bitswap", | ||||||||||||||
... | ||||||||||||||
} | ||||||||||||||
] | ||||||||||||||
} | ||||||||||||||
``` | ||||||||||||||
|
||||||||||||||
Each object in the `Providers` list is a *write provider record*. | ||||||||||||||
|
||||||||||||||
#### `PUT` Response Body | ||||||||||||||
|
||||||||||||||
```json | ||||||||||||||
{ | ||||||||||||||
"ProvideResults": [ | ||||||||||||||
{ ... } | ||||||||||||||
] | ||||||||||||||
} | ||||||||||||||
``` | ||||||||||||||
|
||||||||||||||
- `ProvideResults` is a list of results in the same order as the `Providers` in the request, and the schema of each object is determined by the `Protocol` of the corresponding write object (called "Write Provider Records Response" in the Known Transfer Protocols section) | ||||||||||||||
- This may contain output information such as TTLs, errors, etc. | ||||||||||||||
- It is undefined whether the server will allow partial results | ||||||||||||||
- The work for processing each provider record should be idempotent so that it can be retried without excessive cost in the case of full or partial failure of the request | ||||||||||||||
- Default limit of 100 keys per request | ||||||||||||||
|
||||||||||||||
## Pagination | ||||||||||||||
|
||||||||||||||
This API does not support pagination, but optional pagination can be added in a backwards-compatible spec update. | ||||||||||||||
|
@@ -118,7 +159,7 @@ limits, allowing every site to query the API for results: | |||||||||||||
|
||||||||||||||
```plaintext | ||||||||||||||
Access-Control-Allow-Origin: * | ||||||||||||||
Access-Control-Allow-Methods: GET, OPTIONS | ||||||||||||||
Access-Control-Allow-Methods: GET, PUT, OPTIONS | ||||||||||||||
``` | ||||||||||||||
|
||||||||||||||
## Known Transfer Protocols | ||||||||||||||
|
@@ -148,6 +189,60 @@ Specification: [ipfs/specs/BITSWAP.md](https://github.com/ipfs/specs/blob/main/B | |||||||||||||
|
||||||||||||||
The server should respect a passed `transport` query parameter by filtering against the `Addrs` list. | ||||||||||||||
|
||||||||||||||
#### Bitswap Write Provider Records | ||||||||||||||
lidel marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
|
||||||||||||||
```json | ||||||||||||||
{ | ||||||||||||||
"Protocol": "transport-bitswap", | ||||||||||||||
"Schema": "bitswap", | ||||||||||||||
"Signature": "<signature>", | ||||||||||||||
"Payload": "<payload>" | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💭 this creates one @masih is this ossified, or is there still time to fix this and use different schema for PUTs?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is still time. Changing thanks |
||||||||||||||
} | ||||||||||||||
``` | ||||||||||||||
|
||||||||||||||
- `Signature`: a multibase-encoded signature of the sha256 hash of the `Payload` field, signed using the private key of the Peer ID specified in the `Payload` JSON. Signing details for specific key types should follow [libp2p/peerid specs](https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#key-types), unless stated otherwise. | ||||||||||||||
lidel marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
|
||||||||||||||
- Servers may ignore this field if they do not require signature verification. | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @masih is cid.contact doing verification of this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cid.contact does not support any PUT over http delegated routing. |
||||||||||||||
- `Payload`: a string containing a serialized JSON object which conforms with the following schema: | ||||||||||||||
|
||||||||||||||
```json | ||||||||||||||
{ | ||||||||||||||
"Keys": ["cid1", "cid2"], | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @masih what is the max length of this list? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My thinking is to make the maximum length be derived from whatever the server supports as max request body. A user should be able to find this out via If that makes sense I am happy to document this in the spec. Unless you think we need some explicit max length for that array? |
||||||||||||||
"Timestamp": 0, | ||||||||||||||
"AdvisoryTTL": 0, | ||||||||||||||
"ID": "12D3K...", | ||||||||||||||
"Addrs": ["/ip4/..."] | ||||||||||||||
} | ||||||||||||||
``` | ||||||||||||||
|
||||||||||||||
- `Keys` is a list of the CIDs being provided | ||||||||||||||
- `Timestamp` is the current time | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the format? Unix epoch? What resolution (ms? ns?) Would ASCII string that follows notation from [rfc3339] ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed on following standardized format that is easily human-parseable and doesn't have ambiguity. |
||||||||||||||
- `AdvisoryTTL` is the time by which the caller expects the server to keep the record available | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this a timestamp of a duration? If a duration, is it miliseconds? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If a duration, maybe get that into the name. |
||||||||||||||
- If this value is unknown, the caller may use a value of 0 | ||||||||||||||
- `ID` is the peer ID that was used to sign the record | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No concerns 👍 |
||||||||||||||
- `Addrs` is a list of string-encoded multiaddrs | ||||||||||||||
|
||||||||||||||
A [400 Bad Request](https://httpwg.org/specs/rfc9110.html#status.400) response code should be returned if the signature check fails. | ||||||||||||||
|
||||||||||||||
Note that this only supports Peer IDs expressed as identity multihashes. Peer IDs with older key types that exceed 42 bytes are not verifiable since they only contain a hash of the key, not the key itself. | ||||||||||||||
Normally, if the Peer ID contains only a hash of the key, then the key is obtained out-of-band (e.g. by fetching the block via IPFS). | ||||||||||||||
If support for these Peer IDs is needed in the future, this spec can be updated to allow the client to provide the key and key type out-of-band by adding optional `PublicKey` and `PublicKeyType` fields, and if the Peer ID is a CID, then the server can verify the public key's authenticity against the CID, and then proceed with the rest of the verification scheme. | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason why we don't include There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alternatively, we could include There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm okay with either of these paths. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems fine to me 👍 |
||||||||||||||
|
||||||||||||||
The `Payload` field is a string, not a proper JSON object, to prevent its contents from being accidentally parsed and re-encoded by intermediaries, which may change the order of JSON fields and thus cause the record to fail validation. | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we have to mangle Reusing DHT record payload would save CPU time on IPFS nodes that publish to both DHT and IPNI (signature would be generated only once, not twice). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I suspect the reason for this is better human readability? The beginning of this document (merged as part of IPIP-337 states "human-readable encodings of types are preferred".
We can make the same argument about HTTP delegated routing itself. Unless there is evidence to suggest that we should be heavily optimising this, my vote would be to favour human readability. @guseggert what are your thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @guillaumemichel this is related to #345 – can you point us where up-to-date protobufs related to CID announcements on DHT lives these days? Unsure how feasible it is to reuse the announcement's wire format here. Could we write down and publish the basic wire format information like protobuf section about ipns record, so this IPIP can refer to spec website, and not some go code 🙏 @masih I think When IPFS node speaks more than bitswap (we already plan to do HTTP next to bitswap in many places), doing a PUT of the same CIDs once for every protocol duplicates the cost on the client. I don't think there is anything special about Maybe instead of having There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I agree 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||
|
||||||||||||||
#### Write Provider Records Response | ||||||||||||||
|
||||||||||||||
```json | ||||||||||||||
{ | ||||||||||||||
"AdvisoryTTL": 0 | ||||||||||||||
} | ||||||||||||||
``` | ||||||||||||||
|
||||||||||||||
- `AdvisoryTTL` is the time at which the server expects itself to drop the record | ||||||||||||||
- If less than the `AdvisoryTTL` in the request, then the client should re-issue the request by that point | ||||||||||||||
- If greater than the `AdvisoryTTL` in the request, then the server expects the client to be responsible for the content for up to that amount of time (TODO: this is ambiguous) | ||||||||||||||
- If 0, the server makes no claims about the lifetime of the record | ||||||||||||||
|
||||||||||||||
### Filecoin Graphsync | ||||||||||||||
|
||||||||||||||
Multicodec name: `transport-graphsync-filecoinv1` | ||||||||||||||
|
@@ -173,3 +268,7 @@ Specification: [ipfs/go-graphsync/blob/main/docs/architecture.md](https://github | |||||||||||||
- `PieceCID`: the CID of the [piece](https://spec.filecoin.io/systems/filecoin_files/piece/#section-systems.filecoin_files.piece) within which the data is stored | ||||||||||||||
- `VerifiedDeal`: whether the deal corresponding to the data is verified | ||||||||||||||
- `FastRetrieval`: whether the provider claims there is an unsealed copy of the data available for fast retrieval | ||||||||||||||
|
||||||||||||||
#### Filecoin Graphsync Write Provider Records | ||||||||||||||
|
||||||||||||||
There is currently no specified schema. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💭 this section grows way faster than the rest of the spec.
Would it be ok to move "Known Transfer Protocols" to a separate file (
KNOWN_TRANSFER_PROTOCOLS.md
)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recommend doing this in a separate PR to reduce lines changes what are irrelevant to what this PR is trying to introduce.
If this is not a blocker for this PR, I'd be happy to take this as a TODO and get it done once this PR is merged.