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: publish location claim to content claims service #1571

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
26 changes: 26 additions & 0 deletions packages/upload-api/src/blob/accept.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ export function blobAcceptProvider(context) {
expiration: Infinity,
})

// Publish this claim to the content claims service
const pubClaim = await publishLocationClaim(context, { space, digest, location: createUrl.ok })
if (pubClaim.error) {
return pubClaim
}

// Create result object
/** @type {API.OkBuilder<API.BlobAcceptSuccess, API.BlobAcceptFailure>} */
const result = Server.ok({
Expand Down Expand Up @@ -137,3 +143,23 @@ export const poll = async (context, receipt) => {

return { ok: {} }
}

/**
* @param {API.ClaimsClientContext} ctx
* @param {{ space: API.SpaceDID, digest: API.MultihashDigest, location: API.URI }} params
*/
const publishLocationClaim = async (ctx, { digest, location }) => {
const { invocationConfig, connection } = ctx.claimsService
const { issuer, audience, with: resource, proofs } = invocationConfig
const res = await Assert.location
.invoke({
issuer,
audience,
with: resource,
nb: { content: { digest: digest.bytes }, location: [location] },
expiration: Infinity,
proofs,
})
.execute(connection)
return res.out
}
4 changes: 2 additions & 2 deletions packages/upload-api/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ import { StorageGetError } from './types/storage.js'
import { AllocationsStorage, BlobsStorage, BlobAddInput } from './types/blob.js'
export type { AllocationsStorage, BlobsStorage, BlobAddInput }
import { IPNIService, IndexServiceContext } from './types/index.js'
import { ClaimsClientConfig } from './types/content-claims.js'
import { ClaimsClientConfig, ClaimsClientContext } from './types/content-claims.js'
import { Claim } from '@web3-storage/content-claims/client/api'
export type {
IndexServiceContext,
Expand Down Expand Up @@ -378,7 +378,7 @@ export type BlobServiceContext = SpaceServiceContext & {
getServiceConnection: () => ConnectionView<Service>
}

export type W3ServiceContext = SpaceServiceContext & {
export type W3ServiceContext = SpaceServiceContext & ClaimsClientContext & {
/**
* Service signer
*/
Expand Down
62 changes: 62 additions & 0 deletions packages/upload-api/test/handlers/blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { alice, registerSpace } from '../util.js'
import { BlobSizeOutsideOfSupportedRangeName } from '../../src/blob/lib.js'
import { createConcludeInvocation } from '../../src/ucan/conclude.js'
import { parseBlobAddReceiptNext } from '../helpers/blob.js'
import * as Result from '../helpers/result.js'

/**
* @type {API.Tests}
Expand Down Expand Up @@ -426,6 +427,67 @@ export const test = {
'accept was not successful'
)
},
'blob/accept publishes location claim to claims service': async (
assert,
context
) => {
const { proof, spaceDid } = await registerSpace(alice, context)

const data = new Uint8Array([11, 22, 34, 44, 55])
const digest = await sha256.digest(data)
const size = data.byteLength

const service = createServer(context)
const connection = connect({ id: context.id, channel: service })

const blobAddInvocation = BlobCapabilities.add.invoke({
issuer: alice,
audience: context.id,
with: spaceDid,
nb: { blob: { digest: digest.bytes, size } },
proofs: [proof],
})
const receipt = await blobAddInvocation.execute(connection)
assert.ok(receipt.out.ok)

const nextTasks = parseBlobAddReceiptNext(receipt)
const { address } = Result.unwrap(nextTasks.allocate.receipt.out)
assert.ok(address)

if (address) {
const httpPut = await fetch(address.url, {
method: 'PUT',
mode: 'cors',
body: data,
headers: address.headers,
})
assert.equal(httpPut.status, 200, await httpPut.text())
Copy link
Member

Choose a reason for hiding this comment

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

suggestion: await httpPut.text() seems like a less-than-ideal assertion message to me. I see it's copying the pattern from blob/add schedules allocation and returns effects for allocate, accept and put together with their receipts (when stored). Could we give both these assertions more meaningful messages? Maybe something like:

Suggested change
assert.equal(httpPut.status, 200, await httpPut.text())
assert.equal(httpPut.status, 200, `PUT ${address.url} failed (${httpPut.status}): ${await httpPut.text()}`)

}

const keys =
/** @type {API.SignerArchive<API.DID, typeof ed25519.signatureCode>} */
(nextTasks.put.task.facts[0]['keys'])
const blobProvider = ed25519.from(keys)
const httpPutReceipt = await Receipt.issue({
issuer: blobProvider,
ran: nextTasks.put.task.link(),
result: { ok: {} },
})
const httpPutConcludeInvocation = createConcludeInvocation(
alice,
context.id,
httpPutReceipt
)
const ucanConclude = await httpPutConcludeInvocation.execute(connection)
assert.ok(ucanConclude.out.ok)

// ensure a location claim exists for the content root
const claims = Result.unwrap(await context.claimsService.read(digest))
assert.ok(
claims.some(c => c.type === 'assert/location'),
'did not find location claim'
)
},
'blob/add fails when a blob with size bigger than maximum size is added':
async (assert, context) => {
const { proof, spaceDid } = await registerSpace(alice, context)
Expand Down
Loading