Skip to content

Commit

Permalink
feat: trigger content claims equals on piece cid computed
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos committed Sep 19, 2023
1 parent 12a5393 commit 607fa87
Show file tree
Hide file tree
Showing 11 changed files with 349 additions and 48 deletions.
28 changes: 20 additions & 8 deletions filecoin/functions/piece-cid-report.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as Sentry from '@sentry/serverless'
import { Config } from '@serverless-stack/node/config/index.js'
import { unmarshall } from '@aws-sdk/util-dynamodb'
import { Piece } from '@web3-storage/data-segment'
import { CID } from 'multiformats/cid'

import { reportPieceCid } from '../index.js'
import { getServiceConnection, getServiceSigner } from '../service.js'
Expand All @@ -28,27 +29,36 @@ async function pieceCidReport (event) {
// @ts-expect-error can't figure out type of new
const pieceRecord = unmarshall(records[0].new)
const piece = Piece.fromString(pieceRecord.piece).link
const content = CID.parse(pieceRecord.link)

const aggregateServiceConnection = getServiceConnection({
did: aggregatorDid,
url: aggregatorUrl
})
const claimsServiceConnection = getServiceConnection({
did: aggregatorDid,
url: aggregatorUrl
})
const issuer = getServiceSigner({
privateKey
})
const audience = aggregateServiceConnection.id
/** @type {import('@web3-storage/filecoin-client/types').InvocationConfig} */
const invocationConfig = {
issuer,
audience,
with: issuer.did(),
}

const { ok, error } = await reportPieceCid({
piece,
content,
group: issuer.did(),
aggregateServiceConnection,
invocationConfig
aggregateInvocationConfig: /** @type {import('@web3-storage/filecoin-client/types').InvocationConfig} */ ({
issuer,
audience: aggregateServiceConnection.id,
with: issuer.did(),
}),
claimsServiceConnection,
claimsInvocationConfig: /** @type {import('../types').ClaimsInvocationConfig} */ ({
issuer,
audience: claimsServiceConnection.id,
with: issuer.did(),
})
})

if (error) {
Expand All @@ -73,6 +83,8 @@ function getEnv() {
return {
aggregatorDid: mustGetEnv('AGGREGATOR_DID'),
aggregatorUrl: mustGetEnv('AGGREGATOR_URL'),
contentClaimsDid: mustGetEnv('CONTENT_CLAIMS_DID'),
contentClaimsUrl: mustGetEnv('CONTENT_CLAIMS_URL'),
}
}

Expand Down
35 changes: 31 additions & 4 deletions filecoin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as Hasher from 'fr32-sha2-256-trunc254-padded-binary-tree-multihash'
import * as Digest from 'multiformats/hashes/digest'
import { Piece } from '@web3-storage/data-segment'
import { CID } from 'multiformats/cid'
import { Assert } from '@web3-storage/content-claims/capability'

Check failure on line 7 in filecoin/index.js

View workflow job for this annotation

GitHub Actions / Test

Cannot find module '@web3-storage/content-claims/capability' or its corresponding type declarations.
import { Aggregator } from '@web3-storage/filecoin-client'

import { GetCarFailed, ComputePieceFailed } from './errors.js'
Expand Down Expand Up @@ -86,19 +87,44 @@ export async function computePieceCid({
/**
* @param {object} props
* @param {import('@web3-storage/data-segment').PieceLink} props.piece
* @param {import('multiformats').CID} props.content
* @param {string} props.group
* @param {import('@web3-storage/filecoin-client/types').InvocationConfig} props.invocationConfig
* @param {import('@ucanto/principal/ed25519').ConnectionView<any>} props.aggregateServiceConnection
* @param {import('@web3-storage/filecoin-client/types').InvocationConfig} props.aggregateInvocationConfig
* @param {import('@ucanto/principal/ed25519').ConnectionView<any>} props.claimsServiceConnection
* @param {import('./types.js').ClaimsInvocationConfig} props.claimsInvocationConfig
*/
export async function reportPieceCid ({
piece,
content,
group,
invocationConfig,
aggregateServiceConnection
aggregateServiceConnection,
aggregateInvocationConfig,
claimsServiceConnection,
claimsInvocationConfig
}) {
// Add claim for reading
const claimResult = await Assert.equals
.invoke({
issuer: claimsInvocationConfig.issuer,
audience: claimsInvocationConfig.audience,
with: claimsInvocationConfig.with,
nb: {
content,
equals: piece
}
})
.execute(claimsServiceConnection)

if (claimResult.out.error) {
return {
error: claimResult.out.error
}
}

// Add piece for aggregation
const aggregateQueue = await Aggregator.aggregateQueue(
invocationConfig,
aggregateInvocationConfig,
piece,
group,
{ connection: aggregateServiceConnection }
Expand All @@ -109,6 +135,7 @@ export async function reportPieceCid ({
error: aggregateQueue.out.error
}
}

return {
ok: {},
}
Expand Down
2 changes: 2 additions & 0 deletions filecoin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
"@aws-sdk/client-sqs": "^3.226.0",
"@sentry/serverless": "^7.22.0",
"@ucanto/client": "^8.0.1",
"@ucanto/interface": "^8.1.0",
"@ucanto/principal": "^8.1.0",
"@ucanto/transport": "^8.0.0",
"@web3-storage/content-claims": "^3.0.1",
"@web3-storage/data-segment": "^3.0.1",
"@web3-storage/filecoin-client": "^1.3.0",
"fr32-sha2-256-trunc254-padded-binary-tree-multihash": "^1.0.0",
Expand Down
6 changes: 5 additions & 1 deletion filecoin/test/helpers/mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const notImplemented = () => {

/**
* @param {Partial<
* import('@web3-storage/filecoin-client/types').AggregatorService
* import('@web3-storage/filecoin-client/types').AggregatorService &
* { assert: Partial<import('@web3-storage/content-claims/server/service/api').AssertService> }

Check failure on line 10 in filecoin/test/helpers/mocks.js

View workflow job for this annotation

GitHub Actions / Test

Cannot find module '@web3-storage/content-claims/server/service/api' or its corresponding type declarations.
* >} impl
*/
export function mockService(impl) {
Expand All @@ -15,6 +16,9 @@ export function mockService(impl) {
add: withCallCount(impl.aggregate?.add ?? notImplemented),
queue: withCallCount(impl.aggregate?.queue ?? notImplemented),
},
assert: {
equals: withCallCount(impl.assert?.equals ?? notImplemented)
}
}
}

Expand Down
66 changes: 65 additions & 1 deletion filecoin/test/helpers/ucanto.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,68 @@ import * as Server from '@ucanto/server'
import * as Client from '@ucanto/client'
import * as CAR from '@ucanto/transport/car'
import * as FilecoinCapabilities from '@web3-storage/capabilities/filecoin'
import { Assert } from '@web3-storage/content-claims/capability'

Check failure on line 6 in filecoin/test/helpers/ucanto.js

View workflow job for this annotation

GitHub Actions / Test

Cannot find module '@web3-storage/content-claims/capability' or its corresponding type declarations.

import { OperationFailed } from './errors.js'
import { mockService } from './mocks.js'

const nop = (/** @type {any} */ invCap) => {}

/**
* @param {any} serviceProvider
* @param {object} [options]
* @param {(inCap: any) => void} [options.onCall]
* @param {boolean} [options.mustFail]
*/
export async function getClaimsServiceServer (serviceProvider, options = {}) {
const onCall = options.onCall || nop
const equalsStore = new Map()

const service = mockService({
assert: {
equals: Server.provide(Assert.equals, async ({ capability, invocation }) => {
const invCap = invocation.capabilities[0]
const { content, equals } = capability.nb

if (options.mustFail) {
return {
error: new OperationFailed(
'failed to add to aggregate',
// @ts-ignore wrong dep
invCap.nb?.content
)
}
}

equalsStore.set(content.toString(), equals.toString())

Check failure on line 39 in filecoin/test/helpers/ucanto.js

View workflow job for this annotation

GitHub Actions / Test

'content' is of type 'unknown'.

Check failure on line 39 in filecoin/test/helpers/ucanto.js

View workflow job for this annotation

GitHub Actions / Test

'equals' is of type 'unknown'.
equalsStore.set(equals.toString(), content.toString())

Check failure on line 40 in filecoin/test/helpers/ucanto.js

View workflow job for this annotation

GitHub Actions / Test

'equals' is of type 'unknown'.

Check failure on line 40 in filecoin/test/helpers/ucanto.js

View workflow job for this annotation

GitHub Actions / Test

'content' is of type 'unknown'.

onCall(invCap)

return {
ok: {}
}
})
}
})

const server = Server.create({
id: serviceProvider,
service,
codec: CAR.inbound,
})
const connection = Client.connect({
id: serviceProvider,
codec: CAR.outbound,
channel: server,
})

return {
service,
connection
}
}

/**
* @param {any} serviceProvider
* @param {object} [options]
Expand Down Expand Up @@ -112,9 +168,10 @@ export async function getAggregatorServiceServer (serviceProvider, options = {})
}
}

export async function getAggregatorServiceCtx () {
export async function getServiceCtx () {
const storefront = await Signer.generate()
const aggregator = await Signer.generate()
const claims = await Signer.generate()

return {
storefront: {
Expand All @@ -126,6 +183,13 @@ export async function getAggregatorServiceCtx () {
did: aggregator.did(),
privateKey: Signer.format(aggregator),
raw: aggregator
},
claims: {
did: claims.did(),
privateKey: Signer.format(claims),
raw: claims
}
}
}


Loading

0 comments on commit 607fa87

Please sign in to comment.