import { PrivateKey, verify } from 'o1js'; import heartbeat from './datasample/heartbeat.json'; import { test, expect, it, describe, beforeAll } from '@jest/globals'; import { type JsonValue, JsonParser, linearizeJson, linearDataToMerkleMap, } from '../src/utils/jsonParser'; import { PackedStringFactory } from 'o1js-pack'; import { MINA_MERKLE_MAP_FACTORY, BackendFactory, } from '../src/proving/mina.js'; import * as IPLD from '../src/linearization/ipld.js'; import * as query from '../src/query/query.js'; import * as os from 'os'; import * as path from 'path'; import * as fs from 'fs'; import { fileURLToPath } from 'url'; import { performance } from 'perf_hooks'; import { type PerformanceData } from '../src/types/monitoring.types.js'; import { Utils } from './utils/utils.js'; // Get the directory name of the current module const __dirname = path.dirname(fileURLToPath(import.meta.url)); class TextInput extends PackedStringFactory() {} describe('use parseJSON', () => { let oracleAccount: PrivateKey; beforeAll(async () => { oracleAccount = PrivateKey.random(); }); // it('correctly verifies value of a specific key', async () => { // const json = parseJSON(JSON.stringify(jsontest)); // json.key('value').assertEqualString('"92"'); // }); it('linearize json and builds a merkle map with direct value storage', async () => { const linearizedData = JsonParser.linearizeJson(heartbeat); const map = JsonParser.linearDataToMerkleMap(linearizedData); const queriedPathCode = 'valueQuantity.code'; const queriedPathValue = 'valueQuantity.value'; const packedPathCode = TextInput.fromString(queriedPathCode); const packedPathValue = TextInput.fromString(queriedPathValue); const packedValueCode = map.get(packedPathCode.packed); const fieldValue = map.get(packedPathValue.packed); expect(TextInput.fromFields([packedValueCode]).toString()).toEqual( 'beats/min' ); expect(Number(fieldValue.toString())).toEqual(72); }); // it('queries merkle tree & prove from small dataset and logs perf metrics', async () => { // let performanceData: PerformanceData = { // resourceType: 'Demo', // systemInfo: { // totalMemory: os.totalmem(), // freeMemory: os.freemem(), // cpuCount: os.cpus().length, // }, // performance: { // buildTime: 0, // proofTime: 0, // verifyTime: 0, // }, // merkleInfo: { // merkleLength: 0, // }, // datasetInfo: { // keyNumber: 0, // }, // }; // const ln = IPLD.LinearModel.fromJS({ // a: 10, // b: 20, // c: 'blue', // d: 'red', // }); // const map = MINA_MERKLE_MAP_FACTORY.fromLinearModel(ln); // const queryObject = Object.assign({ // '/a': { $eq: 10 }, // '/b': { $ge: 20 }, // '/c': { $eq: 'blue' }, // }); // const q = query.parse(queryObject); // if (!performanceData.queryInfo) { // performanceData.queryInfo = q; // } // const backendFactory = new BackendFactory(); // console.time('build'); // const startTimeBuild = performance.now(); // // If merkleInfo doesn't exist, initialize it // if (!performanceData.merkleInfo) { // performanceData.merkleInfo = { merkleLength: 0 }; // Initialize with default values // } // if (!performanceData.datasetInfo) { // performanceData.datasetInfo = { keyNumber: ln.size }; // Initialize with default values // } // performanceData.merkleInfo.merkleLength = map.witnessLength; // const backend = await backendFactory.build(map.witnessLength); // performanceData.performance.buildTime = performance.now() - startTimeBuild; // console.timeEnd('build'); // console.log('proof generation will start'); // console.time('execute'); // const startTimeProof = performance.now(); // const proofE = await backend.execute(map, q); // console.timeEnd('execute'); // performanceData.performance.proofTime = performance.now() - startTimeProof; // console.log( // 'p.0', // proofE.publicOutput.toString(), // proofE.publicInput.given.toString(), // proofE.publicInput.root.toString() // ); // if (!performanceData.verificationInfo) { // performanceData.verificationInfo = { // verificationResult: proofE.publicOutput.toBoolean(), // key: backend.verificationKey, // }; // } // const startTimeVerify = performance.now(); // console.log('p.1', await verify(proofE, backend.verificationKey)); // performanceData.performance.verifyTime = // performance.now() - startTimeVerify; // const timestamp = new Date().toISOString().replace(/[-:.]/g, ''); // const logPath = path.join( // __dirname, // 'logs/performance/jsonproving/', // `light-${timestamp}.json` // ); // fs.writeFileSync(logPath, JSON.stringify(performanceData, null, 2)); // }); it('queries merkle tree & prove from heartbeat dataset and logs perf metrics', async () => { let performanceData: PerformanceData = { resourceType: 'Observation', systemInfo: { totalMemory: os.totalmem(), freeMemory: os.freemem(), cpuCount: os.cpus().length, }, performance: { buildTime: 0, proofTime: 0, verifyTime: 0, }, merkleInfo: { merkleLength: 0, }, datasetInfo: { keyNumber: 0, }, }; const keyNumber = Utils.countKeys(heartbeat); performanceData.datasetInfo ??= {}; // Initialize 'performanceData.datasetInfo' if it is undefined performanceData.datasetInfo.keyNumber = keyNumber; const ln = IPLD.LinearModel.fromJS(heartbeat); const map = MINA_MERKLE_MAP_FACTORY.fromLinearModel(ln); const queryObject = Object.assign({ '/valueQuantity/value': { $eq: 72 }, '/valueQuantity/code': { $eq: 'beats/min' }, }); const q = query.parse(queryObject); if (!performanceData.queryInfo) { performanceData.queryInfo = q; } const backendFactory = new BackendFactory(); console.time('build'); const startTimeBuild = performance.now(); // If merkleInfo doesn't exist, initialize it if (!performanceData.merkleInfo) { performanceData.merkleInfo = { merkleLength: 0 }; // Initialize with default values } performanceData.merkleInfo.merkleLength = map.witnessLength; const backend = await backendFactory.build(map.witnessLength); performanceData.performance.buildTime = performance.now() - startTimeBuild; console.timeEnd('build'); console.log('proof generation will start'); console.time('execute'); const startTimeProof = performance.now(); const proofE = await backend.execute(map, q); console.timeEnd('execute'); performanceData.performance.proofTime = performance.now() - startTimeProof; console.log( 'p.0', proofE.publicOutput.toString(), proofE.publicInput.given.toString(), proofE.publicInput.root.toString(), proofE.proof ); if (!performanceData.verificationInfo) { performanceData.verificationInfo = { verificationResult: proofE.publicOutput.toBoolean(), key: backend.verificationKey, }; } const startTimeVerify = performance.now(); console.log('p.1', await verify(proofE, backend.verificationKey)); performanceData.performance.verifyTime = performance.now() - startTimeVerify; const timestamp = new Date().toISOString().replace(/[-:.]/g, ''); const logPath = path.join( __dirname, 'perflogs/', `heartbeat-${timestamp}.json` ); fs.writeFileSync(logPath, JSON.stringify(performanceData, null, 2)); }); });