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

fix: encode space DID as bytes in blob caveats #41

Merged
merged 2 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all 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 packages/capabilities/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"uint8arrays": "^5.0.3"
},
"devDependencies": {
"@ipld/dag-ucan": "^3.4.0",
"@storacha/eslint-config": "workspace:^",
"@types/assert": "^1.5.6",
"@types/mocha": "^10.0.0",
Expand Down
14 changes: 3 additions & 11 deletions packages/capabilities/src/blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,7 @@
*/
import { capability, Schema, Link, ok } from '@ucanto/validator'
import { content } from './space/blob.js'
import {
equalBlob,
equalWith,
SpaceDID,
and,
equal,
checkLink,
Await,
} from './utils.js'
import { equalBlob, equalWith, and, equal, checkLink, Await } from './utils.js'

/**
* Capability can only be delegated (but not invoked) allowing audience to
Expand All @@ -50,7 +42,7 @@ export const allocate = capability({
/** Link to the add blob task that initiated the allocation. */
cause: Schema.link({ version: 1 }),
/** DID of the user space where the allocation takes place. */
space: SpaceDID,
space: Schema.bytes(),
}),
derives: (claimed, delegated) =>
and(equalWith(claimed, delegated)) ||
Expand All @@ -73,7 +65,7 @@ export const accept = capability({
/** Blob to accept. */
blob: content,
/** DID of the user space where allocation took place. */
space: SpaceDID,
space: Schema.bytes(),
/** This task is blocked on `http/put` receipt available */
_put: Await,
}),
Expand Down
21 changes: 11 additions & 10 deletions packages/capabilities/test/capabilities/blob.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import assert from 'assert'
import { access } from '@ucanto/validator'
import { ed25519, Verifier } from '@ucanto/principal'
import * as DID from '@ipld/dag-ucan/did'
import * as Blob from '../../src/blob.js'
import * as Capability from '../../src/top.js'
import {
Expand Down Expand Up @@ -44,7 +45,7 @@ describe('blob capabilities', function () {
digest: car.cid.multihash.bytes,
size: car.bytes.length,
},
space: space.did(),
space: DID.parse(space.did()),
cause: await createCborCid({ now: Date.now() }),
},
proofs: [await top()],
Expand Down Expand Up @@ -74,7 +75,7 @@ describe('blob capabilities', function () {
digest: car.cid.multihash.bytes,
size: car.bytes.length,
},
space: space.did(),
space: DID.parse(space.did()),
cause: await createCborCid({ now: Date.now() }),
},
proofs: [await blob()],
Expand Down Expand Up @@ -111,7 +112,7 @@ describe('blob capabilities', function () {
digest: car.cid.multihash.bytes,
size: car.bytes.length,
},
space: space.did(),
space: DID.parse(space.did()),
cause: await createCborCid({ now: Date.now() }),
},
proofs: [blob],
Expand All @@ -138,7 +139,7 @@ describe('blob capabilities', function () {
audience: bob,
with: account.did(),
nb: {
space: space0.did(),
space: DID.parse(space0.did()),
},
proofs: [await top()],
})
Expand All @@ -152,7 +153,7 @@ describe('blob capabilities', function () {
digest: car.cid.multihash.bytes,
size: car.bytes.length,
},
space: space1.did(),
space: DID.parse(space1.did()),
cause: await createCborCid({ now: Date.now() }),
},
proofs: [blob],
Expand Down Expand Up @@ -181,7 +182,7 @@ describe('blob capabilities', function () {
digest: car.cid.multihash.bytes,
size: car.bytes.length,
},
space: space.did(),
space: DID.parse(space.did()),
_put: {
'ucan/await': ['.out.ok', await createCborCid('receipt')],
},
Expand Down Expand Up @@ -213,7 +214,7 @@ describe('blob capabilities', function () {
digest: car.cid.multihash.bytes,
size: car.bytes.length,
},
space: space.did(),
space: DID.parse(space.did()),
_put: {
'ucan/await': ['.out.ok', await createCborCid('receipt')],
},
Expand Down Expand Up @@ -252,7 +253,7 @@ describe('blob capabilities', function () {
digest: car.cid.multihash.bytes,
size: car.bytes.length,
},
space: space.did(),
space: DID.parse(space.did()),
_put: {
'ucan/await': ['.out.ok', await createCborCid('receipt')],
},
Expand Down Expand Up @@ -281,7 +282,7 @@ describe('blob capabilities', function () {
audience: bob,
with: account.did(),
nb: {
space: space0.did(),
space: DID.parse(space0.did()),
},
proofs: [await top()],
})
Expand All @@ -295,7 +296,7 @@ describe('blob capabilities', function () {
digest: car.cid.multihash.bytes,
size: car.bytes.length,
},
space: space1.did(),
space: DID.parse(space1.did()),
_put: {
'ucan/await': ['.out.ok', await createCborCid('receipt')],
},
Expand Down
11 changes: 10 additions & 1 deletion packages/upload-api/src/blob/accept.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Message, Invocation } from '@ucanto/core'
import * as Transport from '@ucanto/transport/car'
import * as API from '../types.js'
import * as HTTP from '@storacha/capabilities/http'
import * as DID from '@ipld/dag-ucan/did'
import * as Digest from 'multiformats/hashes/digest'
import { AgentMessage } from '../lib.js'

/**
Expand Down Expand Up @@ -95,7 +97,14 @@ export const poll = async (context, receipt) => {
return messageWrite
}

const register = await context.registry.register(allocate.nb)
const register = await context.registry.register({
space: /** @type {API.SpaceDID} */ (DID.decode(allocate.nb.space).did()),
cause: allocate.nb.cause,
blob: {
digest: Digest.decode(allocate.nb.blob.digest),
size: allocate.nb.blob.size,
},
})
if (register.error) {
// it's ok if there's already a registration of this blob in this space
if (register.error.name !== 'EntryExists') {
Expand Down
5 changes: 3 additions & 2 deletions packages/upload-api/src/blob/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as Blob from '@storacha/capabilities/blob'
import * as SpaceBlob from '@storacha/capabilities/space/blob'
import * as HTTP from '@storacha/capabilities/http'
import * as Digest from 'multiformats/hashes/digest'
import * as DID from '@ipld/dag-ucan/did'
import * as API from '../types.js'
import { allocate as spaceAllocate } from '../space-allocate.js'
import { createConcludeInvocation } from '../ucan/conclude.js'
Expand Down Expand Up @@ -126,7 +127,7 @@ async function allocate({ context, blob, space, cause }) {
digest: blob.digest,
size: blob.size,
},
space,
space: DID.parse(space),
cause,
},
})
Expand Down Expand Up @@ -271,7 +272,7 @@ async function accept({ context, provider, blob, space, delivery }) {
with: provider.did(),
nb: {
blob,
space,
space: DID.parse(space),
_put: { 'ucan/await': ['.out.ok', delivery.task.link()] },
},
})
Expand Down
17 changes: 14 additions & 3 deletions packages/upload-api/src/blob/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,20 @@ export function blobGetProvider(context) {
const digest = Digest.decode(capability.nb.digest)
const space = Server.DID.parse(capability.with).did()
const res = await context.registry.find(space, digest)
if (res.error && res.error.name === 'EntryNotFound') {
return Server.error(new BlobNotFound(digest))
if (res.error) {
if (res.error.name === 'EntryNotFound') {
return Server.error(new BlobNotFound(digest))
}
return res
}
return res

return Server.ok({
blob: {
digest: res.ok.blob.digest.bytes,
size: res.ok.blob.size,
},
cause: res.ok.cause,
insertedAt: res.ok.insertedAt.toISOString(),
})
})
}
16 changes: 15 additions & 1 deletion packages/upload-api/src/blob/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ export function blobListProvider(context) {
return Server.provide(SpaceBlob.list, async ({ capability }) => {
const space = capability.with
const { cursor, size } = capability.nb
return await context.registry.entries(space, { size, cursor })
const result = await context.registry.entries(space, { size, cursor })
if (result.error) {
return result
}
return Server.ok({
...result.ok,
results: result.ok.results.map((r) => ({
blob: {
digest: r.blob.digest.bytes,
size: r.blob.size,
},
cause: r.cause,
insertedAt: r.insertedAt.toISOString(),
})),
})
})
}
6 changes: 5 additions & 1 deletion packages/upload-api/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,11 @@ import { RevocationsStorage } from './types/revocations.js'
export * from '@storacha/capabilities/types'
export * from '@ucanto/interface'

export type { ProvisionsStorage, Provision, Subscription } from './types/provisions.js'
export type {
ProvisionsStorage,
Provision,
Subscription,
} from './types/provisions.js'
export type {
DelegationsStorage,
Query as DelegationsStorageQuery,
Expand Down
14 changes: 11 additions & 3 deletions packages/upload-api/src/types/blob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import type {
} from '@ucanto/interface'
import {
Multihash,
BlobItem as Entry,
BlobAllocate,
BlobAccept,
BlobAllocateSuccess,
Expand All @@ -24,7 +23,16 @@ import { MultihashDigest } from 'multiformats'
import { ListResponse, SpaceDID } from '../types.js'
import { Storage } from './storage.js'

export type { Entry }
export interface Blob {
digest: MultihashDigest
size: number
}

export interface Entry {
blob: Blob
cause: Link
insertedAt: Date
}

/** Indicates an entry was not found that matches the passed details. */
export interface EntryNotFound extends Failure {
Expand Down Expand Up @@ -71,7 +79,7 @@ export interface BlobModel {
export interface RegistrationData {
space: SpaceDID
cause: Link
blob: BlobModel
blob: Blob
}

export interface BlobService {
Expand Down
8 changes: 7 additions & 1 deletion packages/upload-api/test/external-service/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import { BrowserStorageNode, StorageNode } from './storage-node.js'
import * as BlobRetriever from './blob-retriever.js'
import * as RoutingService from './router.js'

export { ClaimsService, BrowserStorageNode, StorageNode, BlobRetriever, RoutingService }
export {
ClaimsService,
BrowserStorageNode,
StorageNode,
BlobRetriever,
RoutingService,
}

/**
* @param {object} config
Expand Down
14 changes: 11 additions & 3 deletions packages/upload-api/test/external-service/storage-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import { ed25519 } from '@ucanto/principal'
import { CAR, HTTP } from '@ucanto/transport'
import * as Server from '@ucanto/server'
import { connect } from '@ucanto/client'
import { AllocatedMemoryNotWrittenError, BlobSizeLimitExceededError } from '../../src/blob.js'
import {
AllocatedMemoryNotWrittenError,
BlobSizeLimitExceededError,
} from '../../src/blob.js'

/**
* @typedef {{
Expand Down Expand Up @@ -61,7 +64,12 @@ const createService = ({
const digest = Digest.decode(capability.nb.blob.digest)
const checksum = base64pad.baseEncode(digest.digest)
if (capability.nb.blob.size > MaxUploadSize) {
return error(new BlobSizeLimitExceededError(capability.nb.blob.size, MaxUploadSize))
return error(
new BlobSizeLimitExceededError(
capability.nb.blob.size,
MaxUploadSize
)
)
}
if (await contentStore.has(digest)) {
return ok({ size: 0 })
Expand Down Expand Up @@ -323,7 +331,7 @@ export class StorageNode {

/**
* @param {API.ClaimsClientContext} ctx
* @param {{ space: API.SpaceDID, digest: API.MultihashDigest, location: API.URI }} params
* @param {{ space: Uint8Array, digest: API.MultihashDigest, location: API.URI }} params
*/
const publishLocationCommitment = async (ctx, { digest, location }) => {
const { invocationConfig, connection } = ctx.claimsService
Expand Down
2 changes: 1 addition & 1 deletion packages/upload-api/test/handlers/blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export const test = {
proofs: [proof],
// Note: we have to set an expiration, or the default expiration value
// will be set when the invocation is executed and the UCAN issued.
expiration: (Math.floor(Date.now() / 1000)) + 10
expiration: Math.floor(Date.now() / 1000) + 10,
})
// Invoke `blob/add` for the first time
const firstBlobAdd = await invocation.execute(connection)
Expand Down
Loading
Loading