From 559807a50c277aac7308186efe46a0440a78e558 Mon Sep 17 00:00:00 2001 From: Mircea Nistor Date: Mon, 16 Oct 2023 14:58:55 +0200 Subject: [PATCH] fix: remove unavailable web3 identifiers when local agent gets rebuilt (#191) * fix(web3 context): use key store abstractions to mess with keys * fix(web3 context): delete unavailable web3 identifiers * chore: remove outdated comment * feat: invalidate queries after updating dids --------- Co-authored-by: Simonas Karuzas --- .../src/context/web3/VeramoWeb3Provider.tsx | 14 ++--- .../src/context/web3/web3Agent.ts | 60 ++++++++++--------- .../identifiers/ManagedIdentifiers.tsx | 19 ++++-- .../plugins/identifiers/NewIdentifierForm.tsx | 1 - 4 files changed, 52 insertions(+), 42 deletions(-) diff --git a/packages/agent-explore/src/context/web3/VeramoWeb3Provider.tsx b/packages/agent-explore/src/context/web3/VeramoWeb3Provider.tsx index 95dcafeb..bc69f09c 100644 --- a/packages/agent-explore/src/context/web3/VeramoWeb3Provider.tsx +++ b/packages/agent-explore/src/context/web3/VeramoWeb3Provider.tsx @@ -44,14 +44,14 @@ export const VeramoWeb3Provider = ({ name: 'walletconnect', }) } - void createWeb3Agent({ connectors }).then(setWeb3Agent) - queryClient.invalidateQueries({ - queryKey: [ - 'identifiers', - { agentId: 'web3Agent'} - ] + void createWeb3Agent({ connectors }).then(setWeb3Agent).then(() => { + queryClient.invalidateQueries({ + queryKey: [ + 'identifiers', + { agentId: 'web3Agent'} + ] + }) }) - console.log('invalidateQueries') return () => { setWeb3Agent(undefined) } diff --git a/packages/agent-explore/src/context/web3/web3Agent.ts b/packages/agent-explore/src/context/web3/web3Agent.ts index 97648a03..82c9f237 100644 --- a/packages/agent-explore/src/context/web3/web3Agent.ts +++ b/packages/agent-explore/src/context/web3/web3Agent.ts @@ -109,6 +109,10 @@ export async function createWeb3Agent({ connectors }: { web3Providers[info.name] = info.provider }) + const keyStore = new KeyStoreJson(identifierDataStore) + const privateKeyStore = new PrivateKeyStoreJson(identifierDataStore) + const didStore = new DIDStoreJson(identifierDataStore) + const id = 'web3Agent' const agent = createAgent< IDIDManager & @@ -137,16 +141,14 @@ export async function createWeb3Agent({ connectors }: { }, { cache: true }), }), new KeyManager({ - store: new KeyStoreJson(identifierDataStore), + store: keyStore, kms: { - local: new KeyManagementSystem( - new PrivateKeyStoreJson(identifierDataStore), - ), + local: new KeyManagementSystem(privateKeyStore), web3: new Web3KeyManagementSystem(web3Providers), }, }), new DIDManager({ - store: new DIDStoreJson(identifierDataStore), + store: didStore, defaultProvider: connectors[0]?.name, providers: didProviders, }), @@ -179,39 +181,34 @@ export async function createWeb3Agent({ connectors }: { ], }) - // commented out in https://github.com/veramolabs/agent-explorer/pull/115/files - // was causing locally-managed X25519 keys to be deleted on page refresh - // const identifiers = await agent.didManagerFind() - // for (const identifier of identifiers) { - // if (identifier.keys.filter((key) => key.kms !== 'web3').length === 0) { - // await agent.didManagerDelete({ did: identifier.did }) - // } - // } + const identifiers = await agent.didManagerFind() + const markedForClearance = new Set([]) + for (const identifier of identifiers) { + if (identifier.keys.filter((key) => key.kms === 'web3').length !== 0) { + markedForClearance.add(identifier.did) + } + } + + const existingKeys = await keyStore.listKeys() for (const info of connectors) { if (info.accounts) { - console.log('nana') for (const account of info.accounts) { for (const provider of ['pkh', 'ethr']) { const prefix = (provider === 'pkh') ? 'did:pkh:eip155:' : 'did:ethr:0x' const did = (provider === 'pkh') ? `${prefix}${info.chainId}:${account}` : `${prefix}${info.chainId.toString(16)}:${account}` - let extraManagedKeys = [] - for (const keyId in { ...identifierDataStore.keys }) { - if ( - identifierDataStore.keys[keyId]?.meta?.did === did && - identifierDataStore.keys[keyId].kms === 'local' - ) { - extraManagedKeys.push(identifierDataStore.keys[keyId]) + markedForClearance.delete(did) + + const extraManagedKeys: MinimalImportableKey[] = [] + for (const key of existingKeys) { + if (key.meta?.did === did && key.kms === 'local') { + const privateKeyHex = (await privateKeyStore.getKey({ alias: key.kid }))?.privateKeyHex + if (privateKeyHex) { + extraManagedKeys.push({ ...key, privateKeyHex }) + } } } - extraManagedKeys = extraManagedKeys.map((k) => { - const privateKeyHex = identifierDataStore.privateKeys[k.kid].privateKeyHex - return { - ...k, - privateKeyHex, - } - }) // const controllerKeyId = `${did}#controller` const controllerKeyId = `${info.name}-${account}` @@ -230,7 +227,7 @@ export async function createWeb3Agent({ connectors }: { account: account.toLocaleLowerCase(), algorithms: ['eth_signMessage', 'eth_signTypedData'], }, - } as MinimalImportableKey, + }, ...extraManagedKeys, ], }) @@ -239,5 +236,10 @@ export async function createWeb3Agent({ connectors }: { } } + for (const did of Array.from(markedForClearance.values())) { + // didStore delete does not remove the keys, just the mapping, which can be recreated later + await didStore.deleteDID({ did }) + } + return agent } diff --git a/packages/agent-explore/src/plugins/identifiers/ManagedIdentifiers.tsx b/packages/agent-explore/src/plugins/identifiers/ManagedIdentifiers.tsx index 05f6798b..0e744a04 100644 --- a/packages/agent-explore/src/plugins/identifiers/ManagedIdentifiers.tsx +++ b/packages/agent-explore/src/plugins/identifiers/ManagedIdentifiers.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react' import { Table, Button, Row, Space, App, Drawer } from 'antd' import { Link } from 'react-router-dom' -import { useQuery } from 'react-query' +import { useQuery, useQueryClient } from 'react-query' import { useVeramo } from '@veramo-community/veramo-react' import { PageContainer, ProList } from '@ant-design/pro-components' import { IDIDManager } from '@veramo/core-types' @@ -12,13 +12,15 @@ import { } from './NewIdentifierForm' import { shortId, IdentifierProfile } from '@veramo-community/agent-explorer-plugin' import { createMediateRequestMessage } from '@veramo/did-comm' -import { DeleteOutlined, CopyOutlined, PlusOutlined } from '@ant-design/icons' -import { IDataStore, IIdentifier } from '@veramo/core' +import { DeleteOutlined, PlusOutlined } from '@ant-design/icons' +import { IDataStore } from '@veramo/core' export const ManagedIdentifiers = () => { const { notification } = App.useApp() const { agent } = useVeramo() const [drawerOpen, setDrawerOpen] = useState(false) + const [ creating, setCreating ] = useState(false) + const queryClient = useQueryClient() const { data: providers } = useQuery( ['providers', { agentId: agent?.context.id }], @@ -31,6 +33,7 @@ export const ManagedIdentifiers = () => { const handleNewIdentifierOk = async (values: NewIdentifierFormValues) => { setDrawerOpen(false) + setCreating(true) const { alias, provider } = values let options = undefined if (provider === 'did:peer') { @@ -106,8 +109,13 @@ export const ManagedIdentifiers = () => { } - - refetch() + queryClient.invalidateQueries({ + queryKey: [ + 'identifiers', + { agentId: 'web3Agent'} + ] + }) + setCreating(false) } return ( @@ -118,6 +126,7 @@ export const ManagedIdentifiers = () => { icon={} type="primary" title="Create new identifier" + loading={creating} onClick={() => setDrawerOpen(true)} >New, ]} diff --git a/packages/agent-explore/src/plugins/identifiers/NewIdentifierForm.tsx b/packages/agent-explore/src/plugins/identifiers/NewIdentifierForm.tsx index c57406c1..167b2d31 100644 --- a/packages/agent-explore/src/plugins/identifiers/NewIdentifierForm.tsx +++ b/packages/agent-explore/src/plugins/identifiers/NewIdentifierForm.tsx @@ -72,7 +72,6 @@ export const NewIdentifierForm: React.FC = ({ .then((values) => { form.resetFields() setStep(0) - console.log({values}) onNewIdentifier(values) }) .catch((info) => {