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

Feature/indexed-db-support #44

Merged
merged 8 commits into from
Mar 20, 2023
Merged
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
13 changes: 7 additions & 6 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint",
"prettier"
],
"plugins": ["@typescript-eslint", "prettier"],
"parserOptions": {
"project": ["tsconfig.json"]
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"rules": {
"no-console": 1, // Means warning
"prettier/prettier": 2 // Means error
"no-console": 1, // Means warning
"prettier/prettier": 2, // Means error
"@typescript-eslint/no-floating-promises": ["error"]
},
"ignorePatterns": ["dist", "node_modules"]
}
1,282 changes: 933 additions & 349 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@0xpolygonid/js-sdk",
"version": "1.0.0-beta.2",
"version": "1.0.0-beta.3",
"description": "SDK to work with Polygon ID",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
@@ -62,11 +62,11 @@
"typescript": "^4.8.4"
},
"dependencies": {
"@iden3/js-crypto": "1.0.0-beta.0",
"@iden3/js-iden3-core": "1.0.0-beta.0",
"@iden3/js-jsonld-merklization": "1.0.0-beta.3",
"@iden3/js-crypto": "1.0.0-beta.1",
"@iden3/js-iden3-core": "1.0.0-beta.2",
"@iden3/js-jsonld-merklization": "1.0.0-beta.6",
"@iden3/js-jwz": "1.0.0-beta.2",
"@iden3/js-merkletree": "1.0.0-beta.0",
"@iden3/js-merkletree": "1.0.0-beta.2",
"@lumeweb/js-sha3-browser": "^0.8.1",
"ajv": "^6.12.6",
"axios": "^1.2.1",
@@ -76,6 +76,7 @@
"crypto-browserify": "^3.12.0",
"ethers": "^5.7.2",
"ffjavascript": "^0.2.57",
"idb-keyval": "^6.2.0",
"ipfs-http-client": "56.0.3",
"rfc4648": "^1.5.2",
"snarkjs": "^0.5.0",
8 changes: 6 additions & 2 deletions src/credentials/revocation.ts
Original file line number Diff line number Diff line change
@@ -272,7 +272,11 @@ export async function pushHashesToRHS(
// add new state node
if (!state.bytes.every((b) => b === 0)) {
nb.addProofNode(
new ProofNode(state, [trees.claimsTree.root, trees.revocationTree.root, trees.rootsTree.root])
new ProofNode(state, [
await trees.claimsTree.root(),
await trees.revocationTree.root(),
await trees.rootsTree.root()
])
);
}

@@ -290,7 +294,7 @@ async function addRoRNode(nb: NodesBuilder, trees: TreesModel): Promise<void> {
const currentRootsTree = trees.rootsTree;
const claimsTree = trees.claimsTree;

return nb.addKey(currentRootsTree, claimsTree.root.bigInt());
return nb.addKey(currentRootsTree, (await claimsTree.root()).bigInt());
}
async function addRevocationNode(
nb: NodesBuilder,
58 changes: 35 additions & 23 deletions src/identity/identity-wallet.ts
Original file line number Diff line number Diff line change
@@ -332,7 +332,7 @@ export class IdentityWallet implements IIdentityWallet {
);

const currentState = await hashElems([
claimsTree.root.bigInt(),
(await claimsTree.root()).bigInt(),
ZERO_HASH.bigInt(),
ZERO_HASH.bigInt()
]);
@@ -377,10 +377,11 @@ export class IdentityWallet implements IIdentityWallet {
}

const index = authClaim.hIndex();
const ctr = await claimsTree.root();

const { proof } = await claimsTree.generateProof(index, claimsTree.root);
const { proof } = await claimsTree.generateProof(index, ctr);

const claimsTreeHex = claimsTree.root.hex();
const claimsTreeHex = ctr.hex();
const stateHex = currentState.hex();

const mtpProof: Iden3SparseMerkleTreeProof = new Iden3SparseMerkleTreeProof({
@@ -466,9 +467,9 @@ export class IdentityWallet implements IIdentityWallet {
MerkleTreeType.Roots
);
const state = await hashElems([
claimsTree.root.bigInt(),
revocationTree.root.bigInt(),
rootsTree.root.bigInt()
(await claimsTree.root()).bigInt(),
(await revocationTree.root()).bigInt(),
(await rootsTree.root()).bigInt()
]);

return {
@@ -494,18 +495,21 @@ export class IdentityWallet implements IIdentityWallet {
MerkleTreeType.Claims
);

const claimsRoot = await treesModel.claimsTree.root();
const rootOfRoots = await treesModel.rootsTree.root();
const revocationRoot = await treesModel.revocationTree.root();
const { proof } = await claimsTree.generateProof(
coreClaim.hIndex(),
treeState ? treeState.claimsRoot : treesModel.claimsTree.root
treeState ? treeState.claimsRoot : claimsRoot
);

return {
proof,
treeState: treeState ?? {
state: treesModel.state,
claimsRoot: treesModel.claimsTree.root,
rootOfRoots: treesModel.rootsTree.root,
revocationRoot: treesModel.revocationTree.root
claimsRoot,
rootOfRoots,
revocationRoot
}
};
}
@@ -527,18 +531,21 @@ export class IdentityWallet implements IIdentityWallet {
MerkleTreeType.Revocations
);

const claimsRoot = await treesModel.claimsTree.root();
const rootOfRoots = await treesModel.rootsTree.root();
const revocationRoot = await treesModel.revocationTree.root();
const { proof } = await revocationTree.generateProof(
revNonce,
treeState ? treeState.revocationRoot : treesModel.revocationTree.root
treeState ? treeState.revocationRoot : revocationRoot
);

return {
proof,
treeState: treeState ?? {
state: treesModel.state,
claimsRoot: treesModel.claimsTree.root,
rootOfRoots: treesModel.rootsTree.root,
revocationRoot: treesModel.revocationTree.root
claimsRoot,
rootOfRoots,
revocationRoot
}
};
}
@@ -671,12 +678,14 @@ export class IdentityWallet implements IIdentityWallet {
issuerDID: DID
): Promise<Iden3ProofCreationResult> {
const oldIssuerTree = await this.getDIDTreeModel(issuerDID);

let claimsRoot = await oldIssuerTree.claimsTree.root();
let rootOfRoots = await oldIssuerTree.rootsTree.root();
let revocationRoot = await oldIssuerTree.revocationTree.root();
const oldTreeState: TreeState = {
revocationRoot: oldIssuerTree.revocationTree.root,
claimsRoot: oldIssuerTree.claimsTree.root,
state: oldIssuerTree.state,
rootOfRoots: oldIssuerTree.rootsTree.root
claimsRoot,
revocationRoot,
rootOfRoots
};

for (let index = 0; index < credentials.length; index++) {
@@ -698,22 +707,25 @@ export class IdentityWallet implements IIdentityWallet {
}

const newIssuerTreeState = await this.getDIDTreeModel(issuerDID);

const claimTreeRoot = await newIssuerTreeState.claimsTree.root();
await this._storage.mt.addToMerkleTree(
issuerDID.toString(),
MerkleTreeType.Roots,
newIssuerTreeState.claimsTree.root.bigInt(),
claimTreeRoot.bigInt(),
BigInt(0)
);
const newIssuerTreeStateWithROR = await this.getDIDTreeModel(issuerDID);

claimsRoot = await newIssuerTreeStateWithROR.claimsTree.root();
rootOfRoots = await newIssuerTreeStateWithROR.rootsTree.root();
revocationRoot = await newIssuerTreeStateWithROR.revocationTree.root();
return {
credentials,
newTreeState: {
revocationRoot: newIssuerTreeStateWithROR.revocationTree.root,
claimsRoot: newIssuerTreeStateWithROR.claimsTree.root,
state: newIssuerTreeStateWithROR.state,
rootOfRoots: newIssuerTreeStateWithROR.rootsTree.root
claimsRoot,
rootOfRoots,
revocationRoot
},
oldTreeState: oldTreeState
};
1 change: 1 addition & 0 deletions src/kms/store/index.ts
Original file line number Diff line number Diff line change
@@ -2,3 +2,4 @@ export * from './abstract-key-store';
export * from './memory-key-store';
export * from './types';
export * from './local-storage-key-store';
export * from './indexed-db-key-store';
46 changes: 46 additions & 0 deletions src/kms/store/indexed-db-key-store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { UseStore, createStore, get, set } from 'idb-keyval';
import { AbstractPrivateKeyStore } from './abstract-key-store';

/**
* Allows storing keys in the indexed db storage of the browser
* (NOT ENCRYPTED: DO NOT USE IN THE PRODUCTION)
*
* @export
* @beta
* @class IndexedDBPrivateKeyStore
* @implements implements AbstractPrivateKeyStore interface
*/
export class IndexedDBPrivateKeyStore implements AbstractPrivateKeyStore {
static readonly storageKey = 'keystore';
private readonly _store: UseStore;

constructor() {
this._store = createStore(
`${IndexedDBPrivateKeyStore.storageKey}-db`,
IndexedDBPrivateKeyStore.storageKey
);
}
/**
* Gets key from the indexed db storage
*
* @param {{ alias: string }} args
* @returns hex string
*/
async get(args: { alias: string }): Promise<string> {
const key = await get(args.alias, this._store);
if (!key) {
throw new Error('no key under given alias');
}
return key.value;
}

/**
* Import key to the indexed db storage
*
* @param {{ alias: string; key: string }} args - alias and private key in the hex
* @returns void
*/
async import(args: { alias: string; key: string }): Promise<void> {
await set(args.alias, { value: args.key }, this._store);
}
}
9 changes: 6 additions & 3 deletions src/proof/proof-service.ts
Original file line number Diff line number Diff line change
@@ -203,12 +203,15 @@ export class ProofService implements IProofService {
const authInfo = await this.prepareAuthBJJCredential(did, oldTreeState);

const newTreeModel = await this._identityWallet.getDIDTreeModel(did);
const claimsRoot = await newTreeModel.claimsTree.root();
const rootOfRoots = await newTreeModel.rootsTree.root();
const revocationRoot = await newTreeModel.revocationTree.root();

const newTreeState: TreeState = {
revocationRoot: newTreeModel.revocationTree.root,
claimsRoot: newTreeModel.claimsTree.root,
revocationRoot,
claimsRoot,
state: newTreeModel.state,
rootOfRoots: newTreeModel.rootsTree.root
rootOfRoots
};
const challenge = Poseidon.hash([oldTreeState.state.bigInt(), newTreeState.state.bigInt()]);

4 changes: 2 additions & 2 deletions src/schema-processor/json/parser.ts
Original file line number Diff line number Diff line change
@@ -142,12 +142,12 @@ export class Parser {
switch (opts.merklizedRootPosition) {
case MerklizedRootPosition.Index: {
const mk = await credential.merklize();
claim.setIndexMerklizedRoot(mk.root().bigInt());
claim.setIndexMerklizedRoot((await mk.root()).bigInt());
break;
}
case MerklizedRootPosition.Value: {
const mk = await credential.merklize();
claim.setValueMerklizedRoot(mk.root().bigInt());
claim.setValueMerklizedRoot((await mk.root()).bigInt());
break;
}
case MerklizedRootPosition.None:
1 change: 1 addition & 0 deletions src/storage/index.ts
Original file line number Diff line number Diff line change
@@ -4,4 +4,5 @@ export * from './entities';
export * from './filters';
export * from './memory';
export * from './local-storage';
export * from './indexed-db';
export * from './shared';
60 changes: 60 additions & 0 deletions src/storage/indexed-db/data-source.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { IDataSource } from '../interfaces/data-source';
import { set, get, del, values, createStore, UseStore } from 'idb-keyval';

/**
* Storage in the browser, uses indexed db storage
*
* @export
* @beta
* @class IndexedDBDataSource
* @template Type
*/
export class IndexedDBDataSource<Type> implements IDataSource<Type> {
/**
* Creates an instance of IndexedDBDataSource.
*
* @param {string} _storageKey - key string to put storage name
*/
private readonly _store: UseStore;
constructor(private _storageKey: string) {
this._store = createStore(`${_storageKey}-db`, _storageKey);
}

/**
* Saves value to the indexed db storage
*
* @param {string} key - key value
* @param {Type} value - value to store
* @param {string} [keyName='id'] - key name
*/
async save(key: string, value: Type, keyName = 'id'): Promise<void> {
return set(key, value, this._store);
}

/**
* Gets value from the indexed db storage by given key
*
* @param {string} key - key value
* @param {string} [keyName='id'] - key name
*/

async get(key: string, keyName = 'id'): Promise<Type | undefined> {
return get(key, this._store);
}

/**
* loads all from the indexed db storage
*/
async load(): Promise<Type[]> {
return values(this._store);
}
/**
* deletes item from the indexed db storage
* @param {string} key - key value
* @param {string} [keyName='id'] - key name
*/
async delete(key: string, keyName = 'id'): Promise<void> {
return del(key, this._store);
}
}
2 changes: 2 additions & 0 deletions src/storage/indexed-db/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './data-source';
export * from './merkletree';
Loading