From 6c340006f7492e7d0534d3c36b6aa965a02caae3 Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Mon, 18 Sep 2023 10:27:28 +0200 Subject: [PATCH] feat: trigger content claims equals on piece cid computed --- filecoin/functions/piece-cid-report.js | 28 +++++--- filecoin/index.js | 35 +++++++-- filecoin/package.json | 1 + package-lock.json | 98 ++++++++++++++++++++++++++ stacks/config.js | 2 + stacks/filecoin-stack.js | 4 +- 6 files changed, 155 insertions(+), 13 deletions(-) diff --git a/filecoin/functions/piece-cid-report.js b/filecoin/functions/piece-cid-report.js index f50c12a8..fdb035a0 100644 --- a/filecoin/functions/piece-cid-report.js +++ b/filecoin/functions/piece-cid-report.js @@ -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' @@ -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('@web3-storage/filecoin-client/types').InvocationConfig} */ ({ + issuer, + audience: claimsServiceConnection.id, + with: issuer.did(), + }) }) if (error) { @@ -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'), } } diff --git a/filecoin/index.js b/filecoin/index.js index 3c24d34f..35db955a 100644 --- a/filecoin/index.js +++ b/filecoin/index.js @@ -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' import { Aggregator } from '@web3-storage/filecoin-client' import { GetCarFailed, ComputePieceFailed } from './errors.js' @@ -83,19 +84,25 @@ 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} props.aggregateServiceConnection + * @param {import('@web3-storage/filecoin-client/types').InvocationConfig} props.aggregateInvocationConfig + * @param {import('@ucanto/principal/ed25519').ConnectionView} props.claimsServiceConnection + * @param {import('@web3-storage/filecoin-client/types').InvocationConfig} props.claimsInvocationConfig */ export async function reportPieceCid ({ piece, + content, group, - invocationConfig, - aggregateServiceConnection + aggregateServiceConnection, + aggregateInvocationConfig, + claimsServiceConnection, + claimsInvocationConfig }) { // Add piece for aggregation const aggregateQueue = await Aggregator.aggregateQueue( - invocationConfig, + aggregateInvocationConfig, piece, group, { connection: aggregateServiceConnection } @@ -106,6 +113,26 @@ export async function reportPieceCid ({ error: aggregateQueue.out.error } } + + // 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 + } + } + return { ok: {}, } diff --git a/filecoin/package.json b/filecoin/package.json index 6294aae9..61414ff2 100644 --- a/filecoin/package.json +++ b/filecoin/package.json @@ -13,6 +13,7 @@ "@ucanto/client": "^8.0.1", "@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": "github:web3-storage/fr32-sha2-256-trunc254-padded-binary-tree-multihash", diff --git a/package-lock.json b/package-lock.json index 904f35ff..02cc3e24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -108,6 +108,7 @@ "@ucanto/client": "^8.0.1", "@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": "github:web3-storage/fr32-sha2-256-trunc254-padded-binary-tree-multihash", @@ -4854,6 +4855,27 @@ "@web3-storage/data-segment": "^3.0.1" } }, + "node_modules/@web3-storage/content-claims": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@web3-storage/content-claims/-/content-claims-3.0.1.tgz", + "integrity": "sha512-7+JLmQaw4mDgs+VREtkHtk3Q0Bp1rv4Kt5YN2Qw/g73xvRja28/Uioy7iv83YHez52lAPwXFkSkGb0ifJy5PLw==", + "dependencies": { + "@ucanto/client": "^8.0.0", + "@ucanto/server": "^8.0.1", + "@ucanto/transport": "^8.0.0", + "carstream": "^1.0.2", + "multiformats": "^12.0.1" + } + }, + "node_modules/@web3-storage/content-claims/node_modules/multiformats": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-12.1.1.tgz", + "integrity": "sha512-GBSToTmri2vJYs8wqcZQ8kB21dCaeTOzHTIAlr8J06C1eL6UbzqURXFZ5Fl0EYm9GAFz1IlYY8SxGOs9G9NJRg==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@web3-storage/data-segment": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@web3-storage/data-segment/-/data-segment-3.0.1.tgz", @@ -6543,6 +6565,25 @@ "cardex": "bin.js" } }, + "node_modules/carstream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/carstream/-/carstream-1.1.0.tgz", + "integrity": "sha512-tbf8FOnGX1+0kOe77nm9MG53REiqQopDwzwbXYVxUcsKOAHG2KSD++qy95v1vrtRt1Q6L0Sb01it7QwJ+Yt1sQ==", + "dependencies": { + "@ipld/dag-cbor": "^9.0.3", + "multiformats": "^12.0.1", + "uint8arraylist": "^2.4.3" + } + }, + "node_modules/carstream/node_modules/multiformats": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-12.1.1.tgz", + "integrity": "sha512-GBSToTmri2vJYs8wqcZQ8kB21dCaeTOzHTIAlr8J06C1eL6UbzqURXFZ5Fl0EYm9GAFz1IlYY8SxGOs9G9NJRg==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/cbor": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", @@ -14979,6 +15020,18 @@ "node": ">=4.2.0" } }, + "node_modules/uint8arraylist": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/uint8arraylist/-/uint8arraylist-2.4.3.tgz", + "integrity": "sha512-oEVZr4/GrH87K0kjNce6z8pSCzLEPqHNLNR5sj8cJOySrTP8Vb/pMIbZKLJGhQKxm1TiZ31atNrpn820Pyqpow==", + "dependencies": { + "uint8arrays": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/uint8arrays": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-4.0.6.tgz", @@ -19805,6 +19858,25 @@ "@web3-storage/data-segment": "^3.0.1" } }, + "@web3-storage/content-claims": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@web3-storage/content-claims/-/content-claims-3.0.1.tgz", + "integrity": "sha512-7+JLmQaw4mDgs+VREtkHtk3Q0Bp1rv4Kt5YN2Qw/g73xvRja28/Uioy7iv83YHez52lAPwXFkSkGb0ifJy5PLw==", + "requires": { + "@ucanto/client": "^8.0.0", + "@ucanto/server": "^8.0.1", + "@ucanto/transport": "^8.0.0", + "carstream": "^1.0.2", + "multiformats": "^12.0.1" + }, + "dependencies": { + "multiformats": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-12.1.1.tgz", + "integrity": "sha512-GBSToTmri2vJYs8wqcZQ8kB21dCaeTOzHTIAlr8J06C1eL6UbzqURXFZ5Fl0EYm9GAFz1IlYY8SxGOs9G9NJRg==" + } + } + }, "@web3-storage/data-segment": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@web3-storage/data-segment/-/data-segment-3.0.1.tgz", @@ -19961,6 +20033,7 @@ "@ucanto/client": "^8.0.1", "@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", "ava": "^4.3.3", @@ -21265,6 +21338,23 @@ "varint": "^6.0.0" } }, + "carstream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/carstream/-/carstream-1.1.0.tgz", + "integrity": "sha512-tbf8FOnGX1+0kOe77nm9MG53REiqQopDwzwbXYVxUcsKOAHG2KSD++qy95v1vrtRt1Q6L0Sb01it7QwJ+Yt1sQ==", + "requires": { + "@ipld/dag-cbor": "^9.0.3", + "multiformats": "^12.0.1", + "uint8arraylist": "^2.4.3" + }, + "dependencies": { + "multiformats": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-12.1.1.tgz", + "integrity": "sha512-GBSToTmri2vJYs8wqcZQ8kB21dCaeTOzHTIAlr8J06C1eL6UbzqURXFZ5Fl0EYm9GAFz1IlYY8SxGOs9G9NJRg==" + } + } + }, "cbor": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", @@ -27353,6 +27443,14 @@ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true }, + "uint8arraylist": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/uint8arraylist/-/uint8arraylist-2.4.3.tgz", + "integrity": "sha512-oEVZr4/GrH87K0kjNce6z8pSCzLEPqHNLNR5sj8cJOySrTP8Vb/pMIbZKLJGhQKxm1TiZ31atNrpn820Pyqpow==", + "requires": { + "uint8arrays": "^4.0.2" + } + }, "uint8arrays": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-4.0.6.tgz", diff --git a/stacks/config.js b/stacks/config.js index 3a7c9755..be779f47 100644 --- a/stacks/config.js +++ b/stacks/config.js @@ -128,6 +128,8 @@ export function getEnv() { UPLOAD_API_DID: mustGetEnv('UPLOAD_API_DID'), AGGREGATOR_DID: mustGetEnv('AGGREGATOR_DID'), AGGREGATOR_URL: mustGetEnv('AGGREGATOR_URL'), + CONTENT_CLAIMS_DID: mustGetEnv('CONTENT_CLAIMS_DID'), + CONTENT_CLAIMS_URL: mustGetEnv('CONTENT_CLAIMS_URL'), } } diff --git a/stacks/filecoin-stack.js b/stacks/filecoin-stack.js index 277671ec..5305efbd 100644 --- a/stacks/filecoin-stack.js +++ b/stacks/filecoin-stack.js @@ -20,7 +20,7 @@ export function FilecoinStack({ stack, app }) { srcPath: 'filecoin' }) - const { AGGREGATOR_DID, AGGREGATOR_URL } = getEnv() + const { AGGREGATOR_DID, AGGREGATOR_URL, CONTENT_CLAIMS_DID, CONTENT_CLAIMS_URL } = getEnv() // Setup app monitoring with Sentry setupSentry(app, stack) @@ -40,6 +40,8 @@ export function FilecoinStack({ stack, app }) { environment: { AGGREGATOR_DID, AGGREGATOR_URL, + CONTENT_CLAIMS_DID, + CONTENT_CLAIMS_URL, }, timeout: 3 * 60, bind: [