Skip to content

Commit fbe6187

Browse files
Merge pull request #249 from 0xPolygonID/fix/create-eth-id-no-bjj
fix error thrown if createBjjCredential is false and no ethSigner provided
2 parents d78c3b5 + 7626cc8 commit fbe6187

13 files changed

+205
-8
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@0xpolygonid/js-sdk",
3-
"version": "1.17.0",
3+
"version": "1.17.1",
44
"description": "SDK to work with Polygon ID",
55
"main": "dist/node/cjs/index.js",
66
"module": "dist/node/esm/index.js",

src/identity/identity-wallet.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ export class IdentityWallet implements IIdentityWallet {
720720
let credential;
721721
const ethSigner = opts.ethSigner;
722722

723-
if (!ethSigner) {
723+
if (opts.createBjjCredential && !ethSigner) {
724724
throw new Error(
725725
'Ethereum signer is required to create Ethereum identities in order to transit state'
726726
);
@@ -747,7 +747,7 @@ export class IdentityWallet implements IIdentityWallet {
747747
isStateGenesis: true
748748
});
749749

750-
if (opts.createBjjCredential) {
750+
if (opts.createBjjCredential && ethSigner) {
751751
// Old tree state genesis state
752752
const oldTreeState: TreeState = {
753753
revocationRoot: ZERO_HASH,
@@ -1489,6 +1489,13 @@ export class IdentityWallet implements IIdentityWallet {
14891489
);
14901490
await this._credentialWallet.saveAll(credsWithIden3MTPProof);
14911491

1492+
await this._storage.identity.saveIdentity({
1493+
did: did.string(),
1494+
state: currentState,
1495+
isStatePublished: true,
1496+
isStateGenesis: false
1497+
});
1498+
14921499
const credRefreshed = await this._credentialWallet.findById(credential.id);
14931500
if (!credRefreshed) {
14941501
throw new Error('Credential not found in credential wallet');

src/kms/key-providers/bjj-provider.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@ export class BjjProvider implements IKeyProvider {
3131
this.keyType = keyType;
3232
this.keyStore = keyStore;
3333
}
34+
/**
35+
* get all keys
36+
* @returns list of keys
37+
*/
38+
async list(): Promise<
39+
{
40+
alias: string;
41+
key: string;
42+
}[]
43+
> {
44+
const allKeysFromKeyStore = await this.keyStore.list();
45+
return allKeysFromKeyStore.filter((key) => key.alias.startsWith(this.keyType));
46+
}
47+
3448
/**
3549
* generates a baby jub jub key from a seed phrase
3650
* @param {Uint8Array} seed - byte array seed

src/kms/key-providers/ed25519-provider.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ export class Ed25519Provider implements IKeyProvider {
2121
private readonly _keyStore: AbstractPrivateKeyStore
2222
) {}
2323

24+
/**
25+
* get all keys
26+
* @returns list of keys
27+
*/
28+
async list(): Promise<
29+
{
30+
alias: string;
31+
key: string;
32+
}[]
33+
> {
34+
const allKeysFromKeyStore = await this._keyStore.list();
35+
return allKeysFromKeyStore.filter((key) => key.alias.startsWith(this.keyType));
36+
}
37+
2438
/**
2539
* generates a ed25519 key from a seed phrase
2640
* @param {Uint8Array} seed - byte array seed

src/kms/key-providers/secp256k1-provider.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@ export class Sec256k1Provider implements IKeyProvider {
3232
this.keyType = keyType;
3333
this._keyStore = keyStore;
3434
}
35+
36+
/**
37+
* get all keys
38+
* @returns list of keys
39+
*/
40+
async list(): Promise<
41+
{
42+
alias: string;
43+
key: string;
44+
}[]
45+
> {
46+
const allKeysFromKeyStore = await this._keyStore.list();
47+
return allKeysFromKeyStore.filter((key) => key.alias.startsWith(this.keyType));
48+
}
49+
3550
/**
3651
* generates a baby jub jub key from a seed phrase
3752
* @param {Uint8Array} seed - byte array seed

src/kms/kms.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@ export interface IKeyProvider {
1313
* @type {KmsKeyType}
1414
*/
1515
keyType: KmsKeyType;
16+
17+
/**
18+
* get all keys
19+
*
20+
* @returns list of keys
21+
*/
22+
list(): Promise<
23+
{
24+
alias: string;
25+
key: string;
26+
}[]
27+
>;
1628
/**
1729
* gets public key by key id
1830
*
@@ -138,4 +150,24 @@ export class KMS {
138150
}
139151
return keyProvider.verify(data, signatureHex, keyId);
140152
}
153+
154+
/**
155+
* get all keys by key type
156+
*
157+
* @param keyType - Key type
158+
* @returns list of keys
159+
*/
160+
list(keyType: KmsKeyType): Promise<
161+
{
162+
alias: string;
163+
key: string;
164+
}[]
165+
> {
166+
const keyProvider = this._registry.get(keyType);
167+
if (!keyProvider) {
168+
throw new Error(`keyProvider not found for: ${keyType}`);
169+
}
170+
171+
return keyProvider.list();
172+
}
141173
}

src/kms/store/abstract-key-store.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,12 @@ export abstract class AbstractPrivateKeyStore {
2323
* @returns `Promise<string>`
2424
*/
2525
abstract get(args: { alias: string }): Promise<string>;
26+
27+
/**
28+
* get all keys
29+
*
30+
* @abstract
31+
* @returns `Promise<{ alias: string; key: string }[]>`
32+
*/
33+
abstract list(): Promise<{ alias: string; key: string }[]>;
2634
}

src/kms/store/indexed-db-key-store.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { UseStore, createStore, get, set } from 'idb-keyval';
1+
import { UseStore, createStore, get, set, entries } from 'idb-keyval';
22
import { AbstractPrivateKeyStore } from './abstract-key-store';
33

44
/**
@@ -19,6 +19,21 @@ export class IndexedDBPrivateKeyStore implements AbstractPrivateKeyStore {
1919
IndexedDBPrivateKeyStore.storageKey
2020
);
2121
}
22+
23+
/**
24+
* get all keys
25+
*
26+
* @abstract
27+
* @returns `Promise<{ alias: string; key: string }[]>`
28+
*/
29+
async list(): Promise<{ alias: string; key: string }[]> {
30+
const allEntries = await entries(this._store);
31+
return allEntries.map(([alias, key]) => ({ alias, key: key.value })) as unknown as {
32+
alias: string;
33+
key: string;
34+
}[];
35+
}
36+
2237
/**
2338
* Gets key from the indexed db storage
2439
*

src/kms/store/local-storage-key-store.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,21 @@ import { KmsKeyId } from './types';
1111
*/
1212
export class LocalStoragePrivateKeyStore implements AbstractPrivateKeyStore {
1313
static readonly storageKey = 'keystore';
14+
15+
/**
16+
* get all keys
17+
*
18+
* @abstract
19+
* @returns `Promise<{ alias: string; key: string }[]>`
20+
*/
21+
list(): Promise<{ alias: string; key: string }[]> {
22+
const dataStr = localStorage.getItem(LocalStoragePrivateKeyStore.storageKey);
23+
if (!dataStr) {
24+
throw new Error('no key under given alias');
25+
}
26+
const data = JSON.parse(dataStr);
27+
return data.map((i: { id: string; value: string }) => ({ alias: i.id, key: i.value }));
28+
}
1429
/**
1530
* Gets key from the local storage
1631
*

src/kms/store/memory-key-store.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ export class InMemoryPrivateKeyStore implements AbstractPrivateKeyStore {
1212
constructor() {
1313
this._data = new Map<string, string>();
1414
}
15+
list(): Promise<{ alias: string; key: string }[]> {
16+
return Promise.resolve(Array.from(this._data).map(([alias, key]) => ({ alias, key })));
17+
}
1518
async get(args: { alias: string }): Promise<string> {
1619
const privateKey = this._data.get(args.alias);
1720
if (!privateKey) {

tests/identity/id.test.ts

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {
1414
FSCircuitStorage,
1515
NativeProver,
1616
Iden3SparseMerkleTreeProof,
17-
BJJSignatureProof2021
17+
BJJSignatureProof2021,
18+
TreeState
1819
} from '../../src';
1920
import {
2021
MOCK_STATE_STORAGE,
@@ -24,11 +25,14 @@ import {
2425
getInMemoryDataStorage,
2526
registerKeyProvidersInMemoryKMS,
2627
WALLET_KEY,
27-
createEthereumBasedIdentity
28+
createEthereumBasedIdentity,
29+
SEED_ISSUER
2830
} from '../helpers';
2931
import { expect } from 'chai';
3032
import { Wallet } from 'ethers';
3133
import { getRandomBytes } from '@iden3/js-crypto';
34+
import { Blockchain, DidMethod, NetworkId } from '@iden3/js-iden3-core';
35+
import { ZERO_HASH } from '@iden3/js-merkletree';
3236

3337
describe('identity', () => {
3438
let credWallet: ICredentialWallet;
@@ -192,6 +196,68 @@ describe('identity', () => {
192196
expect((await claimsTree.root()).bigInt()).not.to.equal(0);
193197
});
194198

199+
it('createIdentity Secp256k1 w/o auth bjj cred and add after creation', async () => {
200+
const authBJJCredentialCreationOptions = {
201+
seed: SEED_ISSUER,
202+
revocationOpts: {
203+
type: CredentialStatusType.Iden3ReverseSparseMerkleTreeProof,
204+
id: RHS_URL
205+
}
206+
};
207+
// create identity without auth bjj credential
208+
const { did, credential } = await idWallet.createEthereumBasedIdentity({
209+
method: DidMethod.Iden3,
210+
blockchain: Blockchain.Polygon,
211+
networkId: NetworkId.Amoy,
212+
...authBJJCredentialCreationOptions,
213+
createBjjCredential: false
214+
});
215+
216+
expect(did.string()).to.equal(
217+
'did:iden3:polygon:amoy:x6x5sor7zpxsu478u36QvEgaRUfPjmzqFo5PHHzbM'
218+
);
219+
expect(credential).to.be.undefined;
220+
221+
// add bjj credential
222+
const ethSigner = new Wallet(WALLET_KEY, dataStorage.states.getRpcProvider());
223+
224+
const oldTreeState: TreeState = {
225+
revocationRoot: ZERO_HASH,
226+
claimsRoot: ZERO_HASH,
227+
state: ZERO_HASH,
228+
rootOfRoots: ZERO_HASH
229+
};
230+
231+
const credential2 = await idWallet.addBJJAuthCredential(
232+
did,
233+
oldTreeState,
234+
true,
235+
ethSigner,
236+
authBJJCredentialCreationOptions
237+
);
238+
239+
const dbCred = await dataStorage.credential.findCredentialById(credential2.id);
240+
expect(credential2).to.deep.equal(dbCred);
241+
242+
const claimsTree = await dataStorage.mt.getMerkleTreeByIdentifierAndType(
243+
did.string(),
244+
MerkleTreeType.Claims
245+
);
246+
247+
expect((await claimsTree.root()).bigInt()).not.to.equal(0);
248+
});
249+
250+
it('createIdentity Secp256k1 with bjj cred and no signer', async () => {
251+
try {
252+
await createEthereumBasedIdentity(idWallet);
253+
expect.fail();
254+
} catch (err: unknown) {
255+
expect((err as Error).message).to.be.eq(
256+
`Ethereum signer is required to create Ethereum identities in order to transit state`
257+
);
258+
}
259+
});
260+
195261
it('add auth bjj credential', async () => {
196262
const { did, credential } = await createIdentity(idWallet);
197263
expect(did.string()).to.equal(expectedDID);

tests/kms/kms.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ const testFlow = async (provider: IKeyProvider) => {
2828
provider.newPrivateKeyFromSeed(seed2),
2929
provider.newPrivateKeyFromSeed(seed1)
3030
]);
31+
32+
const providerKeys = await provider.list();
33+
expect(providerKeys.length).to.equal(2);
34+
expect(providerKeys[0].alias).to.include(provider.keyType);
35+
expect(providerKeys[1].alias).to.include(provider.keyType);
36+
3137
const [signature1, signature2, signature3] = await Promise.all([
3238
provider.sign(keyId1, dataToSign1),
3339
provider.sign(keyId2, dataToSign2),
@@ -56,5 +62,7 @@ describe('Key store providers', () => {
5662
testFlow(ed25519Provider),
5763
testFlow(secp256k1Provider)
5864
]);
65+
const allKeys = await keyStore.list();
66+
expect(allKeys.length).to.equal(6);
5967
});
6068
});

0 commit comments

Comments
 (0)