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

chore: switch to more coherent naming #118

Merged
merged 6 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions .github/workflows/words-to-ignore.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ JWT-encoded
Pre-Draft
TTL
UCAN
ucan
UCAN's
UCANs
Zelenka
Expand Down
255 changes: 154 additions & 101 deletions w3-blob.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,48 +51,66 @@ Authorized agent MAY invoke `/space/content/add/blob` capability on the [space]

### Add Blob Diagram

Following diagram illustrates execution workflow.
Following diagram illustrates execution flow. Alice invokes `/space/content/add/blob` command which produces receipt with three effects (`allocate`, `put`, `accept`) and awaited `claim`. Effects have dependencies and therefor predict execution flow (from left to right). The output of the main task awaits on the result of the result of the last effect.
Gozala marked this conversation as resolved.
Show resolved Hide resolved

```mermaid
flowchart TB
Gozala marked this conversation as resolved.
Show resolved Hide resolved
Add("▶️ /space/content/add/blob 👩‍💻 🤖")
Add("⏯️ /space/content/add/blob 👩‍💻 🤖")
AddOk("🧾 { ok: { claim } }")
Gozala marked this conversation as resolved.
Show resolved Hide resolved

Added("🧾 { ok: { claim 🚦 } }")

Allocate("⏭️ /service/blob/allocate 🤖")
subgraph accept
Accept("⏯️ /service/blob/accept 🤖")
AcceptOk("🧾 { ok: { claim } }")
Gozala marked this conversation as resolved.
Show resolved Hide resolved
end

Put("⏭️ /http/put 🤖🔑")
subgraph put
Put("⏯️ /http/put 🔑")
PutOk("🧾 { ok: {} }")
end

Accept("⏭️ /service/blob/accept 🤖")

Accepted("🧾 { ok: { claim 🎫 } }")

subgraph allocate
Allocate("⏯️ /service/blob/allocate 🤖")
AllocateOk("🧾 { ok: { url headers } }")
end

Claim("🎫 /assert/location 🤖👩‍💻")
Gozala marked this conversation as resolved.
Show resolved Hide resolved

Add --o Added
Added -.-> Allocate
Added -.-> Accept
Added -.-> Put
Allocate --> Accept

Put --> Accept
Accept --o Accepted
Accepted -- claim --> Claim
Added -- claim --> Accept

Add -.-> AddOk
AddOk -- ⏭️ --> allocate
AddOk -- ⏭️ --> put
AddOk -- ⏭️ --> accept
AddOk -- 🚦 out.ok.claim --> AcceptOk
Gozala marked this conversation as resolved.
Show resolved Hide resolved



Allocate -.-> AllocateOk

Put -- 🚦url --> AllocateOk
Put -- 🚦headers --> AllocateOk

Put -.-> PutOk



Accept -- 🚦_put --> PutOk
Accept -.-> AcceptOk
AcceptOk -- claim --> Claim
Gozala marked this conversation as resolved.
Show resolved Hide resolved
```

#### Iconography

- Icon on the left describes type of the node
- Icon on the right describes issuer / audience pair if only one audience is the issuer
- ▶️ Task
- ⏯️ Task
- ⏭️ Next Task (a.k.a Effect)
- 🧾 Receipt
- 🎫 Delegation / Commitment
- 🎫 Delegation
- 🚦 Await
- 👩‍💻 Alice
- 🤖 Service
- 🔑 Derived Principal

### Add Blob Invocation Example

Expand All @@ -105,9 +123,9 @@ Shown Invocation example illustrates Alice requesting to add 2MiB blob to her sp
"iss": "did:key:zAlice",
"aud": "did:web:web3.storage",
"args": {
"blob": {
"site": {
Gozala marked this conversation as resolved.
Show resolved Hide resolved
// multihash of the blob as byte array
"content": { "/": { "bytes": "mEi...sfKg" } },
"digest": { "/": { "bytes": "mEi...sfKg" } },
// size of the blob in bytes
"size": 2_097_152,
}
Expand All @@ -122,74 +140,102 @@ Shows an example receipt for the above `/space/content/add/blob` capability invo
> ℹ️ We use `// "/": "bafy..` comments to denote CID of the parent object.

```js
{ // "/": "bafy..add",
{ // "/": "bafy..work",
"iss": "did:web:web3.storage",
"aud": "did:key:zAlice",
"cmd": "/ucan/assert/result"
"cmd": "/ucan/assert",
"sub": "did:web:web3.storage",
"args": {
// refers to the invocation from the example
"ran": { "/": "bafy..add" },
"out": {
"ok": {
// result of the add is the content (location) claim
// that is produced as result of "bafy..accept"
"claim": { "await/ok": { "/": "bafy...accept" } }
}
},
// Previously `next` was known as `fx` instead, which is
// set of tasks to be scheduled.
"next": [
// 1. System attempts to allocate memory in user space for the blob.
{ // "/": "bafy...alloc",
"cmd": "/service/blob/allocate",
"sub": "did:web:web3.storage",
"args": {
// space where memory is allocated
"space": "did:key:zAlice",
"blob": {
// multihash of the blob as byte array
"content": { "/": { "bytes": "mEi...sfKg" } },
// size of the blob in bytes
"size": 2_097_152,
"assert": [
// refers to the invocation from the example
{ "/": "bafy..add" },
Gozala marked this conversation as resolved.
Show resolved Hide resolved
// refers to the receipt corresponding to the above invocation
{
"out": {
"ok": {
// result of the add is the content (location) claim
// that is produced as result of "bafy..accept"
"blob": {
"ucan/await": [
".out.ok.blob",
Gozala marked this conversation as resolved.
Show resolved Hide resolved
{ "/": "bafy...accept" }
]
}
}
}
},
// 2. System requests user agent (or anyone really) to upload the content
// corresponding to the blob
// via HTTP PUT to given location.
{ // "/": "bafy...put",
"cmd": "/http/put",
"sub": "did:key:zMh...der", // <-- Ed299.. derived key from content multihash
"args": {
"content": { "/": { "bytes": "mEi...sfKg" } },
"address": { "await/ok": { "/": "bafy...alloc" } },
"_allocate": { "await/ok": { "/": "bafy...alloc" } }
},
"meta": {
// archive of the principal keys
"keys": {
"did:key:zMh...der": { "/": "mEi...sfKg" }
}
}
},
// 3. System will attempt to accept uploaded content that matches blob
// multihash and size.
{ // "/": "bafy...accept",
"cmd": "/service/blob/accept",
"sub": "did:web:web3.storage",
"args": {
"space": "did:key:zAlice",
"blob": {
// multihash of the blob as byte array
"content": { "/": { "bytes": "mEi...sfKg" } },
"size": 2_097_152,
// Previously `next` was known as `fx` instead, which is
// set of tasks to be scheduled.
"next": [
// 1. System attempts to allocate memory in user space for the blob.
{ // "/": "bafy...alloc",
"cmd": "/service/blob/allocate",
"sub": "did:web:web3.storage",
"args": {
// space where memory is allocated
"space": "did:key:zAlice",
"blob": {
// multihash of the blob as byte array
"digest": { "/": { "bytes": "mEi...sfKg" } },
// size of the blob in bytes
"size": 2_097_152,
},
// task that caused this invocation
"cause": { "/": "bafy..add" }
}
},
exp: 1711122994101,
// This task is blocked on allocation
_allocate: { "await/ok": { "/": "bafy...alloc" } },
_put: { "await/ok", { "/": "bafy...put" } }
}
// 2. System requests user agent (or anyone really) to upload the content
// corresponding to the blob
// via HTTP PUT to given location.
{ // "/": "bafy...put",
"cmd": "/http/put",
"sub": "did:key:zMh...der", // <-- Ed299.. derived key from content multihash
"args": {
// pipe url from the allocation result
"url": {
"ucan/await": [
".out.ok.address.url",
{ "/": "bafy...alloc" }
]
},
// pipe headers from the allocation result
"headers": {
"ucan/await": [
".out.ok.address.headers",
{ "/": "bafy...alloc" }
]
},
// body of the http request
"body": {
// multihash of the blob as byte array
"digest": { "/": { "bytes": "mEi...sfKg" } },
"size": 2_097_152
},
},
"meta": {
// archive of the principal keys
"keys": {
"did:key:zMh...der": { "/": "mEi...sfKg" }
}
}
},
// 3. System will attempt to accept uploaded content that matches blob
// multihash and size.
{ // "/": "bafy...accept",
"cmd": "/service/blob/accept",
"sub": "did:web:web3.storage",
"args": {
"space": "did:key:zAlice",
"blob": {
// multihash of the blob as byte array
"content": { "/": { "bytes": "mEi...sfKg" } },
"size": 2_097_152,
},
"exp": 1711122994101,
// This task is blocked on allocation
"_put": { "ucan/await": [".out.ok", { "/": "bafy...put" }] }
}
}
]
}
]
}
Expand All @@ -210,17 +256,17 @@ type AddBlob = {
}

type Blob = {
content: Multihash
size: int
digest: Multihash
size: int
}

type Multihash = bytes
type SpaceDID = string
```

#### Blob Content
#### Blob Digest

The `args.blob.content` field MUST be a [multihash] digest of the blob payload bytes. Implementation SHOULD support SHA2-256 algorithm. Implementation MAY in addition support other hashing algorithms.
The `args.blob.digest` field MUST be a [multihash] digest of the blob payload bytes. Implementation SHOULD support SHA2-256 algorithm. Implementation MAY in addition support other hashing algorithms.

#### Blob Size

Expand All @@ -243,8 +289,8 @@ type AddBlobReceipt = {
}

type AddBlobOk = {
claim: {
"await/ok": Link<AcceptBlob>
site: {
"ucan/await": [".out.ok.site", Link<AcceptBlob>]
}
}

Expand All @@ -259,12 +305,12 @@ Invocation MUST fail if any of the following is true

1. Provided **sub**ject space is not provisioned with a provider.
1. Provided `blob.size` is outside of supported range.
1. Provided `blob.content` is not a valid [multihash].
1. Provided `blob.content` [multihash] hashing algorithm is not supported.
1. Provided `blob.digest` is not a valid [multihash].
1. Provided `blob.digest` [multihash] hashing algorithm is not supported.

Invocation MUST succeed if non of the above is true. Success value MUST be an object with a `claim` field set to [await/ok] of the task that produces [location claim].
Invocation MUST succeed if non of the above is true. Success value MUST be an object with a `site` field set to [ucan/await] of the task that produces [location commitment].

Task linked from the `claim` of the success value MUST be present in the receipt effects _(`next` field)_.
Task linked from the `site` of the success value MUST be present in the receipt effects _(`next` field)_.

#### Add Blob Effects

Expand Down Expand Up @@ -304,7 +350,7 @@ The `args.blob` field MUST be set to the `Blob` the space is allocated for.

#### Allocation Cause

The `args.cause` field MUST be set to the [Link] for an [Add Blob] task, that caused an allocation.
The `args.cause` field MUST be set to the [Link] for the [Add Blob] task, that caused an allocation.

### Allocate Blob Receipt

Gozala marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -380,15 +426,23 @@ type BlobPut = {

### Put Blob Subject

The subject field SHOULD be [`did:key`] corresponding to the [Ed25519] private key that is first 32 bytes of the blob [multihash].
The subject field SHOULD be [`did:key`] corresponding to the [Ed25519] private key that is last 32 bytes of the blob [multihash].
Gozala marked this conversation as resolved.
Show resolved Hide resolved

### Put Blob Metadata

Metadata MUST contain `keys` field with an object value that contains [`did:key`] subject as key and corresponding private key as bytes as a value.
Metadata MUST contain `keys` field with an object value that contains [`did:key`] subject as key and corresponding private key bytes as a value.

### Put Blob URL

Destination `url` MUST be specified in the arguments and it MUST be an endpoint that can accept HTTP PUT request.

### Put Blob Headers

The `headers` map MUST be specified in the arguments. It MUST have string keys corresponding to header names and string values corresponding to header values.

### Put Blob Address
### Put Blob Body
Gozala marked this conversation as resolved.
Show resolved Hide resolved

Destination address `url` and required `headers` MUST be specified in the arguments.
The `body` argument MUST be an object with `digest` and `size` fields describing the content of the request body.

### Put Blob Receipt

Expand Down Expand Up @@ -418,7 +472,7 @@ Receipt MUST not have any effects.

## Accept Blob

Authorized agent MAY invoke `/service/blob/accept` capability on the [provider] subject. Invocation MUST either succeed when content is delivered on allocated `address` or fail if either allocation failed or expired before content was delivered.
Authorized agent MAY invoke `/service/blob/accept` capability on the [provider] subject. Invocation MUST either succeed when content is delivered to an allocated `address` or fail if either allocation failed or expired before content was delivered.
Gozala marked this conversation as resolved.
Show resolved Hide resolved

Invocation MUST block until content is delivered. Implementation MAY resume when content is sent to the allocated address or await until client signals that content has been delivered using [put blob receipt].
Gozala marked this conversation as resolved.
Show resolved Hide resolved

Expand Down Expand Up @@ -520,7 +574,6 @@ Blob can be published by authorizing read interface (e.g. IPFS gateway) by deleg
[multihash]:https://github.com/multiformats/multihash
[space]:#space
[IPNI]:https://github.com/ipni/specs/blob/main/IPNI.md
[await/ok]:https://github.com/ucan-wg/invocation?tab=readme-ov-file#await
[location claim]:#location-claim
[Add Blob]:#add-blob
[Put Blob]:#put-blob
Expand Down
Loading