Skip to content

Commit

Permalink
ability to replace auth bjj with another status (#264)
Browse files Browse the repository at this point in the history
* add logic for removal of the credential with another status

* add possibility to disable publishing of the genesis state
  • Loading branch information
vmidyllic authored and volodymyr-basiuk committed Sep 19, 2024
1 parent 189e973 commit 936acba
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 35 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@0xpolygonid/js-sdk",
"version": "1.18.3",
"version": "1.18.4",
"description": "SDK to work with Polygon ID",
"main": "dist/node/cjs/index.js",
"module": "dist/node/esm/index.js",
Expand Down
68 changes: 38 additions & 30 deletions src/identity/identity-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,19 @@ export type IdentityCreationOptions = {
/**
* Options for creating Auth BJJ credential
* seed - seed to generate BJJ key pair
* revocationOpts -
* revocationOpts
* nonce - explicit revocation nonce to use
* onChain - onchain status related option
* txCallback - defines how the TransactionReceipt is handled
* publishMode - specifies the work of transaction polling type: sync / async / callback
* genesisPublishingDisabled - genesis is publishing by default. Set `true` to prevent genesis publishing
*/
export type AuthBJJCredentialCreationOptions = {
revocationOpts: {
id: string;
type: CredentialStatusType;
nonce?: number;
genesisPublishingDisabled?: boolean;
onChain?: {
txCallback?: (tx: TransactionReceipt) => Promise<void>;
publishMode?: PublishMode;
Expand Down Expand Up @@ -661,13 +667,24 @@ export class IdentityWallet implements IIdentityWallet {
allowedIssuers: [did.string()]
});

if (credentials.length) {
// if credential exists with the same credential status type we return this credential
if (
credentials.length === 1 &&
credentials[0].credentialStatus.type === opts.revocationOpts.type
) {
return {
did,
credential: credentials[0]
};
}

// otherwise something is already wrong with storage as it has more than 1 credential in it or credential status type of existing credential is different from what user provides - We should remove everything and create new credential.
// in this way credential status of auth credential can be upgraded
for (let i = 0; i < credentials.length; i++) {
await this._credentialWallet.remove(credentials[i].id);
}

// otherwise we create a new credential
const credential = await this.createAuthBJJCredential(
did,
pubKey,
Expand Down Expand Up @@ -695,10 +712,13 @@ export class IdentityWallet implements IIdentityWallet {

credential.proof = [mtpProof];

await this.publishRevocationInfoByCredentialStatusType(did, opts.revocationOpts.type, {
rhsUrl: opts.revocationOpts.id,
onChain: opts.revocationOpts.onChain
});
// only if user specified that genesis state publishing is not needed we won't do this.
if (!opts.revocationOpts.genesisPublishingDisabled) {
await this.publishRevocationInfoByCredentialStatusType(did, opts.revocationOpts.type, {
rhsUrl: opts.revocationOpts.id,
onChain: opts.revocationOpts.onChain
});
}

await this._credentialWallet.save(credential);

Expand Down Expand Up @@ -1248,30 +1268,18 @@ export class IdentityWallet implements IIdentityWallet {
}

let nodes: ProofNode[] = [];
if (opts?.treeModel) {
nodes = await getNodesRepresentation(
opts.revokedNonces,
{
revocationTree: opts.treeModel.revocationTree,
claimsTree: opts.treeModel.claimsTree,
state: opts.treeModel.state,
rootsTree: opts.treeModel.rootsTree
},
opts.treeModel.state
);
} else {
const treeState = await this.getDIDTreeModel(issuerDID);
nodes = await getNodesRepresentation(
opts?.revokedNonces,
{
revocationTree: treeState.revocationTree,
claimsTree: treeState.claimsTree,
state: treeState.state,
rootsTree: treeState.rootsTree
},
treeState.state
);
}

const tree = opts?.treeModel ?? (await this.getDIDTreeModel(issuerDID));
nodes = await getNodesRepresentation(
opts?.revokedNonces ?? [],
{
revocationTree: tree.revocationTree,
claimsTree: tree.claimsTree,
state: tree.state,
rootsTree: tree.rootsTree
},
tree.state
);

if (!nodes.length) {
return;
Expand Down
56 changes: 54 additions & 2 deletions tests/identity/id.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
NativeProver,
Iden3SparseMerkleTreeProof,
BJJSignatureProof2021,
TreeState
TreeState,
IdentityCreationOptions
} from '../../src';
import {
MOCK_STATE_STORAGE,
Expand All @@ -26,7 +27,8 @@ import {
registerKeyProvidersInMemoryKMS,
WALLET_KEY,
createEthereumBasedIdentity,
SEED_ISSUER
SEED_ISSUER,
RHS_CONTRACT_ADDRESS
} from '../helpers';
import { expect } from 'chai';
import { Wallet } from 'ethers';
Expand Down Expand Up @@ -397,4 +399,54 @@ describe('identity', () => {
expect(credential).to.be.deep.eq(restoredCredential);
expect(did.string()).to.be.eq(restoredDid.string());
});

it('replace auth bjj credential', async () => {
const idRequest: IdentityCreationOptions = {
method: DidMethod.Iden3,
blockchain: Blockchain.Polygon,
networkId: NetworkId.Amoy,
seed: SEED_ISSUER,
revocationOpts: {
type: CredentialStatusType.Iden3ReverseSparseMerkleTreeProof,
id: RHS_URL
}
};
const { did, credential } = await idWallet.createIdentity(idRequest);
expect(did.string()).to.equal(expectedDID);

let credentials = await credWallet.findByQuery({
credentialSubject: {
x: {
$eq: credential.credentialSubject['x']
},
y: {
$eq: credential.credentialSubject['y']
}
}
});
expect(credentials.length).to.be.equal(1);

idRequest.revocationOpts.type = CredentialStatusType.Iden3OnchainSparseMerkleTreeProof2023;
idRequest.revocationOpts.id = RHS_CONTRACT_ADDRESS;
idRequest.revocationOpts.genesisPublishingDisabled = true;

const { did: did2, credential: credential2 } = await idWallet.createIdentity(idRequest);
expect(did2.string()).to.equal(expectedDID);
expect(credential2.credentialStatus.type).to.be.equal(
CredentialStatusType.Iden3OnchainSparseMerkleTreeProof2023
);
expect(credential2.credentialStatus.id).to.contain('state');

credentials = await credWallet.findByQuery({
credentialSubject: {
x: {
$eq: credential2.credentialSubject['x']
},
y: {
$eq: credential2.credentialSubject['y']
}
}
});
expect(credentials.length).to.be.equal(1);
});
});

0 comments on commit 936acba

Please sign in to comment.