Skip to content

Commit

Permalink
fix: encode space DID as bytes in blob caveats
Browse files Browse the repository at this point in the history
  • Loading branch information
alanshaw committed Nov 11, 2024
1 parent 4d263c7 commit 746b6f0
Show file tree
Hide file tree
Showing 14 changed files with 90 additions and 43 deletions.
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
5 changes: 2 additions & 3 deletions packages/capabilities/src/blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { content } from './space/blob.js'
import {
equalBlob,
equalWith,
SpaceDID,
and,
equal,
checkLink,
Expand Down Expand Up @@ -50,7 +49,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 +72,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()
}))
})
})
}
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
2 changes: 1 addition & 1 deletion packages/upload-api/test/external-service/storage-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,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
22 changes: 11 additions & 11 deletions packages/upload-api/test/storage/blob-registry-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const test = {
const { registry } = context
const data = new Uint8Array([11, 22, 34, 44, 55])
const digest = await sha256.digest(data)
const blob = { digest: digest.bytes, size: data.length }
const blob = { digest: digest, size: data.length }
const cause = await randomCID()
const registration = await registry.register({ space, blob, cause })
assert.ok(registration.ok)
Expand All @@ -26,7 +26,7 @@ export const test = {
const { registry } = context
const data = new Uint8Array([11, 22, 34, 44, 55])
const digest = await sha256.digest(data)
const blob = { digest: digest.bytes, size: data.length }
const blob = { digest: digest, size: data.length }
const cause = await randomCID()
const registration0 = await registry.register({ space, blob, cause })
assert.ok(registration0.ok)
Expand All @@ -45,7 +45,7 @@ export const test = {
assert.ok(find0.error)
assert.equal(find0.error?.name, EntryNotFound.name)

const blob = { digest: digest.bytes, size: data.length }
const blob = { digest: digest, size: data.length }
const cause = await randomCID()
const registration = await registry.register({ space, blob, cause })
assert.ok(registration.ok)
Expand All @@ -54,7 +54,7 @@ export const test = {
assert.ok(find1.ok)
assert.ok(find1.ok?.blob)
assert.equal(find1.ok?.blob.size, data.length)
assert.ok(equals(digest.bytes, find1.ok?.blob.digest || new Uint8Array()))
assert.ok(equals(digest.bytes, find1.ok?.blob.digest.bytes || new Uint8Array()))
assert.equal(find1.ok?.cause.toString(), cause.toString())
},
'should list all blobs in a space': async (assert, context) => {
Expand All @@ -65,12 +65,12 @@ export const test = {
// Data for alice
const data0 = new Uint8Array([11, 22, 34, 44, 55])
const digest0 = await sha256.digest(data0)
const blob0 = { digest: digest0.bytes, size: data0.length }
const blob0 = { digest: digest0, size: data0.length }
const cause0 = await randomCID()
// Data for bob
const data1 = new Uint8Array([66, 77, 88, 99, 0])
const digest1 = await sha256.digest(data1)
const blob1 = { digest: digest1.bytes, size: data1.length }
const blob1 = { digest: digest1, size: data1.length }
const cause1 = await randomCID()

// Get alice empty entries
Expand Down Expand Up @@ -101,8 +101,8 @@ export const test = {
assert.equal(entriesAlice1.ok?.results.length, 1)
assert.ok(
equals(
blob0.digest,
entriesAlice1.ok?.results[0].blob.digest || new Uint8Array()
blob0.digest.bytes,
entriesAlice1.ok?.results[0].blob.digest.bytes || new Uint8Array()
)
)

Expand All @@ -121,12 +121,12 @@ export const test = {
assert.equal(entriesAlice2.ok?.results.length, 2)
assert.ok(
entriesAlice2.ok?.results.some((res) =>
equals(res.blob.digest, blob0.digest)
equals(res.blob.digest.bytes, blob0.digest.bytes)
)
)
assert.ok(
entriesAlice2.ok?.results.some((res) =>
equals(res.blob.digest, blob1.digest)
equals(res.blob.digest.bytes, blob1.digest.bytes)
)
)
},
Expand All @@ -144,7 +144,7 @@ export const test = {
const { registry } = context
const data = new Uint8Array([11, 22, 34, 44, 55])
const digest = await sha256.digest(data)
const blob = { digest: digest.bytes, size: data.length }
const blob = { digest: digest, size: data.length }
const cause = await randomCID()

const reg = await registry.register({ space, blob, cause })
Expand Down
9 changes: 4 additions & 5 deletions packages/upload-api/test/storage/blob-registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,25 @@ export class Registry {
/** @type {API.BlobAPI.Registry['register']} */
async register({ space, cause, blob }) {
const entries = this.data.get(space) ?? []
if (entries.some((e) => equals(e.blob.digest, blob.digest))) {
if (entries.some((e) => equals(e.blob.digest.bytes, blob.digest.bytes))) {
return error(new EntryExists())
}
const insertedAt = new Date().toISOString()
this.data.set(space, [{ blob, cause, insertedAt }, ...entries])
this.data.set(space, [{ blob, cause, insertedAt: new Date() }, ...entries])
return ok({})
}

/** @type {API.BlobAPI.Registry['find']} */
async find(space, digest) {
const entries = this.data.get(space) ?? []
const entry = entries.find((e) => equals(e.blob.digest, digest.bytes))
const entry = entries.find((e) => equals(e.blob.digest.bytes, digest.bytes))
if (!entry) return error(new EntryNotFound())
return ok(entry)
}

/** @type {API.BlobAPI.Registry['deregister']} */
async deregister(space, digest) {
const entries = this.data.get(space) ?? []
const entry = entries.find((e) => equals(e.blob.digest, digest.bytes))
const entry = entries.find((e) => equals(e.blob.digest.bytes, digest.bytes))
if (!entry) return error(new EntryNotFound())
this.data.set(
space,
Expand Down
2 changes: 1 addition & 1 deletion packages/upload-api/test/storage/usage-storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class UsageStorage {
return {
cause: /** @type {import('../types.js').Link} */ (item.cause),
delta: item.size,
receiptAt: item.insertedAt,
receiptAt: item.insertedAt.toISOString(),
}
}),
},
Expand Down
Loading

0 comments on commit 746b6f0

Please sign in to comment.