From 0a29fa8dd95b37e490c18df2db90a7324ebe762c Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Tue, 5 Sep 2023 18:55:35 -0300 Subject: [PATCH] fix(rpc): Fixes getNodeInfo serialisation (#1991) When calling the RPC server across HTTP, the automagical json-rpc-server serialisation was failing to deserialise the `NodeInfo`. The constructor of the NodeInfo object was not exactly `Object`, so the converter did not go recursively into each field. This PR makes the check for "is something an object" wider, and changes the RPC server test so it reproduces the issue without the fix. Before this change, `getNodeInfo().rollupAddress` was equal to `{ type: 'EthAddress', data: '0x...' }`, so calling `toString()` on it resulted in the string `[object Object]`. --- .../test/aztec_rpc_test_suite.ts | 6 ++-- .../foundation/src/json-rpc/convert.ts | 28 +++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_test_suite.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_test_suite.ts index 94ec2c629d0..16e3ec57de4 100644 --- a/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_test_suite.ts +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/test/aztec_rpc_test_suite.ts @@ -132,9 +132,9 @@ export const aztecRpcTestSuite = (testName: string, aztecRpcSetup: () => Promise it('successfully gets node info', async () => { const nodeInfo = await rpc.getNodeInfo(); - expect(nodeInfo.version).toBeDefined(); - expect(nodeInfo.chainId).toBeDefined(); - expect(nodeInfo.rollupAddress).toBeDefined(); + expect(typeof nodeInfo.version).toEqual('number'); + expect(typeof nodeInfo.chainId).toEqual('number'); + expect(nodeInfo.rollupAddress.toString()).toMatch(/0x[a-fA-F0-9]+/); }); // Note: Not testing `isGlobalStateSynchronised`, `isAccountStateSynchronised` and `getSyncStatus` as these methods diff --git a/yarn-project/foundation/src/json-rpc/convert.ts b/yarn-project/foundation/src/json-rpc/convert.ts index 7ca545ddbd4..aec26c8f5cf 100644 --- a/yarn-project/foundation/src/json-rpc/convert.ts +++ b/yarn-project/foundation/src/json-rpc/convert.ts @@ -96,8 +96,9 @@ export function convertFromJsonObj(cc: ClassConverter, obj: any): any { if (Array.isArray(obj)) { return obj.map((x: any) => convertFromJsonObj(cc, x)); } + // Is this a dictionary? - if (obj.constructor === Object) { + if (typeof obj === 'object') { const newObj: any = {}; for (const key of Object.keys(obj)) { newObj[key] = convertFromJsonObj(cc, obj[key]); @@ -119,6 +120,7 @@ export function convertToJsonObj(cc: ClassConverter, obj: any): any { if (!obj) { return obj; // Primitive type } + // Is this a Node buffer? if (obj instanceof Buffer) { return { type: 'Buffer', data: obj.toString('base64') }; @@ -135,22 +137,26 @@ export function convertToJsonObj(cc: ClassConverter, obj: any): any { if (cc.isRegisteredClass(obj.constructor)) { return cc.toJsonObj(obj); } + // Is this an array? if (Array.isArray(obj)) { return obj.map((x: any) => convertToJsonObj(cc, x)); } - // Is this a dictionary? - if (obj.constructor === Object) { - const newObj: any = {}; - for (const key of Object.keys(obj)) { - newObj[key] = convertToJsonObj(cc, obj[key]); + + if (typeof obj === 'object') { + // Is this a dictionary? + if (isPlainObject(obj)) { + const newObj: any = {}; + for (const key of Object.keys(obj)) { + newObj[key] = convertToJsonObj(cc, obj[key]); + } + return newObj; + } else { + // Throw if this is a non-primitive class that was not registered + throw new Error(`Object ${obj.constructor.name} not registered for serialisation`); } - return newObj; - } - // Throw if this is a non-primitive class that was not registered - if (typeof obj === 'object' && !isPlainObject(obj)) { - throw new Error(`Object ${obj.constructor.name} not registered for serialisation`); } + // Leave alone, assume JSON primitive return obj; }