From 307d46e0f99fb306146ac6021603b898c3c1fd66 Mon Sep 17 00:00:00 2001 From: Aryan Jassal Date: Fri, 11 Jul 2025 15:08:00 +1000 Subject: [PATCH 1/6] fix: `claimNetwork` will error if a claim already exists --- src/nodes/NodeManager.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/nodes/NodeManager.ts b/src/nodes/NodeManager.ts index 783cfbfb8..cd0de1244 100644 --- a/src/nodes/NodeManager.ts +++ b/src/nodes/NodeManager.ts @@ -1875,6 +1875,12 @@ class NodeManager { network, targetNodeId, ); + + // Error out if a network access claim already exists + if (await this.getClaimNetworkAccess(network, tran) != null) { + throw new Error('TMP network access claim already exists') + } + const encodedNetworkAuthority = claimsUtils.generateSignedClaim( claimNetworkAuthority.toSigned(), ); From 6d8c2cda7cfe68b8856cc4257e081a22b049253e Mon Sep 17 00:00:00 2001 From: Aryan Jassal Date: Tue, 15 Jul 2025 15:27:25 +1000 Subject: [PATCH 2/6] chore: added network to syncNodeGraphHandler --- src/PolykeyAgent.ts | 1 + src/nodes/NodeManager.ts | 24 ++++++++++++++++++++---- tests/nodes/NodeManager.test.ts | 10 ++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/PolykeyAgent.ts b/src/PolykeyAgent.ts index 1af1a9fdf..54593a27a 100644 --- a/src/PolykeyAgent.ts +++ b/src/PolykeyAgent.ts @@ -774,6 +774,7 @@ class PolykeyAgent { }); const initialNodesShortlist = initialNodes.slice(0, 3); await this.nodeManager.syncNodeGraph( + options.network, initialNodesShortlist, undefined, false, diff --git a/src/nodes/NodeManager.ts b/src/nodes/NodeManager.ts index cd0de1244..a91b34fa4 100644 --- a/src/nodes/NodeManager.ts +++ b/src/nodes/NodeManager.ts @@ -253,6 +253,7 @@ class NodeManager { protected syncNodeGraphHandler = async ( ctx: ContextTimed, _taskInfo: TaskInfo | undefined, + network: string | undefined, initialNodes: Array<[NodeIdEncoded, NodeAddress]>, connectionConnectTimeoutTime: number | undefined, ) => { @@ -299,6 +300,14 @@ class NodeManager { } if (ctx.signal.aborted) return; + if (network != null) { + try { + await this.claimNetwork(successfulConnections[0].value.nodeId, network); + } catch { + await this.switchNetwork(network); + } + } + // Attempt a findNode operation looking for ourselves await this.findNode( { @@ -1877,10 +1886,10 @@ class NodeManager { ); // Error out if a network access claim already exists - if (await this.getClaimNetworkAccess(network, tran) != null) { - throw new Error('TMP network access claim already exists') + if ((await this.getClaimNetworkAccess(network, tran)) != null) { + throw new Error('TMP network access claim already exists'); } - + const encodedNetworkAuthority = claimsUtils.generateSignedClaim( claimNetworkAuthority.toSigned(), ); @@ -2793,6 +2802,7 @@ class NodeManager { * */ public syncNodeGraph( + network: string | undefined, initialNodes: Array<[NodeId, NodeAddress]>, connectionConnectTimeoutTime?: number, blocking?: boolean, @@ -2801,6 +2811,7 @@ class NodeManager { @startStop.ready(new nodesErrors.ErrorNodeManagerNotRunning()) @decorators.timedCancellable(true) public async syncNodeGraph( + network: string, initialNodes: Array<[NodeId, NodeAddress]>, connectionConnectTimeoutTime: number = this.connectionConnectTimeoutTime, blocking: boolean = false, @@ -2823,6 +2834,7 @@ class NodeManager { await this.syncNodeGraphHandler( ctx, undefined, + network, initialNodesParameter, connectionConnectTimeoutTime, ); @@ -2832,7 +2844,11 @@ class NodeManager { delay: 0, handlerId: this.syncNodeGraphHandlerId, lazy: true, - parameters: [initialNodesParameter, connectionConnectTimeoutTime], + parameters: [ + network, + initialNodesParameter, + connectionConnectTimeoutTime, + ], path: [this.tasksPath, this.syncNodeGraphHandlerId], priority: 0, }); diff --git a/tests/nodes/NodeManager.test.ts b/tests/nodes/NodeManager.test.ts index dd5cc55e4..4c0cecb32 100644 --- a/tests/nodes/NodeManager.test.ts +++ b/tests/nodes/NodeManager.test.ts @@ -2144,6 +2144,7 @@ describe(`${NodeManager.name}`, () => { const mockedRefreshBucket = jest.spyOn(nodeManager, 'refreshBucket'); await nodeManager.syncNodeGraph( + undefined, [ [ ncmPeers[0].nodeId, @@ -2203,6 +2204,7 @@ describe(`${NodeManager.name}`, () => { const mockedRefreshBucket = jest.spyOn(nodeManager, 'refreshBucket'); await nodeManager.syncNodeGraph( + undefined, [ [ ncmPeers[0].nodeId, @@ -2225,6 +2227,7 @@ describe(`${NodeManager.name}`, () => { }); test('network entry with syncNodeGraph handles failure to resolve hostnames', async () => { const syncP = nodeManager.syncNodeGraph( + undefined, [ [ncmPeers[0].nodeId, ['some.random.host' as Host, 55555 as Port]], [ncmPeers[0].nodeId, [localHost, 55555 as Port]], @@ -2309,6 +2312,7 @@ describe(`${NodeManager.name}`, () => { expect(await nodeGraph.nodesTotal()).toBe(0); await nodeManager.syncNodeGraph( + undefined, [ [ ncmPeers[0].nodeId, @@ -2963,5 +2967,11 @@ describe(`${NodeManager.name}`, () => { node1.nodeManager.claimNetwork(seedNodeId, network), ).rejects.toThrow(claimsErrors.ErrorEmptyStream); }); + // verify the claim exists + test.todo( + 'node should automatically request NetworkAccessClaim if it does not exist', + ); + // verify the claim is unmodified + test.todo('node should not request new NetworkAccessClaim if it exist'); }); }); From 1760ab53c2d93a315e7e7b216f9b2875c11480e5 Mon Sep 17 00:00:00 2001 From: Aryan Jassal Date: Mon, 21 Jul 2025 15:56:34 +1000 Subject: [PATCH 3/6] feat: added tests for startup network join behaviour --- jest.config.mjs | 2 +- src/nodes/NodeManager.ts | 6 +- src/nodes/agent/handlers/NodesSyncGraph.ts | 41 ++++++ src/nodes/agent/types.ts | 14 +- tests/nodes/NodeManager.test.ts | 147 ++++++++++++++++++++- 5 files changed, 199 insertions(+), 11 deletions(-) create mode 100644 src/nodes/agent/handlers/NodesSyncGraph.ts diff --git a/jest.config.mjs b/jest.config.mjs index 63bb380ae..c74d516bc 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -1,6 +1,6 @@ import path from 'node:path'; import url from 'node:url'; -import tsconfigJSON from './tsconfig.json' assert { type: "json" }; +import tsconfigJSON from './tsconfig.json' with { type: "json" }; const projectPath = path.dirname(url.fileURLToPath(import.meta.url)); diff --git a/src/nodes/NodeManager.ts b/src/nodes/NodeManager.ts index a91b34fa4..6e05b55d4 100644 --- a/src/nodes/NodeManager.ts +++ b/src/nodes/NodeManager.ts @@ -301,9 +301,9 @@ class NodeManager { if (ctx.signal.aborted) return; if (network != null) { - try { + if (this.getClaimNetworkAccess(network) == null) { await this.claimNetwork(successfulConnections[0].value.nodeId, network); - } catch { + } else { await this.switchNetwork(network); } } @@ -1757,7 +1757,7 @@ class NodeManager { /** * This returns the `ClaimNetworkAccess` for the given network. */ - protected async getClaimNetworkAccess( + public async getClaimNetworkAccess( network: string, tran?: DBTransaction, ): Promise | undefined> { diff --git a/src/nodes/agent/handlers/NodesSyncGraph.ts b/src/nodes/agent/handlers/NodesSyncGraph.ts new file mode 100644 index 000000000..594fa7411 --- /dev/null +++ b/src/nodes/agent/handlers/NodesSyncGraph.ts @@ -0,0 +1,41 @@ +import type { ContextTimed } from '@matrixai/contexts'; +import type { JSONValue } from '@matrixai/rpc'; +import type NodeManager from '../../NodeManager.js'; +import type { + AgentRPCRequestParams, + AgentRPCResponseResult, + NodesSyncGraphMessage, +} from '../types.js'; +import type { AgentClientManifest } from '../callers/index.js'; +import { UnaryHandler } from '@matrixai/rpc'; + +class NodesSyncGraph extends UnaryHandler< + { + nodeManager: NodeManager; + }, + AgentRPCRequestParams, + AgentRPCResponseResult +> { + public handle = async ( + input: AgentRPCRequestParams, + _cancel: (reason?: any) => void, + _meta: Record | undefined, + ctx: ContextTimed, + ): Promise => { + const { + nodeManager, + }: { + nodeManager: NodeManager; + } = this.container; + await nodeManager.syncNodeGraph( + input.network, + input.initialNodes, + input.connectionTimeout, + true, + ctx, + ); + return {}; + }; +} + +export default NodesSyncGraph; diff --git a/src/nodes/agent/types.ts b/src/nodes/agent/types.ts index 7d9a307fd..a0a17b05d 100644 --- a/src/nodes/agent/types.ts +++ b/src/nodes/agent/types.ts @@ -13,7 +13,12 @@ import type { import type { VaultAction, VaultName } from '../../vaults/types.js'; import type { SignedNotification } from '../../notifications/types.js'; import type { Host, Hostname, Port } from '../../network/types.js'; -import type { NetworkId, NodeContact } from '../../nodes/types.js'; +import type { + NetworkId, + NodeContact, + NodeId, + NodeAddress, +} from '../../nodes/types.js'; import type { AuditEvent } from '../../audit/types.js'; import type { SignedClaimEncoded } from '../../claims/types.js'; @@ -125,6 +130,12 @@ type NodesAuthenticateConnectionMessageNone = { type: 'NodesAuthenticateConnectionMessageNone'; }; +type NodesSyncGraphMessage = { + network: string; + initialNodes: Array<[NodeId, NodeAddress]>; + connectionTimeout: number; +}; + export type { AgentRPCRequestParams, AgentRPCResponseResult, @@ -147,4 +158,5 @@ export type { NodesAuthenticateConnectionMessagePrivate, NodesAuthenticateConnectionMessageBasicPublic, NodesAuthenticateConnectionMessageNone, + NodesSyncGraphMessage, }; diff --git a/tests/nodes/NodeManager.test.ts b/tests/nodes/NodeManager.test.ts index 4c0cecb32..d011a4ab2 100644 --- a/tests/nodes/NodeManager.test.ts +++ b/tests/nodes/NodeManager.test.ts @@ -2967,11 +2967,146 @@ describe(`${NodeManager.name}`, () => { node1.nodeManager.claimNetwork(seedNodeId, network), ).rejects.toThrow(claimsErrors.ErrorEmptyStream); }); - // verify the claim exists - test.todo( - 'node should automatically request NetworkAccessClaim if it does not exist', - ); - // verify the claim is unmodified - test.todo('node should not request new NetworkAccessClaim if it exist'); + test('node should automatically request a claim if it does not exist', async () => { + // Creating network credentials + const networkKeyPair = keysUtils.generateKeyPair(); + const networkNodeId = keysUtils.publicKeyToNodeId( + networkKeyPair.publicKey, + ); + const network = 'public.network.com'; + + // Setting up seed nodes claims + const seedNode = await createPeerNode(); + const [, seedNodeClaimNetworkAuthority] = + await seedNode.nodeManager.createClaimNetworkAuthority( + networkNodeId, + network, + false, + async (claim) => { + claim.signWithPrivateKey(networkKeyPair.privateKey); + return claim; + }, + ); + await seedNode.nodeManager.createSelfSignedClaimNetworkAccess( + seedNodeClaimNetworkAuthority, + ); + const seedNodeId = seedNode.keyRing.getNodeId(); + + // Setting up the new node entering the network + const node1 = await createPeerNode(); + // We intentionally do not claim the network manually + const node1Id = node1.keyRing.getNodeId(); + await allowNodeToJoin(seedNode.gestaltGraph, node1Id); + // Connect to the seed node + await node1.nodeConnectionManager.createConnection( + [seedNodeId], + localHost, + seedNode.nodeConnectionManager.port, + ); + + await node1.nodeManager.syncNodeGraph( + network, + [ + [ + seedNode.keyRing.getNodeId(), + [localHost, seedNode.nodeConnectionManager.port], + ], + ], + 1000, + true, + ); + + // We have now proved that a node can request access to the network from a node with network authority. + // Now We should be able to connect while authenticated to the seed node. + + // Re-initiate authentication + await seedNode.nodeConnectionManager.destroyConnection(node1Id, true); + await node1.nodeConnectionManager.destroyConnection(seedNodeId, true); + await node1.nodeConnectionManager.createConnection( + [seedNodeId], + localHost, + seedNode.nodeConnectionManager.port, + ); + + const networkAccess = + await node1.nodeManager.getClaimNetworkAccess(network); + if (networkAccess == null) { + throw new Error('network access claim not found'); + } + claimNetworkAccessUtils.verifyClaimNetworkAccess( + networkNodeId, + node1Id, + network, + networkAccess, + ); + + await node1.nodeManager.withConnF(seedNodeId, undefined, async () => { + // Do nothing + }); + }); + test('node should not request new claim if it already exists', async () => { + // Creating network credentials + const networkKeyPair = keysUtils.generateKeyPair(); + const networkNodeId = keysUtils.publicKeyToNodeId( + networkKeyPair.publicKey, + ); + const network = 'test.network.com'; + + // Setting up seed nodes claims + const seedNode = await createPeerNode(); + const [, seedNodeClaimNetworkAuthority] = + await seedNode.nodeManager.createClaimNetworkAuthority( + networkNodeId, + network, + true, + async (claim) => { + claim.signWithPrivateKey(networkKeyPair.privateKey); + return claim; + }, + ); + await seedNode.nodeManager.createSelfSignedClaimNetworkAccess( + seedNodeClaimNetworkAuthority, + ); + const seedNodeId = seedNode.keyRing.getNodeId(); + + // Setting up the new node entering the network + const node1 = await createPeerNode(); + + const node1Id = node1.keyRing.getNodeId(); + await allowNodeToJoin(seedNode.gestaltGraph, node1Id); + + // Connect to the seednode + await node1.nodeConnectionManager.createConnection( + [seedNodeId], + localHost, + seedNode.nodeConnectionManager.port, + ); + + // Create a network access claim + await node1.nodeManager.claimNetwork(seedNodeId, network); + + // Re-initiate authentication + await seedNode.nodeConnectionManager.destroyConnection(node1Id, true); + await node1.nodeConnectionManager.destroyConnection(seedNodeId, true); + await node1.nodeConnectionManager.createConnection( + [seedNodeId], + localHost, + seedNode.nodeConnectionManager.port, + ); + + // Check the claim once we have re-authenticated + const token1 = await node1.nodeManager.getClaimNetworkAccess(network); + if (token1 == null) throw new Error('network access claim not found'); + const token1Id = token1.payload.jti; + + // Try claiming again + await expect(node1.nodeManager.claimNetwork(seedNodeId, network)).toReject(); + + // The token should not have changed + const token2 = await node1.nodeManager.getClaimNetworkAccess(network); + if (token2 == null) throw new Error('network access claim not found'); + const token2Id = token2.payload.jti; + expect(token1Id).toBe(token2Id); + }); }); }); From 452ce012db56ed31ef9d4360e6650fb3b5e3b317 Mon Sep 17 00:00:00 2001 From: Aryan Jassal Date: Tue, 22 Jul 2025 13:02:06 +1000 Subject: [PATCH 4/6] fix: lint and tests --- src/nodes/NodeManager.ts | 2 +- tests/nodes/NodeManager.test.ts | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/nodes/NodeManager.ts b/src/nodes/NodeManager.ts index 6e05b55d4..8341a7f8d 100644 --- a/src/nodes/NodeManager.ts +++ b/src/nodes/NodeManager.ts @@ -301,7 +301,7 @@ class NodeManager { if (ctx.signal.aborted) return; if (network != null) { - if (this.getClaimNetworkAccess(network) == null) { + if ((await this.getClaimNetworkAccess(network)) == null) { await this.claimNetwork(successfulConnections[0].value.nodeId, network); } else { await this.switchNetwork(network); diff --git a/tests/nodes/NodeManager.test.ts b/tests/nodes/NodeManager.test.ts index d011a4ab2..da8a72676 100644 --- a/tests/nodes/NodeManager.test.ts +++ b/tests/nodes/NodeManager.test.ts @@ -3017,7 +3017,7 @@ describe(`${NodeManager.name}`, () => { ); // We have now proved that a node can request access to the network from a node with network authority. - // Now We should be able to connect while authenticated to the seed node. + // Now we should be able to connect while authenticated to the seed node. // Re-initiate authentication await seedNode.nodeConnectionManager.destroyConnection(node1Id, true); @@ -3030,9 +3030,7 @@ describe(`${NodeManager.name}`, () => { const networkAccess = await node1.nodeManager.getClaimNetworkAccess(network); - if (networkAccess == null) { - throw new Error('network access claim not found'); - } + if (networkAccess == null) fail('network access claim not found'); claimNetworkAccessUtils.verifyClaimNetworkAccess( networkNodeId, node1Id, @@ -3096,15 +3094,17 @@ describe(`${NodeManager.name}`, () => { // Check the claim once we have re-authenticated const token1 = await node1.nodeManager.getClaimNetworkAccess(network); - if (token1 == null) throw new Error('network access claim not found'); + if (token1 == null) fail('network access claim not found'); const token1Id = token1.payload.jti; // Try claiming again - await expect(node1.nodeManager.claimNetwork(seedNodeId, network)).toReject(); + await expect( + node1.nodeManager.claimNetwork(seedNodeId, network), + ).toReject(); // The token should not have changed const token2 = await node1.nodeManager.getClaimNetworkAccess(network); - if (token2 == null) throw new Error('network access claim not found'); + if (token2 == null) fail('network access claim not found'); const token2Id = token2.payload.jti; expect(token1Id).toBe(token2Id); }); From 029577f4b45cef15e3910b99ec31c491a8865d32 Mon Sep 17 00:00:00 2001 From: Aryan Jassal Date: Wed, 23 Jul 2025 14:47:07 +1000 Subject: [PATCH 5/6] chore: moved rpc handler from agent rpc to client rpc --- src/client/callers/index.ts | 3 +++ src/client/callers/nodesSyncGraph.ts | 12 ++++++++++++ .../agent => client}/handlers/NodesSyncGraph.ts | 16 ++++++++-------- src/client/handlers/index.ts | 3 +++ src/client/types.ts | 8 ++++++++ src/nodes/agent/types.ts | 14 +------------- 6 files changed, 35 insertions(+), 21 deletions(-) create mode 100644 src/client/callers/nodesSyncGraph.ts rename src/{nodes/agent => client}/handlers/NodesSyncGraph.ts (67%) diff --git a/src/client/callers/index.ts b/src/client/callers/index.ts index 7a00bc4ec..ab5981a93 100644 --- a/src/client/callers/index.ts +++ b/src/client/callers/index.ts @@ -46,6 +46,7 @@ import nodesFind from './nodesFind.js'; import nodesGetAll from './nodesGetAll.js'; import nodesListConnections from './nodesListConnections.js'; import nodesPing from './nodesPing.js'; +import nodesSyncGraph from './nodesSyncGraph.js'; import notificationsInboxClear from './notificationsInboxClear.js'; import notificationsInboxRead from './notificationsInboxRead.js'; import notificationsInboxRemove from './notificationsInboxRemove.js'; @@ -128,6 +129,7 @@ const clientManifest = { nodesGetAll, nodesListConnections, nodesPing, + nodesSyncGraph, notificationsInboxClear, notificationsInboxRead, notificationsInboxRemove, @@ -209,6 +211,7 @@ export { nodesGetAll, nodesListConnections, nodesPing, + nodesSyncGraph, notificationsInboxClear, notificationsInboxRead, notificationsInboxRemove, diff --git a/src/client/callers/nodesSyncGraph.ts b/src/client/callers/nodesSyncGraph.ts new file mode 100644 index 000000000..c868971b5 --- /dev/null +++ b/src/client/callers/nodesSyncGraph.ts @@ -0,0 +1,12 @@ +import type { HandlerTypes } from '@matrixai/rpc'; +import type NodesSyncGraph from '../handlers/NodesSyncGraph.js'; +import { UnaryCaller } from '@matrixai/rpc'; + +type CallerTypes = HandlerTypes; + +const nodesSyncGraph = new UnaryCaller< + CallerTypes['input'], + CallerTypes['output'] +>(); + +export default nodesSyncGraph; diff --git a/src/nodes/agent/handlers/NodesSyncGraph.ts b/src/client/handlers/NodesSyncGraph.ts similarity index 67% rename from src/nodes/agent/handlers/NodesSyncGraph.ts rename to src/client/handlers/NodesSyncGraph.ts index 594fa7411..e5bb30bdc 100644 --- a/src/nodes/agent/handlers/NodesSyncGraph.ts +++ b/src/client/handlers/NodesSyncGraph.ts @@ -1,27 +1,27 @@ import type { ContextTimed } from '@matrixai/contexts'; import type { JSONValue } from '@matrixai/rpc'; -import type NodeManager from '../../NodeManager.js'; +import type NodeManager from '../../nodes/NodeManager.js'; import type { - AgentRPCRequestParams, - AgentRPCResponseResult, + ClientRPCRequestParams, + ClientRPCResponseResult, NodesSyncGraphMessage, } from '../types.js'; -import type { AgentClientManifest } from '../callers/index.js'; +import type { AgentClientManifest } from '../../nodes/agent/callers/index.js'; import { UnaryHandler } from '@matrixai/rpc'; class NodesSyncGraph extends UnaryHandler< { nodeManager: NodeManager; }, - AgentRPCRequestParams, - AgentRPCResponseResult + ClientRPCRequestParams, + ClientRPCResponseResult > { public handle = async ( - input: AgentRPCRequestParams, + input: ClientRPCRequestParams, _cancel: (reason?: any) => void, _meta: Record | undefined, ctx: ContextTimed, - ): Promise => { + ): Promise => { const { nodeManager, }: { diff --git a/src/client/handlers/index.ts b/src/client/handlers/index.ts index f4b9a6588..b4fe7467f 100644 --- a/src/client/handlers/index.ts +++ b/src/client/handlers/index.ts @@ -64,6 +64,7 @@ import NodesFind from './NodesFind.js'; import NodesGetAll from './NodesGetAll.js'; import NodesListConnections from './NodesListConnections.js'; import NodesPing from './NodesPing.js'; +import NodesSyncGraph from './NodesSyncGraph.js'; import NotificationsInboxClear from './NotificationsInboxClear.js'; import NotificationsInboxRead from './NotificationsInboxRead.js'; import NotificationsInboxRemove from './NotificationsInboxRemove.js'; @@ -169,6 +170,7 @@ const serverManifest = (container: { nodesGetAll: new NodesGetAll(container), nodesListConnections: new NodesListConnections(container), nodesPing: new NodesPing(container), + nodesSyncGraph: new NodesSyncGraph(container), notificationsInboxClear: new NotificationsInboxClear(container), notificationsInboxRead: new NotificationsInboxRead(container), notificationsInboxRemove: new NotificationsInboxRemove(container), @@ -252,6 +254,7 @@ export { NodesGetAll, NodesListConnections, NodesPing, + NodesSyncGraph, NotificationsInboxClear, NotificationsInboxRead, NotificationsInboxRemove, diff --git a/src/client/types.ts b/src/client/types.ts index 5b6f30837..b1021bdc3 100644 --- a/src/client/types.ts +++ b/src/client/types.ts @@ -27,6 +27,7 @@ import type { NodeContact, NodeAddress, NodeContactAddressData, + NodeId, } from '../nodes/types.js'; import type { AuditEventsGetTypeOverride } from './callers/auditEventsGet.js'; @@ -151,6 +152,12 @@ type NodeConnectionMessage = NodeAddressMessage & { authenticated: boolean; }; +type NodesSyncGraphMessage = { + network: string; + initialNodes: Array<[NodeId, NodeAddress]>; + connectionTimeout?: number; +}; + // Gestalts messages type ActionsListMessage = { @@ -428,6 +435,7 @@ export type { NodeAddressMessage, NodesFindMessage, NodeConnectionMessage, + NodesSyncGraphMessage, ActionsListMessage, SetIdentityActionMessage, SetNodeActionMessage, diff --git a/src/nodes/agent/types.ts b/src/nodes/agent/types.ts index a0a17b05d..7d9a307fd 100644 --- a/src/nodes/agent/types.ts +++ b/src/nodes/agent/types.ts @@ -13,12 +13,7 @@ import type { import type { VaultAction, VaultName } from '../../vaults/types.js'; import type { SignedNotification } from '../../notifications/types.js'; import type { Host, Hostname, Port } from '../../network/types.js'; -import type { - NetworkId, - NodeContact, - NodeId, - NodeAddress, -} from '../../nodes/types.js'; +import type { NetworkId, NodeContact } from '../../nodes/types.js'; import type { AuditEvent } from '../../audit/types.js'; import type { SignedClaimEncoded } from '../../claims/types.js'; @@ -130,12 +125,6 @@ type NodesAuthenticateConnectionMessageNone = { type: 'NodesAuthenticateConnectionMessageNone'; }; -type NodesSyncGraphMessage = { - network: string; - initialNodes: Array<[NodeId, NodeAddress]>; - connectionTimeout: number; -}; - export type { AgentRPCRequestParams, AgentRPCResponseResult, @@ -158,5 +147,4 @@ export type { NodesAuthenticateConnectionMessagePrivate, NodesAuthenticateConnectionMessageBasicPublic, NodesAuthenticateConnectionMessageNone, - NodesSyncGraphMessage, }; From 7242559a4084b8f2270910bc0fb2255bb9efc8dd Mon Sep 17 00:00:00 2001 From: Aryan Jassal Date: Thu, 24 Jul 2025 16:53:38 +1000 Subject: [PATCH 6/6] chore: changed rpc types to be easily seralisable --- src/client/handlers/NodesSyncGraph.ts | 9 ++++++++- src/client/types.ts | 3 +-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/client/handlers/NodesSyncGraph.ts b/src/client/handlers/NodesSyncGraph.ts index e5bb30bdc..fa56ca6fc 100644 --- a/src/client/handlers/NodesSyncGraph.ts +++ b/src/client/handlers/NodesSyncGraph.ts @@ -7,7 +7,9 @@ import type { NodesSyncGraphMessage, } from '../types.js'; import type { AgentClientManifest } from '../../nodes/agent/callers/index.js'; +import type { NodeId, NodeAddress } from '../../nodes/types.js'; import { UnaryHandler } from '@matrixai/rpc'; +import * as nodesUtils from '../../nodes/utils.js'; class NodesSyncGraph extends UnaryHandler< { @@ -27,9 +29,14 @@ class NodesSyncGraph extends UnaryHandler< }: { nodeManager: NodeManager; } = this.container; + // Convert the encoded node id to the binary one we expect + const parsedInitialNodes = input.initialNodes.map( + (value) => + [nodesUtils.decodeNodeId(value[0]), value[1]] as [NodeId, NodeAddress], + ); await nodeManager.syncNodeGraph( input.network, - input.initialNodes, + parsedInitialNodes, input.connectionTimeout, true, ctx, diff --git a/src/client/types.ts b/src/client/types.ts index b1021bdc3..e4e2cb969 100644 --- a/src/client/types.ts +++ b/src/client/types.ts @@ -27,7 +27,6 @@ import type { NodeContact, NodeAddress, NodeContactAddressData, - NodeId, } from '../nodes/types.js'; import type { AuditEventsGetTypeOverride } from './callers/auditEventsGet.js'; @@ -154,7 +153,7 @@ type NodeConnectionMessage = NodeAddressMessage & { type NodesSyncGraphMessage = { network: string; - initialNodes: Array<[NodeId, NodeAddress]>; + initialNodes: Array<[NodeIdEncoded, NodeAddress]>; connectionTimeout?: number; };