Skip to content

Commit

Permalink
Increased max Verifiable Credential size in Compose DB (#32)
Browse files Browse the repository at this point in the history
* move ceramic npm-scripts into programmatically call-script file

* hotfix

* add migrations between composites

* prevent duplicates

* hotfix

* upd manifest, fix vc tests

* fix hardcoded definition, prevent duplicates from store migration

* bump v

* reduce store and old ceramic vcs

* update changelog & bump v

* add npmignore

* add description for ceramic-prepare-vc script

* Apply suggestions from code review

* Apply suggestions from code review

---------

Co-authored-by: Ihor Diachenko <[email protected]>
  • Loading branch information
lukachi and ihordiachenko authored Feb 1, 2024
1 parent dd691a7 commit fff3e19
Show file tree
Hide file tree
Showing 17 changed files with 214 additions and 60 deletions.
11 changes: 9 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.0.2] - 2024-02-01
### Added
- `@rarimo/rarime`:
- Migration to a Compose DB model with increased Verifiable Credential size;
- Compose DB model preparation script;

## [2.0.1] - 2024-01-24
### Changed
- `@rarimo/rarime-connector` - set strict snap version requirement
Expand Down Expand Up @@ -150,8 +156,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Implemented `@rarimo/rarime-connector` and `@rarimo/rarime` packages

[Unreleased]: https://github.com/rarimo/rarime/compare/2.0.1...HEAD
[2.0.0]: https://github.com/rarimo/rarime/compare/2.0.0...2.0.1
[Unreleased]: https://github.com/rarimo/rarime/compare/2.0.2...HEAD
[2.0.2]: https://github.com/rarimo/rarime/compare/2.0.1...2.0.2
[2.0.1]: https://github.com/rarimo/rarime/compare/2.0.0...2.0.1
[2.0.0]: https://github.com/rarimo/rarime/compare/1.0.2...2.0.0
[1.0.2]: https://github.com/rarimo/rarime/compare/1.0.1...1.0.2
[1.0.1]: https://github.com/rarimo/rarime/compare/1.0.0...1.0.1
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@typescript-eslint/eslint-plugin": "5.33.0",
"@typescript-eslint/parser": "5.33.0",
"chalk": "4.1.2",
"dotenv": "^16.4.1",
"eslint": "8.21.0",
"eslint-config-prettier": "8.1.0",
"eslint-plugin-import": "2.26.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/connector/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rarimo/rarime-connector",
"version": "2.0.1",
"version": "2.0.2",
"description": "Facilitates interaction between a DApp and RariMe MetaMask snap",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion packages/connector/src/version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "2.0.1"
"version": "2.0.2"
}
2 changes: 1 addition & 1 deletion packages/site/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "site",
"version": "2.0.1",
"version": "2.0.2",
"private": true,
"license": "(MIT-0 OR Apache-2.0)",
"scripts": {
Expand Down
1 change: 1 addition & 0 deletions packages/snap/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ceramic-prepare-vc.mjs
70 changes: 70 additions & 0 deletions packages/snap/ceramic-prepare-vc.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* @name ceramic-prepare-vc
* @description Create composite from graphql model,
* deploy and compile json files
*
* https://developers.ceramic.network/docs/composedb/create-your-composite
*/

import path from 'path';
import fs from 'fs';

import { fileURLToPath } from 'url';
import npm from 'npm-commands';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// http://0.0.0.0:7007 || https://ceramic.rarimo.com
const ceramicUrl = process.env.CERAMIC_URL;
const didPK = process.env.DID_PRIVATE_KEY

// Directory path
const modelsDirPath = './ceramic/models';

// Reading directory contents
fs.readdir(modelsDirPath, async (err, files) => {
if (err) {
console.error('Error reading directory:', err);
return;
}

for (const file of files) {
if (fs.statSync(path.join(modelsDirPath, file)).isFile()) {
console.log('\n\n==========================================================\n\n');
console.log('PREPARE VC FOR:', file);

const modelFile = path.join(
__dirname,
`./ceramic/models/${file}`,
);

const modelFileName = path.basename(`./ceramic/models/${modelFile}`, '.graphql');

const compositeOutput = path.join(
__dirname,
`./ceramic/composites/${modelFileName}.json`,
);

const runtimeOutput = path.join(
__dirname,
`./ceramic/composites/${modelFileName}-runtime.json`,
);

await npm().arguments({
['ceramic-url']: ceramicUrl,
['output']: compositeOutput,
['did-private-key']: didPK,
}).runAsync(`composedb composite:create ${modelFile}`);

await npm().arguments({
['ceramic-url']: ceramicUrl,
['did-private-key']: didPK,
}).runAsync(`composedb composite:deploy ${compositeOutput}`);

await npm().arguments({
['ceramic-url']: ceramicUrl,
}).runAsync(`composedb composite:compile ${compositeOutput} ${runtimeOutput}`);
}
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"models":{"VerifiableCredential":{"interface":false,"implements":[],"id":"kjzl6hvfrbw6c5j1vrqei8a3h06om20x4qj8fj84ku46oew5b0yv9h6gyzwd2t4","accountRelation":{"type":"list"}}},"objects":{"VerifiableCredential":{"data":{"type":"string","required":true},"claimId":{"type":"string","required":true,"indexed":true},"ownerDid":{"type":"string","required":true,"indexed":true},"queryHash":{"type":"string","required":true,"indexed":true}}},"enums":{},"accountData":{"verifiableCredentialList":{"type":"connection","name":"VerifiableCredential"}}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":"1.1","models":{"kjzl6hvfrbw6c5j1vrqei8a3h06om20x4qj8fj84ku46oew5b0yv9h6gyzwd2t4":[{"jws":{"payload":"AXESIJ3BF8Q_1bYO8VuaK8GI5BbkQmxJ73zD-xykLspGo9pz","signatures":[{"signature":"vIKvgfCZ3ZdZAiiZtbViRwtGhK4yniFhsf9lbxTyg1LTY6K7699bdieQoggcYTWs_KoP19xU95gy5JNu7yQOCg","protected":"eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa2o2Tmt2Q1I0R0ZGU0pwWkxkNnZZb2FZVlJGTWtIcW1oVGd5MUhuTDVQSjJiI3o2TWtqNk5rdkNSNEdGRlNKcFpMZDZ2WW9hWVZSRk1rSHFtaFRneTFIbkw1UEoyYiJ9"}],"link":"bafyreie5yel4ip6vwyhpcw42fpayrzaw4rbgysppptb7whfef3feni62om"},"linkedBlock":"omRkYXRhqWRuYW1ldFZlcmlmaWFibGVDcmVkZW50aWFsZXZpZXdzoGZzY2hlbWGlZHR5cGVmb2JqZWN0ZyRzY2hlbWF4LGh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMjAtMTIvc2NoZW1haHJlcXVpcmVkhGhvd25lckRpZGRkYXRhaXF1ZXJ5SGFzaGdjbGFpbUlkanByb3BlcnRpZXOkZGRhdGGiZHR5cGVmc3RyaW5naW1heExlbmd0aBoAD0JAZ2NsYWltSWSiZHR5cGVmc3RyaW5naW1heExlbmd0aBkH0Ghvd25lckRpZKJkdHlwZWZzdHJpbmdpbWF4TGVuZ3RoGQfQaXF1ZXJ5SGFzaKJkdHlwZWZzdHJpbmdpbWF4TGVuZ3RoGQfQdGFkZGl0aW9uYWxQcm9wZXJ0aWVz9Gd2ZXJzaW9uYzIuMGlpbnRlcmZhY2X0aXJlbGF0aW9uc6BqaW1wbGVtZW50c4BrZGVzY3JpcHRpb254NEEgbW9kZWwgZm9yIHN0b3JpbmcgZW5jcnlwdGVkIHZlcmlmaWFibGUgY3JlZGVudGlhbHNvYWNjb3VudFJlbGF0aW9uoWR0eXBlZGxpc3RmaGVhZGVyo2NzZXBlbW9kZWxlbW9kZWxSzgEEAXFxCwAJaG1vZGVsLXYxa2NvbnRyb2xsZXJzgXg4ZGlkOmtleTp6Nk1rajZOa3ZDUjRHRkZTSnBaTGQ2dllvYVlWUkZNa0hxbWhUZ3kxSG5MNVBKMmI="}]},"indices":{"kjzl6hvfrbw6c5j1vrqei8a3h06om20x4qj8fj84ku46oew5b0yv9h6gyzwd2t4":[{"fields":[{"path":["queryHash"]}]},{"fields":[{"path":["claimId"]}]},{"fields":[{"path":["ownerDid"]}]}]},"aliases":{"kjzl6hvfrbw6c5j1vrqei8a3h06om20x4qj8fj84ku46oew5b0yv9h6gyzwd2t4":"VerifiableCredential"},"views":{"account":{},"root":{},"models":{"kjzl6hvfrbw6c5j1vrqei8a3h06om20x4qj8fj84ku46oew5b0yv9h6gyzwd2t4":{}}},"commonEmbeds":[]}
13 changes: 13 additions & 0 deletions packages/snap/ceramic/models/VerifiableCredentialsV2.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type VerifiableCredential @createModel(
description: "A model for storing encrypted verifiable credentials",
accountRelation: LIST
)
@createIndex(fields: [{ path: "queryHash" }])
@createIndex(fields: [{ path: "claimId" }])
@createIndex(fields: [{ path: "ownerDid" }])
{
ownerDid: String! @string(maxLength: 2000)
data: String! @string(maxLength: 1000000)
queryHash: String! @string(maxLength: 2000)
claimId: String! @string(maxLength: 2000)
}
13 changes: 6 additions & 7 deletions packages/snap/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rarimo/rarime",
"version": "2.0.1",
"version": "2.0.2",
"description": "RariMe is a MetaMask Snap that safely holds any of your credentials and allows you to prove your identity without revealing any personal data. Powered by Rarimo Protocol and Zero-Knowledge Proof technology.",
"repository": {
"type": "git",
Expand Down Expand Up @@ -34,11 +34,9 @@
"generate-ether-types": "typechain --target=ethers-v5 'abis/**/*.json' --out-dir src/types/contracts",
"prepublishOnly": "yarn && yarn build",
"preversion": "yarn && yarn build && git add snap.manifest.json",
"ceramic:create-vc": "composedb composite:create ./ceramic/models/VerifiableCredentials.graphql --ceramic-url=$CERAMIC_URL --output=./ceramic/composites/VerifiableCredentials.json --did-private-key=$DID_PRIVATE_KEY",
"ceramic:deploy-vc": "composedb composite:deploy ./ceramic/composites/VerifiableCredentials.json --ceramic-url=$CERAMIC_URL --did-private-key=$DID_PRIVATE_KEY",
"ceramic:compile-vc": "composedb composite:compile ./ceramic/composites/VerifiableCredentials.json --ceramic-url=$CERAMIC_URL ./ceramic/composites/VerifiableCredentials-runtime.json",
"ceramic:prepare-vc": "yarn ceramic:create-vc && yarn ceramic:deploy-vc && yarn ceramic:compile-vc",
"ceramic:graphql-server": "composedb graphql:server --ceramic-url=$CERAMIC_URL --graphiql ./ceramic/composites/VerifiableCredentials-runtime.json --did-private-key=$DID_PRIVATE_KEY --port=5005",
"composedb": "composedb",
"ceramic:prepare-vc": "node ceramic-prepare-vc.mjs",
"ceramic:graphql-server": "composedb graphql:server --ceramic-url=$CERAMIC_URL --graphiql ./ceramic/composites/VerifiableCredentialsV2-runtime.json --did-private-key=$DID_PRIVATE_KEY --port=5005",
"generate-graphql-types": "graphql-codegen --config ./codegen.ts"
},
"dependencies": {
Expand All @@ -58,7 +56,7 @@
"@metamask/snaps-jest": "^4.0.0",
"@metamask/snaps-sdk": "^1.1.0",
"@metamask/snaps-utils": "^4.0.0",
"@rarimo/rarime-connector": "2.0.1",
"@rarimo/rarime-connector": "2.0.2",
"buffer": "6.0.3",
"dids": "4.0.4",
"ethers": "5.7.2",
Expand Down Expand Up @@ -101,6 +99,7 @@
"eslint-plugin-prettier": "4.2.1",
"node-stdlib-browser": "1.2.0",
"nodemon": "2.0.20",
"npm-commands": "^1.2.1",
"prettier": "2.2.1",
"rimraf": "3.0.2",
"typechain": "8.3.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/snap/snap.manifest.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"version": "2.0.1",
"version": "2.0.2",
"description": "Securely store and manage all of your identity credentials. Use them across chains with ZK-protected privacy guarantees.",
"proposedName": "RariMe",
"repository": {
"type": "git",
"url": "https://github.com/rarimo/rarime.git"
},
"source": {
"shasum": "vhP1WB7B+rqWRe/XbXFHZSQZ49QZzxDs9tHx0joslpU=",
"shasum": "i0ljRZ0cephpKn1+G77icrHnm0Gh4soRcJ9b6xpQaXA=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
26 changes: 16 additions & 10 deletions packages/snap/src/helpers/ceramic-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,28 @@ import { Hex } from '@iden3/js-crypto';
import { ComposeClient } from '@composedb/client';
import type { RuntimeCompositeDefinition } from '@composedb/types';
import { CERAMIC_URL } from '../config';
import VerifiableRuntimeComposite from '../../ceramic/composites/VerifiableCredentials-runtime.json';

export class CeramicProvider {
private readonly pkHex: string;

private readonly serverURL?: string;
private _compose: ComposeClient;

private _compose = new ComposeClient({
ceramic: CERAMIC_URL,
definition: VerifiableRuntimeComposite as RuntimeCompositeDefinition,
...(this.serverURL && { serverURL: this.serverURL }),
});

constructor(pkHex: string, serverURL?: string) {
constructor(pkHex: string, composeClient: ComposeClient) {
this.pkHex = pkHex;
this.serverURL = serverURL;
this._compose = composeClient;
}

public static create(
pkHex: string,
opts: { definition: object; serverURL?: string },
) {
const composeClient = new ComposeClient({
ceramic: CERAMIC_URL,
definition: opts.definition as RuntimeCompositeDefinition,
...(opts.serverURL && { serverURL: opts.serverURL }),
});

return new CeramicProvider(pkHex, composeClient);
}

async auth() {
Expand Down
67 changes: 53 additions & 14 deletions packages/snap/src/helpers/credential-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import {
GetVerifiableCredentialsByClaimIdAndQueryHash,
} from '../types';
import { getItemFromStore, setItemInStore } from '../rpc';
import VerifiableRuntimeCompositeV2 from '../../ceramic/composites/VerifiableCredentialsV2-runtime.json';
import VerifiableRuntimeComposite from '../../ceramic/composites/VerifiableCredentials-runtime.json';
import { getCoreClaimFromProof } from './proof-helpers';
import { CeramicProvider } from './ceramic-helpers';

Expand Down Expand Up @@ -105,8 +107,8 @@ const loadAllCredentialsListPages = async <
};

export const getAuthenticatedCeramicProvider = async (
opts: { definition: object; serverURL?: string },
pkHex?: string,
serverURL?: string,
) => {
let privateKeyHex = pkHex ?? '';

Expand All @@ -120,7 +122,10 @@ export const getAuthenticatedCeramicProvider = async (
privateKeyHex = identityStorage.privateKeyHex;
}

const ceramicProvider = new CeramicProvider(privateKeyHex, serverURL);
const ceramicProvider = CeramicProvider.create(privateKeyHex, {
...(opts.serverURL && { serverURL: opts.serverURL }),
definition: opts.definition,
});

await ceramicProvider.auth();

Expand All @@ -137,7 +142,11 @@ export class VCManager {
this.saltedEntropy = saltedEntropy;
}

static async create(pkHex?: string, serverURL?: string) {
static async create(opts?: {
pkHex?: string;
definition?: object;
serverURL?: string;
}) {
/**
* Add some account-specific entropy to the input,
* additional entropy will prevent someone from counting
Expand All @@ -154,8 +163,16 @@ export class VCManager {
? entropy.substring(2)
: entropy;

const definition = opts?.definition ?? VerifiableRuntimeCompositeV2;

return new VCManager(
await getAuthenticatedCeramicProvider(pkHex, serverURL),
await getAuthenticatedCeramicProvider(
{
...(opts?.serverURL && { serverURL: opts.serverURL }),
definition,
},
opts?.pkHex,
),
saltedEntropy,
);
}
Expand Down Expand Up @@ -472,19 +489,41 @@ export class VCManager {
}
}

export const moveStoreVCtoCeramic = async () => {
const credentials = (await getItemFromStore(StorageKeys.credentials)) || [];
export const migrateVCsToLastCeramicModel = async () => {
const targetVcManager = await VCManager.create();

const vcManager = await VCManager.create();
const targetVcs = await targetVcManager.getAllDecryptedVCs();

if (credentials.length) {
await Promise.all(
credentials.map(async (credential: W3CCredential) => {
await vcManager.encryptAndSaveVC(credential);
}),
);
await setItemInStore(StorageKeys.credentials, []);
if (targetVcs.length) {
return;
}

const storeCredentials: W3CCredential[] =
(await getItemFromStore(StorageKeys.credentials)) || [];

await Promise.all(
[VerifiableRuntimeComposite].map(async (definition) => {
const vcManager = await VCManager.create({
definition,
});

const ceramicVCs = await vcManager.getAllDecryptedVCs();

const vcs = [...storeCredentials, ...ceramicVCs].reduce((acc, vc) => {
const isVcExist = Boolean(acc.find((el) => el.id === vc.id));

return [...acc, ...(isVcExist ? [] : [vc])];
}, [] as W3CCredential[]);

await Promise.all(
vcs.map(async (vc) => {
await targetVcManager.encryptAndSaveVC(vc);
}),
);

await setItemInStore(StorageKeys.credentials, []);
}),
);
};

export const getRevocationStatus = async (
Expand Down
10 changes: 5 additions & 5 deletions packages/snap/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
getProviderChainInfo,
getRarimoCoreUrl,
loadDataFromRarimoCore,
moveStoreVCtoCeramic,
migrateVCsToLastCeramicModel,
parseDidV2,
VCManager,
} from './helpers';
Expand All @@ -45,7 +45,7 @@ export const onRpcRequest = async ({
origin: string;
}) => {
if (request.method !== RPCMethods.CreateIdentity) {
await moveStoreVCtoCeramic();
await migrateVCsToLastCeramicModel();
}

switch (request.method) {
Expand All @@ -60,7 +60,7 @@ export const onRpcRequest = async ({
proofRequest,
} = request.params as CheckCredentialExistenceRequestParams;

const vcManager = await VCManager.create(identityStorage.privateKeyHex);
const vcManager = await VCManager.create();

let result: SaveCredentialsResponse[] = [];

Expand Down Expand Up @@ -129,7 +129,7 @@ export const onRpcRequest = async ({
});

if (res) {
const vcManager = await VCManager.create(identityStorage.privateKeyHex);
const vcManager = await VCManager.create();

const identity = await Identity.create(identityStorage.privateKeyHex);

Expand Down Expand Up @@ -242,7 +242,7 @@ export const onRpcRequest = async ({
throw new Error('Account address is required');
}

const vcManager = await VCManager.create(identityStorage.privateKeyHex);
const vcManager = await VCManager.create();

const credentials = (
await vcManager.getDecryptedVCsByQuery(query, issuerDid)
Expand Down
Loading

0 comments on commit fff3e19

Please sign in to comment.