diff --git a/package-lock.json b/package-lock.json index fee22109e..0b755d567 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34768,7 +34768,7 @@ }, "packages/build-utils/paima-build-utils": { "name": "@paima/build-utils", - "version": "2.0.1", + "version": "2.1.0", "license": "See license file", "bin": { "paima-build-middleware": "scripts/esbuild.sh" @@ -34906,10 +34906,9 @@ }, "packages/node-sdk/paima-db": { "name": "@paima/db", - "version": "2.0.1", + "version": "2.1.0", "license": "See license file", "dependencies": { - "@paima/utils": "2.0.1", "@pgtyped/runtime": "2.1.0", "pg": "^8.7.3", "pg-tx": "^1.0.1" @@ -34921,11 +34920,10 @@ }, "packages/node-sdk/paima-utils-backend": { "name": "@paima/utils-backend", - "version": "2.0.1", + "version": "2.1.0", "license": "See license file", "dependencies": { - "@paima/db": "2.0.1", - "@paima/utils": "2.0.1", + "@paima/db": "2.1.0", "yaml": "^2.3.1" }, "devDependencies": { @@ -34941,34 +34939,34 @@ }, "packages/node-sdk/publish-wrapper": { "name": "@paima/node-sdk", - "version": "2.0.1", + "version": "2.1.0", "license": "See license file", "dependencies": { - "@paima/db": "2.0.1", - "@paima/utils-backend": "2.0.1" + "@paima/db": "2.1.0", + "@paima/utils-backend": "2.1.0" }, "devDependencies": {} }, "packages/paima-sdk/paima-concise": { "name": "@paima/concise", - "version": "2.0.1", + "version": "2.1.0", "license": "See license file", "dependencies": { "ebnf": "^1.9.0", "web3-utils": "1.10.0" }, "devDependencies": { - "@paima/utils": "2.0.1", + "@paima/utils": "2.1.0", "@types/node": "^18.17.1" } }, "packages/paima-sdk/paima-crypto": { "name": "@paima/crypto", - "version": "2.0.1", + "version": "2.1.0", "license": "See license file", "dependencies": { "@cardano-foundation/cardano-verify-datasignature": "^1.0.11", - "@paima/utils": "2.0.1", + "@paima/utils": "2.1.0", "@polkadot/util": "^10.4.2", "@polkadot/util-crypto": "^10.4.2", "algosdk": "^2.3.0", @@ -34981,10 +34979,10 @@ }, "packages/paima-sdk/paima-executors": { "name": "@paima/executors", - "version": "2.0.1", + "version": "2.1.0", "license": "See license file", "dependencies": { - "@paima/prando": "2.0.1" + "@paima/prando": "2.1.0" }, "devDependencies": { "typescript": "^5.3.2" @@ -34992,14 +34990,14 @@ }, "packages/paima-sdk/paima-mw-core": { "name": "@paima/mw-core", - "version": "2.0.1", + "version": "2.1.0", "license": "See license file", "dependencies": { "@metamask/providers": "^10.2.1", - "@paima/concise": "2.0.1", - "@paima/prando": "2.0.1", - "@paima/providers": "2.0.1", - "@paima/utils": "2.0.1", + "@paima/concise": "2.1.0", + "@paima/prando": "2.1.0", + "@paima/providers": "2.1.0", + "@paima/utils": "2.1.0", "@perawallet/connect": "^1.2.3", "@polkadot/extension-dapp": "^0.44.9", "@truffle/hdwallet-provider": "^2.1.15", @@ -35016,7 +35014,7 @@ }, "packages/paima-sdk/paima-prando": { "name": "@paima/prando", - "version": "2.0.1", + "version": "2.1.0", "license": "See license file", "devDependencies": { "typescript": "^5.3.2" @@ -35024,13 +35022,13 @@ }, "packages/paima-sdk/paima-providers": { "name": "@paima/providers", - "version": "2.0.1", + "version": "2.1.0", "license": "See license file", "dependencies": { "@ethersproject/abstract-signer": "^5.7.0", "@metamask/providers": "^10.2.1", - "@paima/crypto": "2.0.1", - "@paima/utils": "2.0.1", + "@paima/crypto": "2.1.0", + "@paima/utils": "2.1.0", "@perawallet/connect": "^1.2.3", "@polkadot/extension-dapp": "^0.44.9", "@truffle/hdwallet-provider": "^2.1.15", @@ -35042,22 +35040,22 @@ }, "packages/paima-sdk/paima-sdk": { "name": "@paima/sdk", - "version": "2.0.1", + "version": "2.1.0", "license": "See license file", "dependencies": { - "@paima/concise": "2.0.1", - "@paima/crypto": "2.0.1", - "@paima/executors": "2.0.1", - "@paima/mw-core": "2.0.1", - "@paima/prando": "2.0.1", - "@paima/providers": "2.0.1", - "@paima/utils": "2.0.1" + "@paima/concise": "2.1.0", + "@paima/crypto": "2.1.0", + "@paima/executors": "2.1.0", + "@paima/mw-core": "2.1.0", + "@paima/prando": "2.1.0", + "@paima/providers": "2.1.0", + "@paima/utils": "2.1.0" }, "devDependencies": {} }, "packages/paima-sdk/paima-utils": { "name": "@paima/utils", - "version": "2.0.1", + "version": "2.1.0", "license": "See license file", "dependencies": { "@metamask/eth-json-rpc-middleware": "^12.0.0", diff --git a/packages/batcher/runtime/src/index.ts b/packages/batcher/runtime/src/index.ts index 7a3be22b5..bb516b69c 100644 --- a/packages/batcher/runtime/src/index.ts +++ b/packages/batcher/runtime/src/index.ts @@ -25,6 +25,15 @@ import type { ErrorCode, ErrorMessageFxn, GameInputValidatorCore } from '@paima/ import { initializePool } from './pg/pgPool.js'; import type { BatcherRuntimeInitializer } from './types.js'; +import { setLogger } from '@paima/utils'; +import * as fs from 'fs'; +import { parseSecurityYaml } from '@paima/utils-backend'; + +setLogger(s => { + try { + fs.appendFileSync('./logs.log', `${s}\n`); + } catch (e) {} +}); const MINIMUM_INTER_CATCH_PERIOD = 1000; let batchedTransactionPosterReference: BatchedTransactionPoster | null = null; @@ -127,6 +136,7 @@ async function main(): Promise { if (!checkConfig()) { return; } + await parseSecurityYaml(); const privateKey = ENV.BATCHER_PRIVATE_KEY; diff --git a/packages/batcher/runtime/tsconfig.json b/packages/batcher/runtime/tsconfig.json index a4088e531..c49e6c877 100644 --- a/packages/batcher/runtime/tsconfig.json +++ b/packages/batcher/runtime/tsconfig.json @@ -11,5 +11,7 @@ { "path": "../utils" }, { "path": "../batcher-transaction-poster" }, { "path": "../../paima-sdk/paima-providers/tsconfig.build.json" }, + { "path": "../../paima-sdk/paima-utils/tsconfig.build.json" }, + { "path": "../../node-sdk/paima-utils-backend" }, ] } diff --git a/packages/engine/paima-standalone/src/index.ts b/packages/engine/paima-standalone/src/index.ts index bfea7e1b8..0934f782c 100644 --- a/packages/engine/paima-standalone/src/index.ts +++ b/packages/engine/paima-standalone/src/index.ts @@ -4,6 +4,7 @@ import { argumentRouter } from './utils/input.js'; import * as fs from 'fs'; import { setLogger } from '@paima/utils'; +import { parseSecurityYaml } from '@paima/utils-backend'; setLogger(s => { try { @@ -15,6 +16,7 @@ setLogger(s => { config({ path: `${process.cwd()}/.env.${process.env.NODE_ENV || 'development'}` }); async function main(): Promise { + await parseSecurityYaml(); await argumentRouter(); } diff --git a/packages/engine/paima-standalone/tsconfig.json b/packages/engine/paima-standalone/tsconfig.json index 5fe708713..e6b436fd7 100644 --- a/packages/engine/paima-standalone/tsconfig.json +++ b/packages/engine/paima-standalone/tsconfig.json @@ -13,5 +13,6 @@ { "path": "../../paima-sdk/paima-utils/tsconfig.build.json" }, { "path": "../paima-funnel" }, { "path": "../paima-rest/tsconfig.build.json" }, + { "path": "../../node-sdk/paima-utils-backend" }, ] } diff --git a/packages/node-sdk/paima-utils-backend/src/index.ts b/packages/node-sdk/paima-utils-backend/src/index.ts index 3a71f0efb..0bfe68ff8 100644 --- a/packages/node-sdk/paima-utils-backend/src/index.ts +++ b/packages/node-sdk/paima-utils-backend/src/index.ts @@ -1,5 +1,6 @@ import Crypto from 'crypto'; +export { parseSecurityYaml } from './security.js'; export * from './cde-access.js'; export type * from './types.js'; diff --git a/packages/node-sdk/paima-utils-backend/src/security.ts b/packages/node-sdk/paima-utils-backend/src/security.ts new file mode 100644 index 000000000..7f3011e28 --- /dev/null +++ b/packages/node-sdk/paima-utils-backend/src/security.ts @@ -0,0 +1,10 @@ +import { ENV, parseAndValidateYAML } from '@paima/utils'; +import * as fs from 'fs/promises'; + +export async function parseSecurityYaml(): Promise { + const namespace = ENV.SECURITY_NAMESPACE; + if (namespace.endsWith('.yml') || namespace.endsWith('.yaml')) { + const content = await fs.readFile(ENV.SECURITY_NAMESPACE, 'utf-8'); + parseAndValidateYAML(content); + } +} diff --git a/packages/node-sdk/paima-utils-backend/tsconfig.json b/packages/node-sdk/paima-utils-backend/tsconfig.json index 224b74c9b..f2fdfb4e4 100644 --- a/packages/node-sdk/paima-utils-backend/tsconfig.json +++ b/packages/node-sdk/paima-utils-backend/tsconfig.json @@ -8,5 +8,6 @@ "include": ["src/**/*"], "references": [ { "path": "../paima-db" }, + { "path": "../../paima-sdk/paima-utils/tsconfig.build.json" } ] } diff --git a/packages/paima-sdk/paima-utils/src/security/parse.ts b/packages/paima-sdk/paima-utils/src/security/parse.ts index cac41a63d..5956734fa 100644 --- a/packages/paima-sdk/paima-utils/src/security/parse.ts +++ b/packages/paima-sdk/paima-utils/src/security/parse.ts @@ -2,7 +2,6 @@ import type { Static } from '@sinclair/typebox'; import { Type } from '@sinclair/typebox'; import { Value } from '@sinclair/typebox/value'; import YAML from 'yaml'; -import * as fs from 'fs/promises'; import { ENV } from '../config.js'; const BlockSettings = Type.Object({ @@ -21,19 +20,22 @@ const Config = Type.Object({ /** Cache for file content so we don't have to re-read it from disk constantly */ let securityNamespaceConfig: undefined | Static; -async function loadAndValidateYAML(filename: string): Promise> { +async function loadAndValidateYAML(): Promise> { + // try checking the cache first + // note the cache may be set externally by a direct call to parseAndValidateYAML if (securityNamespaceConfig != null) return securityNamespaceConfig; // this ENV var is used to help with compilation of Paima for browser environments // since they can't access fs.readFile, // we instead (at compile time) read the file // and put the file content inside SECURITY_NAMESPACE_ROUTER - const fileContent = process.env.SECURITY_NAMESPACE_ROUTER - ? (JSON.parse(process.env.SECURITY_NAMESPACE_ROUTER) as string) - : await fs.readFile(filename, 'utf-8'); - return await parseAndValidateYAML(fileContent); + if (process.env.SECURITY_NAMESPACE_ROUTER != null) { + const fileContent = JSON.parse(process.env.SECURITY_NAMESPACE_ROUTER) as string; + return parseAndValidateYAML(fileContent); + } + throw new Error(`security namespace YAML specified, but wasn't initialized`); } -async function parseAndValidateYAML(fileContent: string): Promise> { +export function parseAndValidateYAML(fileContent: string): Static { if (securityNamespaceConfig != null) return securityNamespaceConfig; try { // Parse the YAML content into an object @@ -48,18 +50,15 @@ async function parseAndValidateYAML(fileContent: string): Promise { - const config = await loadAndValidateYAML(namespace); +async function getEntryFromFile(blockHeight: number): Promise { + const config = await loadAndValidateYAML(); let highestEntry: Static | null = null; for (const entry of config.namespace.read) { if ( @@ -79,7 +78,7 @@ export async function getReadNamespaces(blockHeight: number): Promise const entry = namespace.endsWith('.yml') || namespace.endsWith('.yaml') - ? await getEntryFromFile(namespace, blockHeight) + ? await getEntryFromFile(blockHeight) : [namespace]; // default if no entry matches @@ -102,7 +101,7 @@ export async function getWriteNamespace(): Promise { const entry = namespace.endsWith('.yml') || namespace.endsWith('.yaml') ? await (async (): Promise => { - const config = await loadAndValidateYAML(namespace); + const config = await loadAndValidateYAML(); return config.namespace.write; })() : namespace; diff --git a/packages/paima-sdk/paima-utils/test/security/index.test.ts b/packages/paima-sdk/paima-utils/test/security/index.test.ts index cf38af004..aaa0a89e1 100644 --- a/packages/paima-sdk/paima-utils/test/security/index.test.ts +++ b/packages/paima-sdk/paima-utils/test/security/index.test.ts @@ -1,5 +1,10 @@ import { describe, expect, test } from '@jest/globals'; -import { getReadNamespaces, getWriteNamespace } from '../../src/security/parse.js'; +import { + getReadNamespaces, + getWriteNamespace, + parseAndValidateYAML, +} from '../../src/security/parse.js'; +import * as fs from 'fs/promises'; const CONTRACT_ADDRESS = '0x35390c41200DD56Ac3A679a0c1EeA369444f3b60'; process.env.CONTRACT_ADDRESS = CONTRACT_ADDRESS; @@ -9,6 +14,10 @@ describe('Test if parsed', () => { inputs.forEach(([namespace, blockHeight, expectedResult]: [string, number, string[]]) => { test(`${namespace} at blockHeight=${blockHeight} to be ${expectedResult}`, async () => { process.env.SECURITY_NAMESPACE = namespace; + if (namespace.endsWith('yml')) { + const content = await fs.readFile(process.env.SECURITY_NAMESPACE, 'utf-8'); + parseAndValidateYAML(content); + } const result = await getReadNamespaces(blockHeight); expect(result).toEqual(expectedResult); });