diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml new file mode 100644 index 00000000..32dde589 --- /dev/null +++ b/.github/workflows/eslint.yml @@ -0,0 +1,19 @@ +name: ESLint + +on: [pull_request] + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: Install NPM dependencies + run: | + npm ci + npm install -g typescript + + - name: Run ESlint + run: | + cd rt + npx eslint src diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml new file mode 100644 index 00000000..f1acf90a --- /dev/null +++ b/.github/workflows/prettier.yml @@ -0,0 +1,19 @@ +name: Prettier + +on: [pull_request] + +jobs: + format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: Install NPM dependencies + run: | + npm ci + npm install -g typescript + + - name: Run Prettier + run: | + cd rt + npx prettier --check src diff --git a/package-lock.json b/package-lock.json index 084700e2..0d5b82c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,14 +39,20 @@ "yargs": "^17.7.2" }, "devDependencies": { + "@eslint/js": "^9.37.0", "@types/ws": "^8.18.1", "@types/yargs": "^17.0.33", + "eslint": "^9.37.0", + "globals": "^16.4.0", + "jiti": "^2.6.1", + "prettier": "3.6.2", "rollup": "^4.41.0", "rollup-plugin-babel-minify": "^10.0.0", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-json": "^4.0.0", "rollup-plugin-node-resolve": "^5.2.0", - "typescript": "^5.8.3" + "typescript": "^5.8.3", + "typescript-eslint": "^8.46.1" } }, "node_modules/@ampproject/remapping": { @@ -322,6 +328,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", @@ -437,6 +453,235 @@ "kuler": "^2.0.0" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz", + "integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/js": { + "version": "9.37.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.37.0.tgz", + "integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", + "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", @@ -1093,6 +1338,44 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@nodeutils/defaults-deep": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@nodeutils/defaults-deep/-/defaults-deep-1.1.0.tgz", @@ -1410,6 +1693,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/multicast-dns": { "version": "7.2.4", "resolved": "https://registry.npmjs.org/@types/multicast-dns/-/multicast-dns-7.2.4.tgz", @@ -1492,12 +1782,329 @@ "dev": true, "license": "MIT" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.1.tgz", + "integrity": "sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.46.1", + "@typescript-eslint/type-utils": "8.46.1", + "@typescript-eslint/utils": "8.46.1", + "@typescript-eslint/visitor-keys": "8.46.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.46.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.1.tgz", + "integrity": "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.46.1", + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1", + "@typescript-eslint/visitor-keys": "8.46.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.1.tgz", + "integrity": "sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.46.1", + "@typescript-eslint/types": "^8.46.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.1.tgz", + "integrity": "sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/visitor-keys": "8.46.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.1.tgz", + "integrity": "sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.1.tgz", + "integrity": "sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1", + "@typescript-eslint/utils": "8.46.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.1.tgz", + "integrity": "sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.1.tgz", + "integrity": "sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.46.1", + "@typescript-eslint/tsconfig-utils": "8.46.1", + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/visitor-keys": "8.46.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.1.tgz", + "integrity": "sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.1", + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz", + "integrity": "sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.1", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/abort-error": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/abort-error/-/abort-error-1.0.1.tgz", "integrity": "sha512-fxqCblJiIPdSXIUrxI0PL+eJG49QdP9SQ70qtB65MVAoMr2rASlOyAbJFOylfB467F/f+5BCLJJq58RYi7mGfg==", "license": "Apache-2.0 OR MIT" }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/aggregate-error": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", @@ -4290,6 +4897,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/camel-case": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", @@ -4685,6 +5302,21 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/cwd": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.9.1.tgz", @@ -4921,6 +5553,13 @@ "node": ">=0.10.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/default-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", @@ -5363,67 +6002,255 @@ "integrity": "sha512-WQQgFoML/sLgmhu9zTekYHZUJaPoa/fpVMQ8oxIuOvppzs70DxxyHZdAIjwcuuNDOVtNYsahhqtBbUvKwhRcGw==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.10.0" + } + }, + "node_modules/error-symbol": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/error-symbol/-/error-symbol-0.1.0.tgz", + "integrity": "sha512-VyjaKxUmeDX/m2lxm/aknsJ1GWDWUO2Ze2Ad8S1Pb9dykAm9TjSKp5CjrNyltYqZ5W/PO6TInAmO2/BfwMyT1g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.37.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz", + "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.4.0", + "@eslint/core": "^0.16.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.37.0", + "@eslint/plugin-kit": "^0.4.0", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/error-symbol": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/error-symbol/-/error-symbol-0.1.0.tgz", - "integrity": "sha512-VyjaKxUmeDX/m2lxm/aknsJ1GWDWUO2Ze2Ad8S1Pb9dykAm9TjSKp5CjrNyltYqZ5W/PO6TInAmO2/BfwMyT1g==", + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, "engines": { - "node": ">= 0.4" + "node": ">=10.13.0" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/eslint/node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "node_modules/eslint/node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "license": "MIT", + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -5439,6 +6266,42 @@ "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/estree-walker": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", @@ -5732,12 +6595,122 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fast-glob/node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-glob/node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob/node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob/node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "license": "MIT" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fecha": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", @@ -5793,6 +6766,19 @@ "node": ">=0.10.0" } }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/file-is-binary": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-is-binary/-/file-is-binary-1.0.0.tgz", @@ -5903,6 +6889,23 @@ "node": ">=0.10.0" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/first-chunk-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", @@ -5912,6 +6915,27 @@ "node": ">=0.10.0" } }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, "node_modules/fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", @@ -6335,13 +7359,16 @@ } }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/gopd": { @@ -6362,6 +7389,13 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/gray-matter": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-3.1.1.tgz", @@ -6579,6 +7613,16 @@ "node": ">=0.10.0" } }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/has-glob": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/has-glob/-/has-glob-0.1.1.tgz", @@ -6738,6 +7782,43 @@ ], "license": "BSD-3-Clause" }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/indent-string": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", @@ -7626,6 +8707,16 @@ "npm": ">=7.0.0" } }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7659,6 +8750,13 @@ "node": ">=6" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", @@ -7711,6 +8809,16 @@ "node": ">=0.6.0" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -7804,10 +8912,24 @@ "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "license": "MIT", "dependencies": { - "readable-stream": "^2.0.5" + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">= 0.6.3" + "node": ">= 0.8.0" } }, "node_modules/libp2p": { @@ -7905,6 +9027,22 @@ "node": ">=0.10.0" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -8099,6 +9237,13 @@ "integrity": "sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==", "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.pairs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash.pairs/-/lodash.pairs-3.0.1.tgz", @@ -8498,6 +9643,16 @@ "node": ">=0.10.0" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/micromatch": { "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", @@ -8692,6 +9847,13 @@ "node": ">=0.10.0" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, "node_modules/netmask": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", @@ -8961,6 +10123,24 @@ "node": ">=0.10.0" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ordered-read-streams": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", @@ -9016,6 +10196,38 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-retry": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", @@ -9066,6 +10278,19 @@ "node": ">=0.10.0" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-author": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-author/-/parse-author-1.0.0.tgz", @@ -9165,6 +10390,16 @@ "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", "license": "MIT" }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -9174,6 +10409,16 @@ "node": ">=0.10.0" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -9208,6 +10453,19 @@ "dev": true, "license": "ISC" }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/pkg-store": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/pkg-store/-/pkg-store-0.2.2.tgz", @@ -9394,6 +10652,16 @@ "node": ">=0.10.0" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", @@ -9403,6 +10671,22 @@ "node": ">=0.10.0" } }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-time": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-0.2.0.tgz", @@ -9716,6 +11000,27 @@ "node": ">=0.10.0" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/race-event": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/race-event/-/race-event-1.6.1.tgz", @@ -10034,6 +11339,16 @@ "node": ">=0.10.0" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/resolve-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-glob/-/resolve-glob-1.0.0.tgz", @@ -10269,6 +11584,17 @@ "node": ">= 4" } }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -10421,6 +11747,30 @@ "once": "^1.3.0" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -10539,6 +11889,29 @@ "node": ">=0.10.0" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -10879,6 +12252,19 @@ "node": ">=0.10.0" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/success-symbol": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/success-symbol/-/success-symbol-0.1.0.tgz", @@ -11236,6 +12622,29 @@ "node": ">=0.10.0" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/to-regex-range/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", @@ -11270,6 +12679,19 @@ "node": ">= 14.0.0" } }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -11288,6 +12710,19 @@ "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "license": "Unlicense" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/typescript": { "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", @@ -11302,6 +12737,30 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.1.tgz", + "integrity": "sha512-VHgijW803JafdSsDO8I761r3SHrgk4T00IdyQ+/UsthtgPRsBWQLqoSxOolxTpxRKi1kGXK0bSz4CoAc9ObqJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.46.1", + "@typescript-eslint/parser": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1", + "@typescript-eslint/utils": "8.46.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, "node_modules/uint8arraylist": { "version": "2.4.8", "resolved": "https://registry.npmjs.org/uint8arraylist/-/uint8arraylist-2.4.8.tgz", @@ -11844,6 +13303,22 @@ "npm": ">=7.0.0" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/winston": { "version": "3.17.0", "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz", @@ -11926,6 +13401,16 @@ "node": ">= 6" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -12055,6 +13540,19 @@ "engines": { "node": ">=12" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index c24e2ca7..d17b0677 100644 --- a/package.json +++ b/package.json @@ -42,13 +42,19 @@ "yargs": "^17.7.2" }, "devDependencies": { + "@eslint/js": "^9.37.0", "@types/ws": "^8.18.1", "@types/yargs": "^17.0.33", + "eslint": "^9.37.0", + "globals": "^16.4.0", + "jiti": "^2.6.1", + "prettier": "3.6.2", "rollup": "^4.41.0", "rollup-plugin-babel-minify": "^10.0.0", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-json": "^4.0.0", "rollup-plugin-node-resolve": "^5.2.0", - "typescript": "^5.8.3" + "typescript": "^5.8.3", + "typescript-eslint": "^8.46.1" } } diff --git a/rt/.prettierignore b/rt/.prettierignore new file mode 100644 index 00000000..9b9e2f1d --- /dev/null +++ b/rt/.prettierignore @@ -0,0 +1,2 @@ +# Ignore artifacts: +built diff --git a/rt/.prettierrc b/rt/.prettierrc new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/rt/.prettierrc @@ -0,0 +1 @@ +{} diff --git a/rt/Makefile b/rt/Makefile index ba32b88a..24045fb9 100644 --- a/rt/Makefile +++ b/rt/Makefile @@ -3,3 +3,15 @@ all: clean: rm -rf built + +format: + npx prettier --write src + +format/dry: + npx prettier --check src + +lint: + npx eslint --fix src + +lint/dry: + npx eslint src diff --git a/rt/eslint.config.mts b/rt/eslint.config.mts new file mode 100644 index 00000000..5849720a --- /dev/null +++ b/rt/eslint.config.mts @@ -0,0 +1,45 @@ +import js from "@eslint/js"; +import globals from "globals"; +import tseslint from "typescript-eslint"; +import { defineConfig } from "eslint/config"; + +export default defineConfig([ + { + files: ["**/*.{js,mjs,cjs,ts,mts,ct}"], + languageOptions: { + parserOptions: { + projectService: true, + }, + globals: globals.browser + }, + plugins: { js }, + extends: ["js/recommended"], + }, + ...tseslint.configs.recommendedTypeChecked, + ...tseslint.configs.strictTypeChecked, + ...tseslint.configs.stylisticTypeChecked, + { + rules: { + // End all lines with a semi colon + "semi": ["warn", "always"], + + // Do not allow trailing whitespace + "no-trailing-spaces": ["warn", { + skipBlankLines: false, + ignoreComments: false, + }], + + // Allow `console.log(...)` + "no-console": "off", + + // TODO: Disable indexed-types vs. `Record<.., ..>` since ESLint confuses + // them with the runtime records of the same name. + "@typescript-eslint/consistent-indexed-object-style": "off", + + // TODO: Enabling 'trailing commas' below adds lots of missing commas + // in the wrong places. + //"comma-dangle": ["warn", "always"], + "comma-dangle": "off", + }, + }, +]); diff --git a/rt/src/AbstractLevel.mts b/rt/src/AbstractLevel.mts index 85b642be..59a9addb 100644 --- a/rt/src/AbstractLevel.mts +++ b/rt/src/AbstractLevel.mts @@ -1,26 +1,25 @@ import { TroupeType } from "./TroupeTypes.mjs"; import { TroupeRawValue } from "./TroupeRawValue.mjs"; -export abstract class AbstractLevel > - implements TroupeRawValue { - isLevel: boolean = true ; - _troupeType: TroupeType = TroupeType.LEVEL +export abstract class AbstractLevel> + implements TroupeRawValue +{ + isLevel = true; + _troupeType: TroupeType = TroupeType.LEVEL; abstract dataLevel; - abstract stringRep (): string + abstract stringRep(): string; } - -export abstract class AbstractLevelSystem > { - abstract BOT : T - abstract TOP : T - abstract ROOT : T - abstract NULL : T - abstract lub (...ls:T[]) : T - lubs (ls:T[]) { - return this.lub(...ls); - } - abstract glb (a : T, b: T) : T - abstract flowsTo (a: T, b: T) : boolean - abstract actsFor (a: T, b: T) : boolean +export abstract class AbstractLevelSystem> { + abstract BOT: T; + abstract TOP: T; + abstract ROOT: T; + abstract NULL: T; + abstract lub(...ls: T[]): T; + lubs(ls: T[]) { + return this.lub(...ls); + } + abstract glb(a: T, b: T): T; + abstract flowsTo(a: T, b: T): boolean; + abstract actsFor(a: T, b: T): boolean; } - diff --git a/rt/src/Asserts.mts b/rt/src/Asserts.mts index 88ed0081..acf37056 100644 --- a/rt/src/Asserts.mts +++ b/rt/src/Asserts.mts @@ -1,281 +1,300 @@ -import { Thread, Capability } from './Thread.mjs'; +import { Thread, Capability } from "./Thread.mjs"; -import { isListFlagSet, isTupleFlagSet } from './ValuesUtil.mjs'; -import * as proc from './process.mjs'; +import { isListFlagSet, isTupleFlagSet } from "./ValuesUtil.mjs"; +import * as proc from "./process.mjs"; const ProcessID = proc.ProcessID; -import { AbstractLevel } from './AbstractLevel.mjs'; -import { Level } from './Level.mjs'; -import { Authority } from './Authority.mjs' -import * as levels from './Level.mjs'; -import { TroupeType } from './TroupeTypes.mjs'; +import { AbstractLevel } from "./AbstractLevel.mjs"; +import { Level } from "./Level.mjs"; +import { Authority } from "./Authority.mjs"; +import * as levels from "./Level.mjs"; +import { TroupeType } from "./TroupeTypes.mjs"; const actsFor = levels.actsFor; -import { getRuntimeObject } from './SysState.mjs'; -import { __nodeManager } from './NodeManager.mjs'; -import { TroupeAggregateRawValue, TroupeRawValue } from './TroupeRawValue.mjs'; +import { getRuntimeObject } from "./SysState.mjs"; +import { __nodeManager } from "./NodeManager.mjs"; +import { TroupeAggregateRawValue, TroupeRawValue } from "./TroupeRawValue.mjs"; // import { LVal } from './Lval'; function _thread() { - return getRuntimeObject().__sched.__currentThread + return getRuntimeObject().__sched.__currentThread; } -function __stringRep (v) { - if (v.stringRep) { - return v.stringRep() +function __stringRep(v) { + if (v.stringRep) { + return v.stringRep(); + } else { + let t = ""; + if (typeof v === "string") { + t = '"' + v.toString() + '"'; } else { - let t="" - if (typeof v === 'string') { - t = "\"" + v.toString() + "\"" - } else { - t = v.toString(); - } - return t + t = v.toString(); } + return t; + } } -let err = x => _thread().threadError(x) -export function assertIsAtom (x: any) { - _thread().raiseBlockingThreadLev(x.tlev) - if (x.val._troupeType != TroupeType.ATOM ) { - err ("value " + __stringRep(x) + " is not an atom") - } +const err = (x) => { + _thread().threadError(x); +}; +export function assertIsAtom(x: any) { + _thread().raiseBlockingThreadLev(x.tlev); + if (x.val._troupeType != TroupeType.ATOM) { + err("value " + __stringRep(x) + " is not an atom"); + } } -export function rawAssertIsNumber (x) { - if (typeof x != 'number') { - err("value " + __stringRep(x) + " is not a number") - } +export function rawAssertIsNumber(x) { + if (typeof x != "number") { + err("value " + __stringRep(x) + " is not a number"); + } } export function assertIsNumber(x: any) { - _thread().raiseBlockingThreadLev(x.tlev) - if (typeof x.val != 'number') { - err("value " + __stringRep(x) + " is not a number") - } + _thread().raiseBlockingThreadLev(x.tlev); + if (typeof x.val != "number") { + err("value " + __stringRep(x) + " is not a number"); + } } export function assertIsBoolean(x: any) { - _thread().raiseBlockingThreadLev(x.tlev); - if (typeof x.val != 'boolean') { - err("value " + __stringRep(x) + " is not a boolean") - } + _thread().raiseBlockingThreadLev(x.tlev); + if (typeof x.val != "boolean") { + err("value " + __stringRep(x) + " is not a boolean"); + } } -export function rawAssertIsBoolean(x:any) { - if (typeof x != 'boolean') { - err("value " + __stringRep(x) + " is not a boolean") - } +export function rawAssertIsBoolean(x: any) { + if (typeof x != "boolean") { + err("value " + __stringRep(x) + " is not a boolean"); + } } export function assertIsFunction(x: any, internal = false) { - _thread().raiseBlockingThreadLev(x.tlev); - rawAssertIsFunction (x.val, internal) + _thread().raiseBlockingThreadLev(x.tlev); + rawAssertIsFunction(x.val, internal); } export function rawAssertIsFunction(x, internal = false) { - if (x._troupeType != TroupeType.CLOSURE) { - _thread().threadError("value " + __stringRep(x) + " is not a function", internal) - } + if (x._troupeType != TroupeType.CLOSURE) { + _thread().threadError( + "value " + __stringRep(x) + " is not a function", + internal, + ); + } } - export function assertIsLocalObject(x: any) { - _thread().raiseBlockingThreadLev(x.tlev); - if (x.val._troupeType != TroupeType.LOCALOBJECT) { - err("value " + __stringRep(x) + " is not a local object") - } + _thread().raiseBlockingThreadLev(x.tlev); + if (x.val._troupeType != TroupeType.LOCALOBJECT) { + err("value " + __stringRep(x) + " is not a local object"); + } } export function assertIsHandler(x: any) { - _thread().raiseBlockingThreadLev(x.tlev); - if (x.val._troupeType != TroupeType.CLOSURE) { - err("value " + __stringRep(x) + " is not a handler") - } + _thread().raiseBlockingThreadLev(x.tlev); + if (x.val._troupeType != TroupeType.CLOSURE) { + err("value " + __stringRep(x) + " is not a handler"); + } } export function assertIsUnit(x: any) { - _thread().raiseBlockingThreadLev(x.tlev); - if (!x.val._is_unit) { - err("value " + __stringRep(x) + " is not unit") - } + _thread().raiseBlockingThreadLev(x.tlev); + if (!x.val._is_unit) { + err("value " + __stringRep(x) + " is not unit"); + } } - export function assertIsListOrTuple(x: any) { - _thread().raiseBlockingThreadLev(x.lev);; - if (!((isListFlagSet(x.val) || isTupleFlagSet(x.val)))) { - err("value " + __stringRep(x) + " is not a list or tuple") - } + _thread().raiseBlockingThreadLev(x.lev); + if (!(isListFlagSet(x.val) || isTupleFlagSet(x.val))) { + err("value " + __stringRep(x) + " is not a list or tuple"); + } } export function assertIsList(x: any) { - _thread().raiseBlockingThreadLev(x.lev);; - rawAssertIsList(x.val) + _thread().raiseBlockingThreadLev(x.lev); + rawAssertIsList(x.val); } -export function rawAssertIsList (x:any) { - if (!isListFlagSet(x)) { - err("value " + __stringRep(x) + " is not a list") - } +export function rawAssertIsList(x: any) { + if (!isListFlagSet(x)) { + err("value " + __stringRep(x) + " is not a list"); + } } export function assertIsNTuple(x: any, n: number) { - _thread().raiseBlockingThreadLev(x.lev); - if (!(Array.isArray(x.val) && isTupleFlagSet(x.val) && x.val.length == n)) { - err("value " + __stringRep(x) + " is not a " + n + "-tuple") - } + _thread().raiseBlockingThreadLev(x.lev); + if (!(Array.isArray(x.val) && isTupleFlagSet(x.val) && x.val.length == n)) { + err("value " + __stringRep(x) + " is not a " + n + "-tuple"); + } } - -export function assertIsNTupleR3 (x:TroupeRawValue, lev:Level, tlev:Level, n:number) { - _thread().raiseBlockingThreadLev(lev); - if (!(Array.isArray(x) && isTupleFlagSet(x) && x.length == n)) { - err("value " + __stringRep(x) + " is not a " + n + "-tuple") - } +export function assertIsNTupleR3( + x: TroupeRawValue, + lev: Level, + tlev: Level, + n: number, +) { + _thread().raiseBlockingThreadLev(lev); + if (!(Array.isArray(x) && isTupleFlagSet(x) && x.length == n)) { + err("value " + __stringRep(x) + " is not a " + n + "-tuple"); + } } -export function rawAssertIsTuple (x) { - if (!(Array.isArray(x) && isTupleFlagSet(x) )) { - err("value " + __stringRep(x) + " is not a tuple") - } +export function rawAssertIsTuple(x) { + if (!(Array.isArray(x) && isTupleFlagSet(x))) { + err("value " + __stringRep(x) + " is not a tuple"); + } } /** * Assumes `x` is a tuple and asserts it has at least length `n`. */ -export function rawAssertTupleLengthGreaterThan (x, n: number) { - if (x.length <= n) { - err("Index out of bounds: tuple " + __stringRep(x) + " does not have length more than " + n) - } +export function rawAssertTupleLengthGreaterThan(x, n: number) { + if (x.length <= n) { + err( + "Index out of bounds: tuple " + + __stringRep(x) + + " does not have length more than " + + n, + ); + } } - -export function rawAssertRecordHasField (x, field: string) { - if (!x.hasField(field)) { - err (`record ${__stringRep(x)} does not have field \'${field}\'`) - } +export function rawAssertRecordHasField(x, field: string) { + if (!x.hasField(field)) { + err(`record ${__stringRep(x)} does not have field \'${field}\'`); + } } - -export function assertIsRecord (x: any) { - _thread().raiseBlockingThreadLev(x.lev); - if (x.val._troupeType != TroupeType.RECORD) { - err (`value ${__stringRep(x)} is not a record`) - } +export function assertIsRecord(x: any) { + _thread().raiseBlockingThreadLev(x.lev); + if (x.val._troupeType != TroupeType.RECORD) { + err(`value ${__stringRep(x)} is not a record`); + } } -export function rawAssertIsRecord (x: any) { - if (x._troupeType != TroupeType.RECORD) { - err (`value ${__stringRep(x)} is not a record`) - } +export function rawAssertIsRecord(x: any) { + if (x._troupeType != TroupeType.RECORD) { + err(`value ${__stringRep(x)} is not a record`); + } } export function assertIsString(x: any) { - _thread().raiseBlockingThreadLev(x.tlev); - if (typeof x.val != 'string') { - err("value " + __stringRep(x) + " is not a string") - } + _thread().raiseBlockingThreadLev(x.tlev); + if (typeof x.val != "string") { + err("value " + __stringRep(x) + " is not a string"); + } } -export function rawAssertIsString(x:any) { - if (typeof x != 'string') { - err("value " + __stringRep(x) + " is not a string") - } +export function rawAssertIsString(x: any) { + if (typeof x != "string") { + err("value " + __stringRep(x) + " is not a string"); + } } -export function rawAssertNotZero(x:any) { - if (x === 0) { - err("Division by zero error") - } +export function rawAssertNotZero(x: any) { + if (x === 0) { + err("Division by zero error"); + } } - export function assertIsNode(x: any) { - _thread().raiseBlockingThreadLev(x.tlev); - if (typeof x.val != 'string') { - err("value " + __stringRep(x) + " is not a node string") // todo: check for it being a proper nodeid format? - } - if (x.val.startsWith("@")) { - if (!__nodeManager.aliases[x.val.substring(1)]) { - err(`${x.val} is not a defined alias`) - } + _thread().raiseBlockingThreadLev(x.tlev); + if (typeof x.val != "string") { + err("value " + __stringRep(x) + " is not a node string"); // todo: check for it being a proper nodeid format? + } + if (x.val.startsWith("@")) { + if (!__nodeManager.aliases[x.val.substring(1)]) { + err(`${x.val} is not a defined alias`); } + } } export function assertIsProcessId(x: any) { - _thread().raiseBlockingThreadLev(x.tlev); - if (!(x.val instanceof ProcessID)) { - err("value " + __stringRep(x) + " is not a process id") - } + _thread().raiseBlockingThreadLev(x.tlev); + if (!(x.val instanceof ProcessID)) { + err("value " + __stringRep(x) + " is not a process id"); + } } - export function assertIsCapability(x: any) { - _thread().raiseBlockingThreadLev(x.tlev); - if (!(x.val instanceof Capability)) { - err("value " + __stringRep(x) + " is not a capability of lowering the mailbox clearance") - } + _thread().raiseBlockingThreadLev(x.tlev); + if (!(x.val instanceof Capability)) { + err( + "value " + + __stringRep(x) + + " is not a capability of lowering the mailbox clearance", + ); + } } export function assertIsLevel(x: any) { - _thread().raiseBlockingThreadLev(x.tlev); - if (!(x.val instanceof AbstractLevel)) { - err("value " + __stringRep(x) + " is not a level"); - } + _thread().raiseBlockingThreadLev(x.tlev); + if (!(x.val instanceof AbstractLevel)) { + err("value " + __stringRep(x) + " is not a level"); + } } -export function rawAssertIsLevel (x:any) { - if (!(x instanceof AbstractLevel)) { - err("value " + __stringRep(x) + " is not a level"); - } +export function rawAssertIsLevel(x: any) { + if (!(x instanceof AbstractLevel)) { + err("value " + __stringRep(x) + " is not a level"); + } } export function assertIsRootAuthority(x: any) { - let isTop = actsFor(x.val.authorityLevel, levels.ROOT); - if (!isTop) { - let errorMessage = - "Provided authority is not TOP\n" + - ` | level of the provided authority: ${x.val.authorityLevel.stringRep()}` - err(errorMessage); - } + const isTop = actsFor(x.val.authorityLevel, levels.ROOT); + if (!isTop) { + const errorMessage = + "Provided authority is not TOP\n" + + ` | level of the provided authority: ${x.val.authorityLevel.stringRep()}`; + err(errorMessage); + } } export function assertIsAuthority(x: any) { - _thread().raiseBlockingThreadLev(x.tlev); - if (!(x.val instanceof Authority)) { - err("value " + __stringRep(x) + " is not a authority"); - } + _thread().raiseBlockingThreadLev(x.tlev); + if (!(x.val instanceof Authority)) { + err("value " + __stringRep(x) + " is not a authority"); + } } export function assertIsAuthorityR3(x, lev, tlev) { - _thread().raiseBlockingThreadLev(x.tlev); - if (!(x instanceof Authority)){ - err("value " + __stringRep(x) + " is not a authority"); - } + _thread().raiseBlockingThreadLev(x.tlev); + if (!(x instanceof Authority)) { + err("value " + __stringRep(x) + " is not a authority"); + } } export function assertIsEnv(x: any) { - _thread().raiseBlockingThreadLev(x.tlev); - if (!(x.val._is_rt_env)) { - err("value " + __stringRep(x) + " is not an environment"); - } + _thread().raiseBlockingThreadLev(x.tlev); + if (!x.val._is_rt_env) { + err("value " + __stringRep(x) + " is not an environment"); + } } export function assertNormalState(s: string) { - if (!_thread().handlerState.isNormal()) { - err("invalid handler state in " + s + " -- side effects are prohbited in handler pattern matching or sandboxed code") - } + if (!_thread().handlerState.isNormal()) { + err( + "invalid handler state in " + + s + + " -- side effects are prohbited in handler pattern matching or sandboxed code", + ); + } } export function assertDeclassificationAllowed(s: string) { - if (!_thread().handlerState.declassificationAllowed()) { - err("invalid handler state in " + s + ": declassification prohibited in handler pattern matching") - } + if (!_thread().handlerState.declassificationAllowed()) { + err( + "invalid handler state in " + + s + + ": declassification prohibited in handler pattern matching", + ); + } } - export function assertPairAreNumbers(x: any, y: any) { - assertIsNumber(x); - assertIsNumber(y); + assertIsNumber(x); + assertIsNumber(y); } /* @@ -289,11 +308,16 @@ export function assertPairAreStringsOrNumbers(x: any, y: any) { } */ -export function rawAssertPairsAreStringsOrNumbers (x:any, y:any) { - switch (typeof x) { - case 'number': rawAssertIsNumber(y); break - case 'string': rawAssertIsString(y); break - default: err("value " + __stringRep(x) + " is not a number or a string") - // default: err("values " + __stringRep(x) + " and " + __stringRep(y) + " are of different types") - } +export function rawAssertPairsAreStringsOrNumbers(x: any, y: any) { + switch (typeof x) { + case "number": + rawAssertIsNumber(y); + break; + case "string": + rawAssertIsString(y); + break; + default: + err("value " + __stringRep(x) + " is not a number or a string"); + // default: err("values " + __stringRep(x) + " and " + __stringRep(y) + " are of different types") + } } diff --git a/rt/src/Atom.mts b/rt/src/Atom.mts index 45623b9e..d55d8ca6 100644 --- a/rt/src/Atom.mts +++ b/rt/src/Atom.mts @@ -1,22 +1,22 @@ -import runId from "./runId.mjs" -import { TroupeType } from "./TroupeTypes.mjs" +import runId from "./runId.mjs"; +import { TroupeType } from "./TroupeTypes.mjs"; import { TroupeRawValue } from "./TroupeRawValue.mjs"; -import * as levels from './Level.mjs' +import * as levels from "./Level.mjs"; -let rt_uuid = runId +const rt_uuid = runId; -export class Atom implements TroupeRawValue { - atom: string +export class Atom implements TroupeRawValue { + atom: string; creation_uuid: any; - _troupeType = TroupeType.ATOM - dataLevel = levels.BOT - - constructor (name:string, creation_uuid = rt_uuid) { - this.atom = name; - this.creation_uuid = creation_uuid + _troupeType = TroupeType.ATOM; + dataLevel = levels.BOT; + + constructor(name: string, creation_uuid = rt_uuid) { + this.atom = name; + this.creation_uuid = creation_uuid; } - stringRep (_omitLevels = false) { - return this.atom - } + stringRep(_omitLevels = false) { + return this.atom; + } } diff --git a/rt/src/Authority.mts b/rt/src/Authority.mts index 76d8af7e..f49a8c7f 100644 --- a/rt/src/Authority.mts +++ b/rt/src/Authority.mts @@ -4,18 +4,17 @@ import { TroupeRawValue } from "./TroupeRawValue.mjs"; import { TroupeType } from "./TroupeTypes.mjs"; export class Authority implements TroupeRawValue { - authorityLevel: Level; - stringRep: () => string; - _troupeType = TroupeType.AUTHORITY - dataLevel = BOT; - constructor (authorityLevel: Level) { - this.authorityLevel = authorityLevel - this.stringRep = this.toString; - } + authorityLevel: Level; + stringRep: () => string; + _troupeType = TroupeType.AUTHORITY; + dataLevel = BOT; + constructor(authorityLevel: Level) { + this.authorityLevel = authorityLevel; + this.stringRep = this.toString; + } - toString () { - let x = this.authorityLevel.stringRep(); - return "!" + x; - } + toString() { + const x = this.authorityLevel.stringRep(); + return "!" + x; + } } - diff --git a/rt/src/BaseFunction.mts b/rt/src/BaseFunction.mts index df9c4210..131b595e 100644 --- a/rt/src/BaseFunction.mts +++ b/rt/src/BaseFunction.mts @@ -1,43 +1,44 @@ -import {ClosureType, TroupeType} from './TroupeTypes.mjs' -import {TroupeAggregateRawValue} from './TroupeRawValue.mjs' -import * as levels from './Level.mjs' -import { getRuntimeObject } from './SysState.mjs' +import { ClosureType, TroupeType } from "./TroupeTypes.mjs"; +import { TroupeAggregateRawValue } from "./TroupeRawValue.mjs"; +import * as levels from "./Level.mjs"; +import { getRuntimeObject } from "./SysState.mjs"; -export function BaseFunctionWithExplicitArg(f, name = null) : TroupeAggregateRawValue{ - - let closure : any = () => { - let thread = getRuntimeObject().$t; - return f (thread.arg_as_lval); - } +export function BaseFunctionWithExplicitArg( + f, + name = null, +): TroupeAggregateRawValue { + const closure: any = () => { + const thread = getRuntimeObject().$t; + return f(thread.arg_as_lval); + }; closure.env = null; - closure.fun = f // TODO: 2025-07-28;AA (this is likely redundant) - closure._troupeType = TroupeType.CLOSURE; + closure.fun = f; // TODO: 2025-07-28;AA (this is likely redundant) + closure._troupeType = TroupeType.CLOSURE; closure._closureType = ClosureType.BUILTINFN; closure.stringRep = () => { if (name) { - return `` + return ``; } else { - return "" + return ""; } - } - closure.dataLevel = levels.BOT; + }; + closure.dataLevel = levels.BOT; return closure; } - -export function ServiceFunction (f, name=null) : TroupeAggregateRawValue { - let closure : any = () => f (); +export function ServiceFunction(f, name = null): TroupeAggregateRawValue { + const closure: any = () => f(); closure.env = null; - closure.fun = f // TODO: 2025-07-28;AA (this is likely redundant) - closure._troupeType = TroupeType.CLOSURE; + closure.fun = f; // TODO: 2025-07-28;AA (this is likely redundant) + closure._troupeType = TroupeType.CLOSURE; closure._closureType = ClosureType.SERVICEFN; closure.stringRep = () => { if (name) { - return `` + return ``; } else { - return "" + return ""; } - } - closure.dataLevel = levels.BOT; - return closure; -} \ No newline at end of file + }; + closure.dataLevel = levels.BOT; + return closure; +} diff --git a/rt/src/Constants.mts b/rt/src/Constants.mts index 0903ea49..d2f922d5 100644 --- a/rt/src/Constants.mts +++ b/rt/src/Constants.mts @@ -1 +1 @@ -export const SYSTEM_PROCESS_STRING = "system-process" \ No newline at end of file +export const SYSTEM_PROCESS_STRING = "system-process"; diff --git a/rt/src/DowngradeEnums.mts b/rt/src/DowngradeEnums.mts index 1d661b78..363bd8ed 100644 --- a/rt/src/DowngradeEnums.mts +++ b/rt/src/DowngradeEnums.mts @@ -1,47 +1,50 @@ -import { Level } from './Level.mjs'; - +import { Level } from "./Level.mjs"; export enum DowngradeKind { - VALUE = 1, - BLOCKING = 2, - MAILBOX = 3 + VALUE = 1, + BLOCKING = 2, + MAILBOX = 3, } - + export enum DowngradeDimension { - CONFIDENTIALITY = 1, - INTEGRITY = 2, + CONFIDENTIALITY = 1, + INTEGRITY = 2, } export enum DowngradeErrorReason { - INTEGRITY_MISMATCH = 1, - CONFIDENTIALITY_MISMATCH = 2, - INSUFFICIENT_AUTHORITY = 3, - BLOCKING_LEVEL_MISMATCH = 4 + INTEGRITY_MISMATCH = 1, + CONFIDENTIALITY_MISMATCH = 2, + INSUFFICIENT_AUTHORITY = 3, + BLOCKING_LEVEL_MISMATCH = 4, } -export type SuccessfulDowngradeResult = { - kind: "SUCCESS"; -}; +export interface SuccessfulDowngradeResult { + kind: "SUCCESS"; +} -export type FailedDowngradeResult = { - kind: "FAILURE"; - reason: DowngradeErrorReason; -}; +export interface FailedDowngradeResult { + kind: "FAILURE"; + reason: DowngradeErrorReason; +} export type DowngradeResult = SuccessfulDowngradeResult | FailedDowngradeResult; -export const DowngradeResultSuccess: SuccessfulDowngradeResult = { kind: "SUCCESS" }; +export const DowngradeResultSuccess: SuccessfulDowngradeResult = { + kind: "SUCCESS", +}; -export function DowngradeError(reason: DowngradeErrorReason): FailedDowngradeResult { - return { kind: "FAILURE", reason }; +export function DowngradeError( + reason: DowngradeErrorReason, +): FailedDowngradeResult { + return { kind: "FAILURE", reason }; } -export type ValidateDowngradeParams = { - downgradeKind: DowngradeKind; - levFrom: Level; - levTo: Level; - authorityLevel: Level; - downgradeDimension: DowngradeDimension; - blockLevel?: Level ; - operationDescription?: string; -}; +export interface ValidateDowngradeParams { + downgradeKind: DowngradeKind; + levFrom: Level; + levTo: Level; + authorityLevel: Level; + downgradeDimension: DowngradeDimension; + blockLevel?: Level; + operationDescription?: string; +} diff --git a/rt/src/DowngradeFormatter.mts b/rt/src/DowngradeFormatter.mts index afce7fac..5f938633 100644 --- a/rt/src/DowngradeFormatter.mts +++ b/rt/src/DowngradeFormatter.mts @@ -1,138 +1,279 @@ -import { Level } from './Level.mjs'; -import { DC_INTG_LITERALS, DC_CONF_LITERALS } from './levels/DCLabels/dcl_pp_config.mjs'; -import { DowngradeKind, DowngradeDimension, ValidateDowngradeParams, DowngradeErrorReason } from './DowngradeEnums.mjs'; -import { ImplementationError } from './TroupeError.mjs'; +import { Level } from "./Level.mjs"; +import { + DC_INTG_LITERALS, + DC_CONF_LITERALS, +} from "./levels/DCLabels/dcl_pp_config.mjs"; +import { + DowngradeKind, + DowngradeDimension, + ValidateDowngradeParams, + DowngradeErrorReason, +} from "./DowngradeEnums.mjs"; +import { ImplementationError } from "./TroupeError.mjs"; // Individual formatter functions (formatIntegrityMismatchMsg, etc.) remain here and are exported. -export function formatIntegrityMismatchMsg(operationDescription: string, dataLevel: Level, targetLevel: Level): string { - return `Integrity level mismatch for ${operationDescription}\n` + - ` | integrity level of the data: ${dataLevel.integrity.stringRep(DC_INTG_LITERALS)}\n` + - ` | integrity level of the target: ${targetLevel.integrity.stringRep(DC_INTG_LITERALS)}`; +export function formatIntegrityMismatchMsg( + operationDescription: string, + dataLevel: Level, + targetLevel: Level, +): string { + return ( + `Integrity level mismatch for ${operationDescription}\n` + + ` | integrity level of the data: ${dataLevel.integrity.stringRep(DC_INTG_LITERALS)}\n` + + ` | integrity level of the target: ${targetLevel.integrity.stringRep(DC_INTG_LITERALS)}` + ); } -export function formatConfidentialityMismatchMsg(operationDescription: string, dataLevel: Level, targetLevel: Level): string { - return `Confidentiality level mismatch for ${operationDescription}\n` + - ` | confidentiality level of the data: ${dataLevel.confidentiality.stringRep(DC_CONF_LITERALS)}\n` + - ` | confidentiality level of the target: ${targetLevel.confidentiality.stringRep(DC_CONF_LITERALS)}`; +export function formatConfidentialityMismatchMsg( + operationDescription: string, + dataLevel: Level, + targetLevel: Level, +): string { + return ( + `Confidentiality level mismatch for ${operationDescription}\n` + + ` | confidentiality level of the data: ${dataLevel.confidentiality.stringRep(DC_CONF_LITERALS)}\n` + + ` | confidentiality level of the target: ${targetLevel.confidentiality.stringRep(DC_CONF_LITERALS)}` + ); } -export function formatPiniBlockingLevelMismatchMsg(operationDescription: string, currentBlockingLevel: Level, targetBlockingLevel: Level): string { - return `Current blocking level does not flow to the target level of the ${operationDescription}\n` + - ` | current blocking level: ${currentBlockingLevel.stringRep()}\n` + - ` | target blocking level: ${targetBlockingLevel.stringRep()}`; +export function formatPiniBlockingLevelMismatchMsg( + operationDescription: string, + currentBlockingLevel: Level, + targetBlockingLevel: Level, +): string { + return ( + `Current blocking level does not flow to the target level of the ${operationDescription}\n` + + ` | current blocking level: ${currentBlockingLevel.stringRep()}\n` + + ` | target blocking level: ${targetBlockingLevel.stringRep()}` + ); } -export function formatPiniInsufficientAuthorityMsg(operationDescription: string, fromBlockingLevel: Level, authorityValLevel: Level, toBlockingLevel: Level): string { - return `Not enough authority for ${operationDescription}\n` + - ` | from level of the blocking level: ${fromBlockingLevel.stringRep()}\n` + - ` | level of the authority: ${authorityValLevel.stringRep()}\n` + - ` | to level of the blocking level: ${toBlockingLevel.stringRep()}`; +export function formatPiniInsufficientAuthorityMsg( + operationDescription: string, + fromBlockingLevel: Level, + authorityValLevel: Level, + toBlockingLevel: Level, +): string { + return ( + `Not enough authority for ${operationDescription}\n` + + ` | from level of the blocking level: ${fromBlockingLevel.stringRep()}\n` + + ` | level of the authority: ${authorityValLevel.stringRep()}\n` + + ` | to level of the blocking level: ${toBlockingLevel.stringRep()}` + ); } -export function formatMboxBlockingLevelMismatchMsg(currentBlockingLevel: Level, targetMailboxLevel: Level): string { - return `Current blocking level does not flow to the target level for lowering mailbox clearance\n` + - ` | current blocking level: ${currentBlockingLevel.stringRep()}\n` + - ` | target mailbox level: ${targetMailboxLevel.stringRep()}`; +export function formatMboxBlockingLevelMismatchMsg( + currentBlockingLevel: Level, + targetMailboxLevel: Level, +): string { + return ( + `Current blocking level does not flow to the target level for lowering mailbox clearance\n` + + ` | current blocking level: ${currentBlockingLevel.stringRep()}\n` + + ` | target mailbox level: ${targetMailboxLevel.stringRep()}` + ); } -export function formatMboxInsufficientAuthorityMsg(authorityProvidedLevel: Level, currentMailboxLevel: Level, targetMailboxLevel: Level): string { - return `Insufficient authority for lowering the mailbox clearance\n` + - `| authority provided: ${authorityProvidedLevel.stringRep()}\n` + - `| current level of the mailbox: ${currentMailboxLevel.stringRep()}\n` + - `| target level of the mailbox: ${targetMailboxLevel.stringRep()}`; +export function formatMboxInsufficientAuthorityMsg( + authorityProvidedLevel: Level, + currentMailboxLevel: Level, + targetMailboxLevel: Level, +): string { + return ( + `Insufficient authority for lowering the mailbox clearance\n` + + `| authority provided: ${authorityProvidedLevel.stringRep()}\n` + + `| current level of the mailbox: ${currentMailboxLevel.stringRep()}\n` + + `| target level of the mailbox: ${targetMailboxLevel.stringRep()}` + ); } -export function formatValueInsufficientAuthorityMsg(operationDescription: string, dataLevel: Level, authorityLevel: Level, targetLevel: Level): string { - return `Not enough authority for ${operationDescription}\n` + - ` | level of the data: ${dataLevel.stringRep()}\n` + - ` | level of the authority: ${authorityLevel.stringRep()}\n` + - ` | target level of the ${operationDescription}: ${targetLevel.stringRep()}`; +export function formatValueInsufficientAuthorityMsg( + operationDescription: string, + dataLevel: Level, + authorityLevel: Level, + targetLevel: Level, +): string { + return ( + `Not enough authority for ${operationDescription}\n` + + ` | level of the data: ${dataLevel.stringRep()}\n` + + ` | level of the authority: ${authorityLevel.stringRep()}\n` + + ` | target level of the ${operationDescription}: ${targetLevel.stringRep()}` + ); } // Non-exported helper for BLOCKING kind function getBlockDowngradeErrorMessageForReason( - reason: DowngradeErrorReason, - operationDescription: string, - levFrom: Level, - levTo: Level, - authorityLevel: Level + reason: DowngradeErrorReason, + operationDescription: string, + levFrom: Level, + levTo: Level, + authorityLevel: Level, ): string { - switch (reason) { - case DowngradeErrorReason.INTEGRITY_MISMATCH: return formatIntegrityMismatchMsg(operationDescription, levFrom, levTo); - case DowngradeErrorReason.CONFIDENTIALITY_MISMATCH: return formatConfidentialityMismatchMsg(operationDescription, levFrom, levTo); - case DowngradeErrorReason.BLOCKING_LEVEL_MISMATCH: return formatPiniBlockingLevelMismatchMsg(operationDescription, levFrom, levTo); - case DowngradeErrorReason.INSUFFICIENT_AUTHORITY: return formatPiniInsufficientAuthorityMsg(operationDescription, levFrom, authorityLevel, levTo); - default: - const _exhaustiveBlockReason: never = reason; - throw new ImplementationError(`Unexpected reason for BLOCKING: ${_exhaustiveBlockReason}`); - } + switch (reason) { + case DowngradeErrorReason.INTEGRITY_MISMATCH: + return formatIntegrityMismatchMsg(operationDescription, levFrom, levTo); + case DowngradeErrorReason.CONFIDENTIALITY_MISMATCH: + return formatConfidentialityMismatchMsg( + operationDescription, + levFrom, + levTo, + ); + case DowngradeErrorReason.BLOCKING_LEVEL_MISMATCH: + return formatPiniBlockingLevelMismatchMsg( + operationDescription, + levFrom, + levTo, + ); + case DowngradeErrorReason.INSUFFICIENT_AUTHORITY: + return formatPiniInsufficientAuthorityMsg( + operationDescription, + levFrom, + authorityLevel, + levTo, + ); + default: + const _exhaustiveBlockReason: never = reason; + throw new ImplementationError( + `Unexpected reason for BLOCKING: ${_exhaustiveBlockReason}`, + ); + } } // Non-exported helper for MAILBOX kind function getMailboxDowngradeErrorMessageForReason( - reason: DowngradeErrorReason, - operationDescription: string, - levFrom: Level, - levTo: Level, - authorityLevel: Level, - currentBlockingLevelForCheck: Level + reason: DowngradeErrorReason, + operationDescription: string, + levFrom: Level, + levTo: Level, + authorityLevel: Level, + currentBlockingLevelForCheck: Level, ): string { - switch (reason) { - case DowngradeErrorReason.INTEGRITY_MISMATCH: return formatIntegrityMismatchMsg(operationDescription, levFrom, levTo); - case DowngradeErrorReason.CONFIDENTIALITY_MISMATCH: return formatConfidentialityMismatchMsg(operationDescription, levFrom, levTo); - case DowngradeErrorReason.BLOCKING_LEVEL_MISMATCH: return formatMboxBlockingLevelMismatchMsg(currentBlockingLevelForCheck, levTo); - case DowngradeErrorReason.INSUFFICIENT_AUTHORITY: return formatMboxInsufficientAuthorityMsg(authorityLevel, levFrom, levTo); - default: - const _exhaustiveMboxReason: never = reason; - throw new ImplementationError(`Unexpected reason for MAILBOX: ${_exhaustiveMboxReason}`); - } + switch (reason) { + case DowngradeErrorReason.INTEGRITY_MISMATCH: + return formatIntegrityMismatchMsg(operationDescription, levFrom, levTo); + case DowngradeErrorReason.CONFIDENTIALITY_MISMATCH: + return formatConfidentialityMismatchMsg( + operationDescription, + levFrom, + levTo, + ); + case DowngradeErrorReason.BLOCKING_LEVEL_MISMATCH: + return formatMboxBlockingLevelMismatchMsg( + currentBlockingLevelForCheck, + levTo, + ); + case DowngradeErrorReason.INSUFFICIENT_AUTHORITY: + return formatMboxInsufficientAuthorityMsg(authorityLevel, levFrom, levTo); + default: + const _exhaustiveMboxReason: never = reason; + throw new ImplementationError( + `Unexpected reason for MAILBOX: ${_exhaustiveMboxReason}`, + ); + } } // Non-exported helper for VALUE kind function getValueDowngradeErrorMessageForReason( - reason: DowngradeErrorReason, - operationDescription: string, - levFrom: Level, - levTo: Level, - authorityLevel: Level, - currentBlockingLevelForCheck: Level + reason: DowngradeErrorReason, + operationDescription: string, + levFrom: Level, + levTo: Level, + authorityLevel: Level, + currentBlockingLevelForCheck: Level, ): string { - if (reason === DowngradeErrorReason.BLOCKING_LEVEL_MISMATCH && currentBlockingLevelForCheck === null) { - throw new ImplementationError("Internal inconsistency: currentBlockingLevelForCheck is null for VALUE kind with BLOCKING_LEVEL_MISMATCH reason."); - } - switch (reason) { - case DowngradeErrorReason.INTEGRITY_MISMATCH: return formatIntegrityMismatchMsg(operationDescription, levFrom, levTo); - case DowngradeErrorReason.CONFIDENTIALITY_MISMATCH: return formatConfidentialityMismatchMsg(operationDescription, levFrom, levTo); - case DowngradeErrorReason.BLOCKING_LEVEL_MISMATCH: - return formatPiniBlockingLevelMismatchMsg(operationDescription, currentBlockingLevelForCheck!, levTo); - case DowngradeErrorReason.INSUFFICIENT_AUTHORITY: return formatValueInsufficientAuthorityMsg(operationDescription, levFrom, authorityLevel, levTo); - default: - const _exhaustiveValueReason: never = reason; - throw new ImplementationError(`Unexpected reason for VALUE: ${_exhaustiveValueReason}`); - } + if ( + reason === DowngradeErrorReason.BLOCKING_LEVEL_MISMATCH && + currentBlockingLevelForCheck === null + ) { + throw new ImplementationError( + "Internal inconsistency: currentBlockingLevelForCheck is null for VALUE kind with BLOCKING_LEVEL_MISMATCH reason.", + ); + } + switch (reason) { + case DowngradeErrorReason.INTEGRITY_MISMATCH: + return formatIntegrityMismatchMsg(operationDescription, levFrom, levTo); + case DowngradeErrorReason.CONFIDENTIALITY_MISMATCH: + return formatConfidentialityMismatchMsg( + operationDescription, + levFrom, + levTo, + ); + case DowngradeErrorReason.BLOCKING_LEVEL_MISMATCH: + return formatPiniBlockingLevelMismatchMsg( + operationDescription, + currentBlockingLevelForCheck, + levTo, + ); + case DowngradeErrorReason.INSUFFICIENT_AUTHORITY: + return formatValueInsufficientAuthorityMsg( + operationDescription, + levFrom, + authorityLevel, + levTo, + ); + default: + const _exhaustiveValueReason: never = reason; + throw new ImplementationError( + `Unexpected reason for VALUE: ${_exhaustiveValueReason}`, + ); + } } -export function getDowngradeErrorMessage(params: ValidateDowngradeParams, reason: DowngradeErrorReason): string { - const { levFrom, levTo, authorityLevel, downgradeKind, blockLevel: currentBlockingLevelForCheck } = params; - let opDesc = params.operationDescription; // Allow opDesc to be potentially modified +export function getDowngradeErrorMessage( + params: ValidateDowngradeParams, + reason: DowngradeErrorReason, +): string { + const { + levFrom, + levTo, + authorityLevel, + downgradeKind, + blockLevel: currentBlockingLevelForCheck, + } = params; + let opDesc = params.operationDescription; // Allow opDesc to be potentially modified - switch (downgradeKind) { - case DowngradeKind.BLOCKING: - if (typeof opDesc !== 'string') { - throw new ImplementationError("operationDescription is required for BLOCKING downgradeKind."); - } - return getBlockDowngradeErrorMessageForReason(reason, opDesc, levFrom, levTo, authorityLevel); - case DowngradeKind.MAILBOX: - opDesc = "lowering mailbox clearance"; // Standardize opDesc for mailbox - if (currentBlockingLevelForCheck === null) { - throw new ImplementationError("currentBlockingLevelForCheck is required for MAILBOX downgradeKind."); - } - return getMailboxDowngradeErrorMessageForReason(reason, opDesc, levFrom, levTo, authorityLevel, currentBlockingLevelForCheck); - case DowngradeKind.VALUE: - opDesc = opDesc || "value downgrade"; // Default opDesc for value - return getValueDowngradeErrorMessageForReason(reason, opDesc, levFrom, levTo, authorityLevel, currentBlockingLevelForCheck); - default: - const _exhaustiveKind: never = downgradeKind; - throw new ImplementationError(`Unhandled DowngradeKind: ${_exhaustiveKind}`); - } -} \ No newline at end of file + switch (downgradeKind) { + case DowngradeKind.BLOCKING: + if (typeof opDesc !== "string") { + throw new ImplementationError( + "operationDescription is required for BLOCKING downgradeKind.", + ); + } + return getBlockDowngradeErrorMessageForReason( + reason, + opDesc, + levFrom, + levTo, + authorityLevel, + ); + case DowngradeKind.MAILBOX: + opDesc = "lowering mailbox clearance"; // Standardize opDesc for mailbox + if (currentBlockingLevelForCheck === null) { + throw new ImplementationError( + "currentBlockingLevelForCheck is required for MAILBOX downgradeKind.", + ); + } + return getMailboxDowngradeErrorMessageForReason( + reason, + opDesc, + levFrom, + levTo, + authorityLevel, + currentBlockingLevelForCheck, + ); + case DowngradeKind.VALUE: + opDesc = opDesc || "value downgrade"; // Default opDesc for value + return getValueDowngradeErrorMessageForReason( + reason, + opDesc, + levFrom, + levTo, + authorityLevel, + currentBlockingLevelForCheck, + ); + default: + const _exhaustiveKind: never = downgradeKind; + throw new ImplementationError( + `Unhandled DowngradeKind: ${_exhaustiveKind}`, + ); + } +} diff --git a/rt/src/EqualityChecker.mts b/rt/src/EqualityChecker.mts index 24f9eff3..a44dd08a 100644 --- a/rt/src/EqualityChecker.mts +++ b/rt/src/EqualityChecker.mts @@ -1,9 +1,9 @@ -import {TroupeType} from './TroupeTypes.mjs' -import {LVal} from './Lval.mjs' -import { TroupeRawValue } from './TroupeRawValue.mjs'; -import * as proc from './process.mjs' -import * as levels from './Level.mjs' -import { Level } from './Level.mjs'; +import { TroupeType } from "./TroupeTypes.mjs"; +import { LVal } from "./Lval.mjs"; +import { TroupeRawValue } from "./TroupeRawValue.mjs"; +import * as proc from "./process.mjs"; +import * as levels from "./Level.mjs"; +import { Level } from "./Level.mjs"; /** * Compute deep equality of the given unlabelled raw values. @@ -11,28 +11,26 @@ import { Level } from './Level.mjs'; */ export function runtimeEquals(x: TroupeRawValue, y: TroupeRawValue): LVal { function baseBoolean(b: boolean, l: Level = levels.BOT) { - return new LVal(b, l, levels.BOT) + return new LVal(b, l, levels.BOT); } function levelEquality(o1, o2) { - return baseBoolean(levels.flowsTo(o1, o2) && levels.flowsTo(o2, o1)) + return baseBoolean(levels.flowsTo(o1, o2) && levels.flowsTo(o2, o1)); } function arrayEquality(o1, o2) { - if (o1.length != o2.length) - return baseBoolean(false) + if (o1.length != o2.length) return baseBoolean(false); // Join of the labels of values compared so far - let l = levels.BOT + let l = levels.BOT; for (let j = 0; j < o1.length; j++) { - let z = runtimeEquals(o1[j].val, o2[j].val); - l = levels.lub(l, z.lev, o1[j].lev, o2[j].lev) + const z = runtimeEquals(o1[j].val, o2[j].val); + l = levels.lub(l, z.lev, o1[j].lev, o2[j].lev); if (!z.val) { - return baseBoolean(false, l) + return baseBoolean(false, l); } } - return baseBoolean(true, l) - + return baseBoolean(true, l); } function recordEquality(o1, o2) { @@ -41,29 +39,29 @@ export function runtimeEquals(x: TroupeRawValue, y: TroupeRawValue): LVal { } // Join of the labels of values compared so far - let l = levels.BOT - for (let [k, v] of o1.__obj.entries()) { + let l = levels.BOT; + for (const [k, v] of o1.__obj.entries()) { if (o2.__obj.has(k)) { - let u = o2.__obj.get(k); - let z = runtimeEquals(v.val, u.val); + const u = o2.__obj.get(k); + const z = runtimeEquals(v.val, u.val); l = levels.lub(l, z.lev, v.lev, u.lev); if (!z.val) { - return baseBoolean(false, l) + return baseBoolean(false, l); } } else { - console.log("does not have field") + console.log("does not have field"); return baseBoolean(false, l); } } - return baseBoolean(true, l) + return baseBoolean(true, l); } // If both types are basic types (and not Troupe types), this check will pass // and basic comparison with "==" will be used in the default case below. - if (x._troupeType != y._troupeType) return baseBoolean(false) + if (x._troupeType != y._troupeType) return baseBoolean(false); - let o1: any = x - let o2: any = y + const o1: any = x; + const o2: any = y; switch (x._troupeType) { case TroupeType.ATOM: @@ -77,10 +75,10 @@ export function runtimeEquals(x: TroupeRawValue, y: TroupeRawValue): LVal { case TroupeType.LIST: return arrayEquality(o1.toArray(), o2.toArray()); case TroupeType.TUPLE: - return arrayEquality(o1, o2) + return arrayEquality(o1, o2); case TroupeType.RECORD: - return recordEquality(o1, o2) + return recordEquality(o1, o2); default: - return baseBoolean(o1 == o2) + return baseBoolean(o1 == o2); } } diff --git a/rt/src/Level.mts b/rt/src/Level.mts index 8f1a66e5..84a5b089 100644 --- a/rt/src/Level.mts +++ b/rt/src/Level.mts @@ -1,31 +1,61 @@ -import {levels, Level } from './levels/DCLabels/dclabel.mjs' -import { DowngradeResult, DowngradeKind, DowngradeDimension } from './DowngradeEnums.mjs' -export { mkLevel, Level } from './levels/DCLabels/dclabel.mjs' - +import { levels, Level } from "./levels/DCLabels/dclabel.mjs"; +import { + DowngradeResult, + DowngradeKind, + DowngradeDimension, +} from "./DowngradeEnums.mjs"; +export { mkLevel, Level } from "./levels/DCLabels/dclabel.mjs"; // import {levels } from './levels/tagsets.mjs' // export { mkLevel, Level } from './levels/tagsets.mjs' -export function lub(...x) { return levels.lub (...x) } -export function lubs(x) { return levels.lubs (x ) } -export function glb(a,b) { return levels.glb (a,b) } -export function flowsTo (a:Level,b:Level) { return levels.flowsTo (a,b) } -export function actsFor (a:Level,b:Level) { return levels.actsFor (a,b) } -export function okToDowngrade (kind: DowngradeKind, dimension: DowngradeDimension) { - return levels.okToDowngrade(kind, dimension); +export function lub(...x) { + return levels.lub(...x); +} +export function lubs(x) { + return levels.lubs(x); +} +export function glb(a, b) { + return levels.glb(a, b); +} +export function flowsTo(a: Level, b: Level) { + return levels.flowsTo(a, b); +} +export function actsFor(a: Level, b: Level) { + return levels.actsFor(a, b); +} +export function okToDowngrade( + kind: DowngradeKind, + dimension: DowngradeDimension, +) { + return levels.okToDowngrade(kind, dimension); +} +export function okToDeclassify( + from: Level, + to: Level, + auth: Level, + bl: Level, + isNMIFC: boolean, +): DowngradeResult { + return levels.okToDeclassify(from, to, auth, bl, isNMIFC); } -export function okToDeclassify (from: Level, to:Level, auth: Level, bl: Level, isNMIFC: boolean): DowngradeResult { - return levels.okToDeclassify (from,to,auth, bl, isNMIFC); +export function okToEndorse( + from: Level, + to: Level, + auth: Level, + bl: Level, + isNMIFC: boolean, +): DowngradeResult { + return levels.okToEndorse(from, to, auth, bl, isNMIFC); } -export function okToEndorse (from: Level, to:Level, auth: Level, bl: Level, isNMIFC: boolean): DowngradeResult { - return levels.okToEndorse (from,to,auth, bl, isNMIFC); +export function fromSingleTag(x: string) { + return levels.fromV1String(x); } -export function fromSingleTag(x:string) { return levels.fromV1String(x)} -export function mkV1Level (x:string ) { - return levels.fromV1String (x); +export function mkV1Level(x: string) { + return levels.fromV1String(x); } -export const BOT = levels.BOT -export const TOP = levels.TOP -export const ROOT = levels.ROOT -export const NULL = levels.NULL +export const BOT = levels.BOT; +export const TOP = levels.TOP; +export const ROOT = levels.ROOT; +export const NULL = levels.NULL; diff --git a/rt/src/LocalObject.mts b/rt/src/LocalObject.mts index af5e1c00..0a1554d1 100644 --- a/rt/src/LocalObject.mts +++ b/rt/src/LocalObject.mts @@ -1,18 +1,18 @@ -import {TroupeType} from './TroupeTypes.mjs' -import {TroupeRawValue} from './TroupeRawValue.mjs' -import * as levels from './Level.mjs' +import { TroupeType } from "./TroupeTypes.mjs"; +import { TroupeRawValue } from "./TroupeRawValue.mjs"; +import * as levels from "./Level.mjs"; export class LocalObject implements TroupeRawValue { - _troupeType : TroupeType - _value : Object - dataLevel = levels.ROOT// 2025-05-25; AA; consider rethinking what this should be... + _troupeType: TroupeType; + _value: object; + dataLevel = levels.ROOT; // 2025-05-25; AA; consider rethinking what this should be... - constructor (v:Object) { - this._troupeType = TroupeType.LOCALOBJECT - this._value = v - } + constructor(v: object) { + this._troupeType = TroupeType.LOCALOBJECT; + this._value = v; + } - stringRep (omitLevels?: boolean, taintRef?: any):string { - return "LocalObject" - } -} \ No newline at end of file + stringRep(omitLevels?: boolean, taintRef?: any): string { + return "LocalObject"; + } +} diff --git a/rt/src/Lval.mts b/rt/src/Lval.mts index 4bf25313..8fb2a41b 100644 --- a/rt/src/Lval.mts +++ b/rt/src/Lval.mts @@ -1,112 +1,105 @@ -import * as levels from './Level.mjs' +import * as levels from "./Level.mjs"; import { Level } from "./Level.mjs"; -import * as Ty from './TroupeTypes.mjs'; -import { TroupeRawValue } from './TroupeRawValue.mjs'; +import * as Ty from "./TroupeTypes.mjs"; +import { TroupeRawValue } from "./TroupeRawValue.mjs"; -export class LVal implements TroupeRawValue{ - val: any; - lev: Level; - tlev: Level; - dlev: Level; - posInfo: string; +export class LVal implements TroupeRawValue { + val: any; + lev: Level; + tlev: Level; + dlev: Level; + posInfo: string; - /* 2020-06-06: AA + /* 2020-06-06: AA - Observe that we only need the type information here only because of the + Observe that we only need the type information here only because of the base type such as booleans, strings, and numbers; becauase we cannot attach - properties to them in JS. + properties to them in JS. - The main downside of duplicating the type information is the duplication of + The main downside of duplicating the type information is the duplication of this information during serialization */ - __troupeType : Ty.TroupeType - - constructor(v:any, l:Level, tlev:Level = null, posInfo:string = null) { - this.val = v; - this.lev = l; - this.tlev = tlev == null?l:tlev; - this.posInfo = posInfo; - if (v._troupeType == undefined) { - this.__troupeType = Ty.getTypeForBasicValue(v) - this.dlev = this.lev - } else { - this.__troupeType = v._troupeType - this.dlev = levels.lub (this.lev, v.dataLevel) - } + __troupeType: Ty.TroupeType; + + constructor(v: any, l: Level, tlev: Level = null, posInfo: string = null) { + this.val = v; + this.lev = l; + this.tlev = tlev == null ? l : tlev; + this.posInfo = posInfo; + if (v._troupeType == undefined) { + this.__troupeType = Ty.getTypeForBasicValue(v); + this.dlev = this.lev; + } else { + this.__troupeType = v._troupeType; + this.dlev = levels.lub(this.lev, v.dataLevel); } + } - get _troupeType() { - return Ty.TroupeType.LVAL - } - get troupeType () { - return this.__troupeType - } + get _troupeType() { + return Ty.TroupeType.LVAL; + } + get troupeType() { + return this.__troupeType; + } - get dataLevel () { - return this.dlev; - } + get dataLevel() { + return this.dlev; + } - get closureType () { - return (this.troupeType == Ty.TroupeType.CLOSURE - ? this.val._closureType - : null - ) - } - stringRep(omitLevels?: boolean, taintRef?: any) { - let v = this.val; - let l = this.lev; - let t = ""; - if (v.stringRep != undefined) { // 2018-05-17; AA; ugly hack! - t = v.stringRep(omitLevels, taintRef) + get closureType() { + return this.troupeType == Ty.TroupeType.CLOSURE + ? this.val._closureType + : null; + } + stringRep(omitLevels?: boolean, taintRef?: any) { + const v = this.val; + const l = this.lev; + let t = ""; + if (v.stringRep != undefined) { + // 2018-05-17; AA; ugly hack! + t = v.stringRep(omitLevels, taintRef); + } else { + if (typeof v === "string") { + t = '"' + v.toString() + '"'; } else { - if (typeof v === 'string') { - t = "\"" + v.toString() + "\"" - } else { - t = v.toString(); - } + t = v.toString(); } + } - if (l.stringRep == undefined) { - console.log("undefined strringrep", l); - } + if (l.stringRep == undefined) { + console.log("undefined strringrep", l); + } - let s = t; + let s = t; - if (!omitLevels) { - s = s + "@" + l.stringRep() + "%" + this.tlev.stringRep(); - } + if (!omitLevels) { + s = s + "@" + l.stringRep() + "%" + this.tlev.stringRep(); + } - if (taintRef) { - taintRef.lev = levels.lub (taintRef.lev, l); - } + if (taintRef) { + taintRef.lev = levels.lub(taintRef.lev, l); + } - return s; + return s; } } - export class LValCopyAt extends LVal { - constructor (x:LVal, l:Level, l2 = null) { - if (l2 == null) { - l2 = levels.lub (x.tlev,l) - } - super (x.val, levels.lub (x.lev, l), l2); + constructor(x: LVal, l: Level, l2 = null) { + if (l2 == null) { + l2 = levels.lub(x.tlev, l); } + super(x.val, levels.lub(x.lev, l), l2); + } } export class LCopyVal extends LVal { - constructor (x:LVal, l1:Level, l2:Level = null) { - super (x.val, l1, l2); - } -} - - - - -export class MbVal extends LVal { - + constructor(x: LVal, l1: Level, l2: Level = null) { + super(x.val, l1, l2); + } } +export class MbVal extends LVal {} export function listStringRep(x, omitLevels = false, taintRef = null) { if (x.length == 0) { @@ -115,7 +108,7 @@ export function listStringRep(x, omitLevels = false, taintRef = null) { let s = x[0].stringRep(omitLevels, taintRef); for (let i = 1; i < x.length; i++) { - s += ", " + x[i].stringRep(omitLevels, taintRef ); + s += ", " + x[i].stringRep(omitLevels, taintRef); } return s; -} \ No newline at end of file +} diff --git a/rt/src/MailboxInterface.mts b/rt/src/MailboxInterface.mts index e737dc9b..49d9b663 100644 --- a/rt/src/MailboxInterface.mts +++ b/rt/src/MailboxInterface.mts @@ -2,7 +2,7 @@ import { Level } from "./Level.mjs"; import { ReceiveTaintAction } from "./ReceiveTaintAction.mjs"; export interface MailboxInterface { - // rcv(pc: any, pc2: any, handlers: any, boost_level: any, taintLimit?: Level, taintAction?: ReceiveTaintAction ); - peek(lev: Level, i: number, lowb: Level, highb: Level) - consume (lev: Level, i: number, lowb: Level, highb: Level) -} \ No newline at end of file + // rcv(pc: any, pc2: any, handlers: any, boost_level: any, taintLimit?: Level, taintAction?: ReceiveTaintAction ); + peek(lev: Level, i: number, lowb: Level, highb: Level); + consume(lev: Level, i: number, lowb: Level, highb: Level); +} diff --git a/rt/src/MailboxProcessor.mts b/rt/src/MailboxProcessor.mts index 8c7bd239..472a022c 100644 --- a/rt/src/MailboxProcessor.mts +++ b/rt/src/MailboxProcessor.mts @@ -1,176 +1,188 @@ -import { assertIsHandler, assertIsNTuple, assertIsFunction } from "./Asserts.mjs"; +import { + assertIsHandler, + assertIsNTuple, + assertIsFunction, +} from "./Asserts.mjs"; import { mkTuple } from "./ValuesUtil.mjs"; import { SchedulerInterface } from "./SchedulerInterface.mjs"; import { __unit } from "./UnitVal.mjs"; import { RuntimeInterface } from "./RuntimeInterface.mjs"; -import { getCliArgs, TroupeCliArg } from './TroupeCliArgs.mjs'; +import { getCliArgs, TroupeCliArg } from "./TroupeCliArgs.mjs"; const argv = getCliArgs(); -let logLevel = argv[TroupeCliArg.DebugMailbox] ? 'debug': 'info' - -import { mkLogger } from './logger.mjs' -const logger = mkLogger('MBX', logLevel); -const debug = x => logger.debug(x); -import { HandlerState as SandboxStatus } from './SandboxStatus.mjs' ; -import {lub,flowsTo} from './Level.mjs' -import * as levels from './Level.mjs' +const logLevel = argv[TroupeCliArg.DebugMailbox] ? "debug" : "info"; + +import { mkLogger } from "./logger.mjs"; +const logger = mkLogger("MBX", logLevel); +const debug = (x) => logger.debug(x); +import { HandlerState as SandboxStatus } from "./SandboxStatus.mjs"; +import { lub, flowsTo } from "./Level.mjs"; +import * as levels from "./Level.mjs"; import { ReceiveTaintAction } from "./ReceiveTaintAction.mjs"; import { LVal, MbVal } from "./Lval.mjs"; import { MailboxInterface } from "./MailboxInterface.mjs"; import { Level } from "./Level.mjs"; import { Thread } from "./Thread.mjs"; - function createMessage(msg, fromNodeId, pc) { - let tuple:any = mkTuple ([msg, fromNodeId]); - // tuple.isTuple = true; // hack! 2018-10-19: AA - // tuple._troupeType = TroupeType.TUPLE - // tuple.dataLevel = lub (msg.dataLevel, pc) - return new MbVal(tuple, pc); + const tuple: any = mkTuple([msg, fromNodeId]); + // tuple.isTuple = true; // hack! 2018-10-19: AA + // tuple._troupeType = TroupeType.TUPLE + // tuple.dataLevel = lub (msg.dataLevel, pc) + return new MbVal(tuple, pc); +} + +export class MailboxProcessor implements MailboxInterface { + sched: SchedulerInterface; + levels: any; + mailboxes: any[]; + rtObj: RuntimeInterface; + + constructor(rtObj: RuntimeInterface) { + this.levels = levels; + this.mailboxes = []; + this.rtObj = rtObj; + this.sched = rtObj.__sched; } + addMessage(fromNodeId, toPid, message, pc) { + debug(`addMessage ${message.stringRep()} ${pc.stringRep()}`); + const __sched = this.sched; -export class MailboxProcessor implements MailboxInterface { - sched: SchedulerInterface; - levels: any; - mailboxes : any []; - rtObj: RuntimeInterface - - - - constructor(rtObj:RuntimeInterface) { - this.levels = levels; - this.mailboxes = new Array(); - this.rtObj = rtObj - this.sched = rtObj.__sched + // check whether the recipient is alive + if (!__sched.isAlive(toPid)) { + return; } + // get the recipient thread + const t = __sched.getThread(toPid); + // create the message + const messageWithSenderId = createMessage(message, fromNodeId, pc); - addMessage(fromNodeId, toPid, message, pc) { - - debug (`addMessage ${message.stringRep()} ${pc.stringRep()}`) - let __sched = this.sched; - - // check whether the recipient is alive - if (!__sched.isAlive(toPid)) { - return; - } + // add the message to the thread's mailbox + t.addMessage(messageWithSenderId); - // get the recipient thread - let t = __sched.getThread (toPid); + // unblock the thread if necessary + __sched.unblockThread(toPid); + } - // create the message - let messageWithSenderId = createMessage(message, fromNodeId, pc); + findFrom( + theThread: Thread, + i: number, + j: number, + index: number, + lowb: Level, + highb: Level, + kont, + ) { + const mb = theThread.mailbox; + const _peekF = (i: number, j: number) => { + for (; i < mb.length; i++) { + const msg_i = mb[i]; + debug(`mailbox iteration ${i} ${j} ${msg_i.stringRep()}`); + const presenceLev = msg_i.lev; + debug(`presence level is ${presenceLev.stringRep()}`); + if (!flowsTo(lowb, presenceLev) || !flowsTo(presenceLev, highb)) { + debug( + "* skipping message because it is outside of the interval bounds", + ); + continue; + } else { + debug(`* message is within the interval ${j} ${index}`); + if (j == index) { + debug(`* find match; returning`); + return kont(i); + } else { + j++; + } + } + } + debug(`* blocking `); + theThread.block(() => { + debug(` * unblocking *`); + return _peekF(i, j); + }); - // add the message to the thread's mailbox - t.addMessage (messageWithSenderId); + this.sched.blockThread(theThread); + }; - // unblock the thread if necessary - __sched.unblockThread(toPid); - } + return _peekF(i, j); + } - findFrom (theThread: Thread, i : number, j:number, index:number, lowb: Level, highb: Level, kont ) { - let mb = theThread.mailbox; - let _peekF = (i : number, j: number) => { - for (; i < mb.length; i ++ ) { - let msg_i = mb[i] - debug (`mailbox iteration ${i} ${j} ${msg_i.stringRep()}`) - let presenceLev = msg_i.lev - debug (`presence level is ${presenceLev.stringRep()}`) - if (!(flowsTo(lowb, presenceLev)) || !(flowsTo(presenceLev, highb))) { - debug("* skipping message because it is outside of the interval bounds"); - continue; - } else { - debug (`* message is within the interval ${j} ${index}`) - if ( j == index ) { - debug (`* find match; returning`) - return kont (i) - } else { - j++ - } - } - } - debug (`* blocking `) - theThread.block (() => { - debug (` * unblocking *`) - return _peekF (i,j) - }) - - this.sched.blockThread(theThread) - } - - return _peekF (i,j) + peek(lev: Level, index: number, lowb: Level, highb: Level) { + const theThread = this.sched.__currentThread; + const mb = theThread.mailbox; + debug(`peek index: ${index}`); + debug(`peek interval: [${lowb.stringRep()}, ${highb.stringRep()}]`); + const lclear = mb.mclear; + theThread.raiseBlockingThreadLev(lub(highb, lclear.boost_level)); + theThread.invalidateSparseBit(); + let _i = 0, + _j = 0; + + if ( + mb.peek_cache_index < index && + mb.peek_cache_lowb == lowb && + mb.peek_cache_highb == highb + ) { + debug(`* peek cache hit`); + _i = mb.peek_cache_position + 1; + _j = mb.peek_cache_index + 1; } + return this.findFrom(theThread, _i, _j, index, lowb, highb, (i: number) => { + mb.peek_cache_index = index; + mb.peek_cache_position = i; + mb.peek_cache_lowb = lowb; + mb.peek_cache_highb = highb; + const newLev = lub(mb[i].lev, lev); + debug(`* peek returns value at level ${newLev.stringRep()}`); + return theThread.returnImmediateLValue( + new LVal(mb[i].val, newLev, newLev), + ); + }); + } - peek(lev: Level, index: number, lowb: Level, highb: Level) { - let theThread = this.sched.__currentThread - let mb = theThread.mailbox; - debug (`peek index: ${index}`) - debug (`peek interval: [${lowb.stringRep()}, ${highb.stringRep()}]`) - let lclear = mb.mclear - theThread.raiseBlockingThreadLev (lub (highb, lclear.boost_level)) - theThread.invalidateSparseBit() - let _i = 0, _j = 0 - - if (mb.peek_cache_index < index && mb.peek_cache_lowb == lowb - && mb.peek_cache_highb == highb) { - debug (`* peek cache hit`) - _i = mb.peek_cache_position + 1 - _j = mb.peek_cache_index + 1 - } - - return this.findFrom ( theThread , _i , _j , index , lowb , highb - , (i:number) => { - mb.peek_cache_index = index - mb.peek_cache_position = i - mb.peek_cache_lowb = lowb - mb.peek_cache_highb = highb - let newLev = lub (mb[i].lev, lev) - debug (`* peek returns value at level ${newLev.stringRep()}`) - return theThread.returnImmediateLValue ( - new LVal (mb[i].val, - newLev, - newLev - )) - }) + consume(lev: Level, index: number, lowb: Level, highb: Level) { + const theThread = this.sched.__currentThread; + const mb = theThread.mailbox; + debug(`consume index: ${index}`); + debug(`consume interval: [${lowb.stringRep()} to ${highb.stringRep()}]`); + const lclear = mb.mclear; + theThread.raiseBlockingThreadLev(lub(highb, lclear.boost_level)); + theThread.invalidateSparseBit(); + const kontFound = (i: number) => { + mb.resetPeekCache(); + const foundValue = mb[i]; + mb.splice(i, 1); + return theThread.returnImmediateLValue( + new LVal(foundValue.val, lub(foundValue.lev, lev)), + ); + }; + + if ( + mb.peek_cache_index == index && + mb.peek_cache_lowb == lowb && + mb.peek_cache_highb == highb + ) { + debug(`* consume exact cache hit`); + return kontFound(mb.peek_cache_position); } - consume(lev: Level, index: number, lowb: Level, highb: Level) { - let theThread = this.sched.__currentThread - let mb = theThread.mailbox; - debug (`consume index: ${index}`) - debug (`consume interval: [${lowb.stringRep()} to ${highb.stringRep()}]`) - let lclear = mb.mclear - theThread.raiseBlockingThreadLev (lub (highb, lclear.boost_level)) - theThread.invalidateSparseBit() - let kontFound = (i:number) => { - mb.resetPeekCache (); - let foundValue = mb[i] - mb.splice (i, 1) - return theThread.returnImmediateLValue ( - new LVal (foundValue.val, lub (foundValue.lev, lev))) - } - - if (mb.peek_cache_index == index && mb.peek_cache_lowb == lowb - && mb.peek_cache_highb == highb) { - debug (`* consume exact cache hit`) - return kontFound (mb.peek_cache_position) - } - - let _i = 0, _j = 0 - - if (mb.peek_cache_index < index && mb.peek_cache_lowb == lowb - && mb.peek_cache_highb == highb) { - debug (`* consume next cache hit`) - _i = mb.peek_cache_position + 1 - _j = mb.peek_cache_index + 1 - } - - return this.findFrom ( theThread , _i , _j , index , lowb , highb, kontFound) - + let _i = 0, + _j = 0; + + if ( + mb.peek_cache_index < index && + mb.peek_cache_lowb == lowb && + mb.peek_cache_highb == highb + ) { + debug(`* consume next cache hit`); + _i = mb.peek_cache_position + 1; + _j = mb.peek_cache_index + 1; } - -} + return this.findFrom(theThread, _i, _j, index, lowb, highb, kontFound); + } +} diff --git a/rt/src/NodeManager.mts b/rt/src/NodeManager.mts index 7e5ba40d..9c4f55d9 100644 --- a/rt/src/NodeManager.mts +++ b/rt/src/NodeManager.mts @@ -1,79 +1,76 @@ -'use strict' +"use strict"; -import * as fs from 'node:fs' +import * as fs from "node:fs"; import * as levels from "./Level.mjs"; -import { getCliArgs, TroupeCliArg } from './TroupeCliArgs.mjs'; +import { getCliArgs, TroupeCliArg } from "./TroupeCliArgs.mjs"; const argv = getCliArgs(); - class Node { - nodeId: any; - constructor(nodeId) { - this.nodeId = nodeId; - } + nodeId: any; + constructor(nodeId) { + this.nodeId = nodeId; + } } class NodeManager { - localNode: any; - levels: any - aliases: any; - - constructor () { + localNode: any; + levels: any; + aliases: any; - let aliases = argv[TroupeCliArg.Aliases] - ? JSON.parse ( fs.readFileSync(argv[TroupeCliArg.Aliases] as string, 'utf8')) - : {} + constructor() { + const aliases = argv[TroupeCliArg.Aliases] + ? JSON.parse(fs.readFileSync(argv[TroupeCliArg.Aliases], "utf8")) + : {}; - - this.localNode = null; - this.levels = levels; - this.aliases = aliases - } + this.localNode = null; + this.levels = levels; + this.aliases = aliases; + } - setLocalPeerId (peerid) { - if (this.localNode != null) { - console.log ("error: local port already set. quitting..."); - process.exit(1); - } - this.localNode = new Node (peerid); + setLocalPeerId(peerid) { + if (this.localNode != null) { + console.log("error: local port already set. quitting..."); + process.exit(1); } + this.localNode = new Node(peerid); + } - getNodeId () { - if (this.localNode.nodeId == null) { - return "" - } - return this.localNode.nodeId + getNodeId() { + if (this.localNode.nodeId == null) { + return ""; } + return this.localNode.nodeId; + } - getNode(nodeName) { - if (nodeName.startsWith ("@")) { - nodeName = this.aliases[nodeName.substring(1)]; - } - // TODO: error handling in case aliases are not available; 2020-01-31 - - return new Node (nodeName); + getNode(nodeName) { + if (nodeName.startsWith("@")) { + nodeName = this.aliases[nodeName.substring(1)]; } + // TODO: error handling in case aliases are not available; 2020-01-31 - isLocalNode (id) { - if (id == "") { - return true; - } - // console.log ("local node id is ", this.localNode) - if (this.localNode == undefined) { - console.log("ERROR: local node undefined; should not happen") - process.exit(1); - } - return this.localNode.nodeId == this.getNode(id).nodeId + return new Node(nodeName); + } + + isLocalNode(id) { + if (id == "") { + return true; + } + // console.log ("local node id is ", this.localNode) + if (this.localNode == undefined) { + console.log("ERROR: local node undefined; should not happen"); + process.exit(1); } + return this.localNode.nodeId == this.getNode(id).nodeId; + } - // Another hack; 2018-03-10; aa - getLocalNode() { - if (this.localNode == undefined) { - console.log("ERROR: local node undefined; should not happen") - process.exit(1); - } - return this.localNode; + // Another hack; 2018-03-10; aa + getLocalNode() { + if (this.localNode == undefined) { + console.log("ERROR: local node undefined; should not happen"); + process.exit(1); } + return this.localNode; + } } -export let __nodeManager = new NodeManager() \ No newline at end of file +export const __nodeManager = new NodeManager(); diff --git a/rt/src/RawClosure.mts b/rt/src/RawClosure.mts index f2248529..ada7542b 100644 --- a/rt/src/RawClosure.mts +++ b/rt/src/RawClosure.mts @@ -1,43 +1,41 @@ -import {TroupeAggregateRawValue} from './TroupeRawValue.mjs' -import {ClosureType, TroupeType} from './TroupeTypes.mjs' -import * as levels from './Level.mjs' -export function RawClosure (e, _t, f) : TroupeAggregateRawValue { - let closure:any = () => { - return f (e) - } - closure.env=e - closure.namespace = _t - closure.fun = f - closure._troupeType = TroupeType.CLOSURE - closure._closureType = ClosureType.REGULARFN - closure.stringRep = (omitLevels = false ) => { - return "fn => .." - } - - closure.dataLevel = e.__dataLevel +import { TroupeAggregateRawValue } from "./TroupeRawValue.mjs"; +import { ClosureType, TroupeType } from "./TroupeTypes.mjs"; +import * as levels from "./Level.mjs"; +export function RawClosure(e, _t, f): TroupeAggregateRawValue { + const closure: any = () => { + return f(e); + }; + closure.env = e; + closure.namespace = _t; + closure.fun = f; + closure._troupeType = TroupeType.CLOSURE; + closure._closureType = ClosureType.REGULARFN; + closure.stringRep = (omitLevels = false) => { + return "fn => .."; + }; + + closure.dataLevel = e.__dataLevel; closure.toString = () => { - return ("[RawClosure]" + f.toString ()) - } - return closure; + return "[RawClosure]" + f.toString(); + }; + return closure; } +export function SandboxResumption(f): TroupeAggregateRawValue { + const closure: any = () => { + return f(); + }; + + closure.fun = f; + closure._troupeType = TroupeType.CLOSURE; + closure._closureType = ClosureType.SANDBOXKONT; + closure.stringRep = (omitLevels = false) => { + return ""; + }; -export function SandboxResumption(f) : TroupeAggregateRawValue { - let closure:any = () => { - return f () - } - - - closure.fun = f - closure._troupeType = TroupeType.CLOSURE - closure._closureType = ClosureType.SANDBOXKONT - closure.stringRep = (omitLevels = false ) => { - return "" - } - - closure.dataLevel = levels.BOT + closure.dataLevel = levels.BOT; closure.toString = () => { - return ("") - } - return closure; -} \ No newline at end of file + return ""; + }; + return closure; +} diff --git a/rt/src/RawList.mts b/rt/src/RawList.mts index 4c21e1df..1d9f9725 100644 --- a/rt/src/RawList.mts +++ b/rt/src/RawList.mts @@ -1,116 +1,112 @@ -import {TroupeType} from './TroupeTypes.mjs' -import {TroupeAggregateRawValue} from './TroupeRawValue.mjs' -import {LVal, listStringRep} from './Lval.mjs' -import { Level } from './Level.mjs' -import * as levels from './Level.mjs' - - -export abstract class RawList implements TroupeAggregateRawValue { - _troupeType = TroupeType.LIST; - isList = true ; - isNil : boolean - - constructor() { - - } - - abstract toArray (): LVal []; - abstract get length() : number; - abstract get head () : LVal - abstract get tail () : RawList - abstract index (j:number) : LVal - - stringRep (omitLevels?: boolean, taintRef?: any) { - return ("[" + listStringRep(this.toArray(), omitLevels, taintRef) + "]") - } - - static fromArray (a : LVal []) { - let x = new Nil(); - for (let j = a.length - 1 ; j >= 0; j -- ) { - x = new Cons(a[j], x); - } - return x; - } - - abstract get dataLevel (): Level +import { TroupeType } from "./TroupeTypes.mjs"; +import { TroupeAggregateRawValue } from "./TroupeRawValue.mjs"; +import { LVal, listStringRep } from "./Lval.mjs"; +import { Level } from "./Level.mjs"; +import * as levels from "./Level.mjs"; + +export abstract class RawList implements TroupeAggregateRawValue { + _troupeType = TroupeType.LIST; + isList = true; + isNil: boolean; + + constructor() {} + + abstract toArray(): LVal[]; + abstract get length(): number; + abstract get head(): LVal; + abstract get tail(): RawList; + abstract index(j: number): LVal; + + stringRep(omitLevels?: boolean, taintRef?: any) { + return "[" + listStringRep(this.toArray(), omitLevels, taintRef) + "]"; + } + + static fromArray(a: LVal[]) { + let x = new Nil(); + for (let j = a.length - 1; j >= 0; j--) { + x = new Cons(a[j], x); + } + return x; + } + + abstract get dataLevel(): Level; } export class Nil extends RawList { - constructor() { - super () - this.isNil = true; - } - - get length () { - return 0; - } - - get head () { - throw new Error ("head: empty list") - return null; - } - - get tail () { - throw new Error ("tail: empty list"); - return null; - } - - toArray () { - return []; - } - - get dataLevel (): Level { - return levels.BOT - } - - index (j:number) { - throw new Error ("index: empty list") - return null - } - + constructor() { + super(); + this.isNil = true; + } + + get length() { + return 0; + } + + get head() { + throw new Error("head: empty list"); + return null; + } + + get tail() { + throw new Error("tail: empty list"); + return null; + } + + toArray() { + return []; + } + + get dataLevel(): Level { + return levels.BOT; + } + + index(j: number) { + throw new Error("index: empty list"); + return null; + } } export class Cons extends RawList { - _head: LVal - _tail: RawList - _length : number; - _dataLevel: Level; - constructor (head: LVal, tail: RawList ) { - super (); - this._head = head; - this._tail = tail; - this.isNil = false; - this._length = tail.length + 1 - this._dataLevel = levels.lub (head.dataLevel, tail.dataLevel) - } - - index (j:number) { - if (j == 0) { - return this._head - } else { - return this._tail.index(j - 1) - } - } - - get dataLevel (): Level { - return this._dataLevel - } - - get head () { - return this._head - } - - get tail () { - return this._tail; - } - - get length () { - return this._length; - } - - toArray () { - let x = this._tail.toArray(); - x.unshift ( this._head ); - return x; - } + _head: LVal; + _tail: RawList; + _length: number; + _dataLevel: Level; + constructor(head: LVal, tail: RawList) { + super(); + this._head = head; + this._tail = tail; + this.isNil = false; + this._length = tail.length + 1; + this._dataLevel = levels.lub(head.dataLevel, tail.dataLevel); + } + + index(j: number) { + if (j == 0) { + return this._head; + } else { + return this._tail.index(j - 1); + } + } + + get dataLevel(): Level { + return this._dataLevel; + } + + get head() { + return this._head; + } + + get tail() { + return this._tail; + } + + get length() { + return this._length; + } + + toArray() { + const x = this._tail.toArray(); + x.unshift(this._head); + return x; + } } diff --git a/rt/src/RawTuple.mts b/rt/src/RawTuple.mts index 1469b6a7..26278af1 100644 --- a/rt/src/RawTuple.mts +++ b/rt/src/RawTuple.mts @@ -1,8 +1,8 @@ -import { Level } from './Level.mjs'; -import { LVal, listStringRep } from './Lval.mjs'; -import { TroupeAggregateRawValue } from './TroupeRawValue.mjs'; -import { TroupeType } from './TroupeTypes.mjs'; -import * as levels from './Level.mjs' +import { Level } from "./Level.mjs"; +import { LVal, listStringRep } from "./Lval.mjs"; +import { TroupeAggregateRawValue } from "./TroupeRawValue.mjs"; +import { TroupeType } from "./TroupeTypes.mjs"; +import * as levels from "./Level.mjs"; export class RawTuple extends Array implements TroupeAggregateRawValue { dataLevel: Level; @@ -11,12 +11,12 @@ export class RawTuple extends Array implements TroupeAggregateRawValue { stringRep = null; constructor(x: LVal[]) { - super(...x) + super(...x); this.stringRep = function (omitLevels = false, taintRef = null) { - return ("(" + listStringRep(x, omitLevels, taintRef) + ")"); + return "(" + listStringRep(x, omitLevels, taintRef) + ")"; }; - let dataLevels = x.map(lv => lv.dataLevel); + const dataLevels = x.map((lv) => lv.dataLevel); this.dataLevel = levels.lubs.call(null, dataLevels); } } diff --git a/rt/src/ReceiveTaintAction.mts b/rt/src/ReceiveTaintAction.mts index 43efbb4e..d6b6f68d 100644 --- a/rt/src/ReceiveTaintAction.mts +++ b/rt/src/ReceiveTaintAction.mts @@ -1,4 +1,4 @@ export enum ReceiveTaintAction { - KEEP = 0, - DROP -} \ No newline at end of file + KEEP = 0, + DROP, +} diff --git a/rt/src/Record.mts b/rt/src/Record.mts index 5d688e1a..c649da8f 100644 --- a/rt/src/Record.mts +++ b/rt/src/Record.mts @@ -1,51 +1,50 @@ -import {TroupeType} from './TroupeTypes.mjs' -import {TroupeAggregateRawValue} from './TroupeRawValue.mjs' -import {LVal, listStringRep} from './Lval.mjs' -import { Level } from './Level.mjs' -import * as levels from './Level.mjs' -import { assertIsRecord } from './Asserts.mjs' - - -export class Record implements TroupeAggregateRawValue { - _troupeType = TroupeType.RECORD - _dataLevel: Level = levels.TOP // TODO compute data level? - __obj : Map - - stringRep (omitLevels?: boolean, taintRef?: any) { - // return ("{" + listStringRep(this.toArray(), omitLevels, taintRef) + "}") - let s = "{" - let spaceOrComma = "" - for (let [k,v] of this.__obj.entries()) { - s += spaceOrComma + k + "=" + v.stringRep(omitLevels, taintRef) - spaceOrComma = ", " - } - s += "}" - return s - } - - constructor(fields: Iterable) { - this.__obj = new Map (fields) - } - - hasField (fieldName:string):boolean { - return this.__obj.has(fieldName) - } - - getField (fieldName:string):LVal { - return this.__obj.get (fieldName) - } - - get dataLevel () { - return this._dataLevel - } - - static mkRecord(fields: Iterable): Record { - return new Record(fields) - } - - static mkWithRecord(r: Record, fields: ConcatArray<[string, LVal]>): Record { - let a = Array.from(r.__obj) - let b = a.concat(fields) - return new Record(b) +import { TroupeType } from "./TroupeTypes.mjs"; +import { TroupeAggregateRawValue } from "./TroupeRawValue.mjs"; +import { LVal, listStringRep } from "./Lval.mjs"; +import { Level } from "./Level.mjs"; +import * as levels from "./Level.mjs"; +import { assertIsRecord } from "./Asserts.mjs"; + +export class Record implements TroupeAggregateRawValue { + _troupeType = TroupeType.RECORD; + _dataLevel: Level = levels.TOP; // TODO compute data level? + __obj: Map; + + stringRep(omitLevels?: boolean, taintRef?: any) { + // return ("{" + listStringRep(this.toArray(), omitLevels, taintRef) + "}") + let s = "{"; + let spaceOrComma = ""; + for (const [k, v] of this.__obj.entries()) { + s += spaceOrComma + k + "=" + v.stringRep(omitLevels, taintRef); + spaceOrComma = ", "; } + s += "}"; + return s; + } + + constructor(fields: Iterable) { + this.__obj = new Map(fields); + } + + hasField(fieldName: string): boolean { + return this.__obj.has(fieldName); + } + + getField(fieldName: string): LVal { + return this.__obj.get(fieldName); + } + + get dataLevel() { + return this._dataLevel; + } + + static mkRecord(fields: Iterable): Record { + return new Record(fields); + } + + static mkWithRecord(r: Record, fields: ConcatArray<[string, LVal]>): Record { + const a = Array.from(r.__obj); + const b = a.concat(fields); + return new Record(b); + } } diff --git a/rt/src/RuntimeInterface.mts b/rt/src/RuntimeInterface.mts index f212b8a2..756f6143 100644 --- a/rt/src/RuntimeInterface.mts +++ b/rt/src/RuntimeInterface.mts @@ -1,22 +1,26 @@ import { SchedulerInterface } from "./SchedulerInterface.mjs"; import { Thread } from "./Thread.mjs"; -import { LVal } from './Lval.mjs' +import { LVal } from "./Lval.mjs"; import { MailboxInterface } from "./MailboxInterface.mjs"; export interface RuntimeInterface { - cleanup(): Promise - mkLabel(levid: any): any; - rt_mkuuid(); - spawnAtNode(arg0: any, arg1: any); - $t: Thread; - $service: any; // todo 2021-06-13; identify what the right interface here should be - debug(arg0: string); - __sched: SchedulerInterface - __mbox : MailboxInterface - sendMessageNoChecks(toPid: any, message: import("./Lval.mjs").LVal, arg2?: boolean): any; - ret(arg0: any); - // ret_raw () - // tailcall(funclos: any, __unit: any); - persist (obj, path) - xconsole: Console -} \ No newline at end of file + cleanup(): Promise; + mkLabel(levid: any): any; + rt_mkuuid(); + spawnAtNode(arg0: any, arg1: any); + $t: Thread; + $service: any; // todo 2021-06-13; identify what the right interface here should be + debug(arg0: string); + __sched: SchedulerInterface; + __mbox: MailboxInterface; + sendMessageNoChecks( + toPid: any, + message: import("./Lval.mjs").LVal, + arg2?: boolean, + ): any; + ret(arg0: any); + // ret_raw () + // tailcall(funclos: any, __unit: any); + persist(obj, path); + xconsole: Console; +} diff --git a/rt/src/SandboxStatus.mts b/rt/src/SandboxStatus.mts index 72d66947..a22051df 100644 --- a/rt/src/SandboxStatus.mts +++ b/rt/src/SandboxStatus.mts @@ -1,100 +1,95 @@ import { Level } from "./Level.mjs"; export interface HnState { - isNormal (): boolean - checkGuard () : void - getTrapper (): any - declassificationAllowed () : boolean - lev : Level + isNormal(): boolean; + checkGuard(): void; + getTrapper(): any; + declassificationAllowed(): boolean; + lev: Level; } -class NormalState implements HnState { - name:string - constructor (name="NORMAL") { - this.name = name - } - - - checkGuard () { - - } - - isNormal () { - return true; - } - - declassificationAllowed() { - return true; - } - - toString () { - return this.name - } - - getTrapper () { - return null; - } - - get lev () { - throw new Error ("handler usage error") - return null; - } +class NormalState implements HnState { + name: string; + constructor(name = "NORMAL") { + this.name = name; + } + + checkGuard() {} + + isNormal() { + return true; + } + + declassificationAllowed() { + return true; + } + + toString() { + return this.name; + } + + getTrapper() { + return null; + } + + get lev() { + throw new Error("handler usage error"); + return null; + } } class InHandlerState extends NormalState { - trapper: any; - _lev : Level - constructor (f,lev, checkGuard ) { - super ("INHANDLER"); - this.trapper = f; - this._lev = lev - this.checkGuard = checkGuard - } - - get lev () { - return this._lev - } - - isNormal () { - return false; - } - - getTrapper() { - return this.trapper; - } - - declassificationAllowed () { - return false; - } - + trapper: any; + _lev: Level; + constructor(f, lev, checkGuard) { + super("INHANDLER"); + this.trapper = f; + this._lev = lev; + this.checkGuard = checkGuard; + } + + get lev() { + return this._lev; + } + + isNormal() { + return false; + } + + getTrapper() { + return this.trapper; + } + + declassificationAllowed() { + return false; + } } - class InSandboxState extends NormalState { - trapper: any; - _lev : Level - constructor (f, lev ) { - super ("INSANDBOX"); - this.trapper = f; - this._lev = lev - } - - get lev () { - return this._lev - } - - isNormal () { - return false; - } - - getTrapper() { - return this.trapper; - } + trapper: any; + _lev: Level; + constructor(f, lev) { + super("INSANDBOX"); + this.trapper = f; + this._lev = lev; + } + + get lev() { + return this._lev; + } + + isNormal() { + return false; + } + + getTrapper() { + return this.trapper; + } } -export const HandlerState = { - NORMAL : NormalState, - INHANDLER : InHandlerState, - INSANDBOX : InSandboxState -} +export const HandlerState = { + NORMAL: NormalState, + INHANDLER: InHandlerState, + INSANDBOX: InSandboxState, +}; -export default HandlerState +export default HandlerState; diff --git a/rt/src/Scheduler.mts b/rt/src/Scheduler.mts index e580e714..cdc9b87b 100644 --- a/rt/src/Scheduler.mts +++ b/rt/src/Scheduler.mts @@ -1,254 +1,260 @@ -'use strict'; -import { v4 as uuidv4} from 'uuid' -import { Thread } from './Thread.mjs'; -import runId from './runId.mjs'; -import { __unit } from './UnitVal.mjs'; -import { mkTuple } from './ValuesUtil.mjs'; -import { SchedulerInterface } from './SchedulerInterface.mjs'; -import { RuntimeInterface } from './RuntimeInterface.mjs'; -import { LVal } from './Lval.mjs' -import {ProcessID, pid_equals} from './process.mjs' -import SandboxStatus from './SandboxStatus.mjs' -import {ThreadError, TroupeError} from './TroupeError.mjs' -import {lub} from './Level.mjs' -import { getCliArgs, TroupeCliArg } from './TroupeCliArgs.mjs'; - -import {SYSTEM_PROCESS_STRING} from './Constants.mjs' +"use strict"; +import { v4 as uuidv4 } from "uuid"; +import { Thread } from "./Thread.mjs"; +import runId from "./runId.mjs"; +import { __unit } from "./UnitVal.mjs"; +import { mkTuple } from "./ValuesUtil.mjs"; +import { SchedulerInterface } from "./SchedulerInterface.mjs"; +import { RuntimeInterface } from "./RuntimeInterface.mjs"; +import { LVal } from "./Lval.mjs"; +import { ProcessID, pid_equals } from "./process.mjs"; +import SandboxStatus from "./SandboxStatus.mjs"; +import { ThreadError, TroupeError } from "./TroupeError.mjs"; +import { lub } from "./Level.mjs"; +import { getCliArgs, TroupeCliArg } from "./TroupeCliArgs.mjs"; + +import { SYSTEM_PROCESS_STRING } from "./Constants.mjs"; const argv = getCliArgs(); -const showStack = argv[TroupeCliArg.ShowStack] -import { mkLogger } from './logger.mjs' -const logger = mkLogger('scheduler'); -const info = x => logger.info(x) -const debug = x => logger.debug(x) +const showStack = argv[TroupeCliArg.ShowStack]; +import { mkLogger } from "./logger.mjs"; +const logger = mkLogger("scheduler"); +const info = (x) => logger.info(x); +const debug = (x) => logger.debug(x); const STACKDEPTH = 150; -let TerminationStatus = { - OK: 0, - ERR: 1 -} +const TerminationStatus = { + OK: 0, + ERR: 1, +}; export class Scheduler implements SchedulerInterface { - rt_uuid: any; - __funloop: Thread[]; - __blocked: any[]; - __alive: {}; - __currentThread: Thread; - stackcounter: number; - __unit: any; - rtObj : RuntimeInterface - __node: any; - __stopWhenAllThreadsAreDone: boolean; - __stopRuntime: () => void; - constructor(rtObj:RuntimeInterface) { - this.rt_uuid = runId; - this.rtObj = rtObj - this.__funloop = new Array() - this.__blocked = new Array() - this.__alive = {} // new Set(); - - this.__currentThread = null; // current thread object - - this.stackcounter = 0; - - // the unit value - this.__unit = __unit - } - - - resetScheduler() { - // console.log (`The current length of __funloop is ${this.__funloop.length}`) - // console.log (`The number of active threads is ${Object.keys(this.__alive).length}`) - for (let x in this.__alive) { - if (this.currentThreadId.val.toString() == x) { - // console.log (x, "ACTIVE") - } else { - // console.log (x, "KILLING"); - delete this.__alive[x] - } - } - this.__blocked = [] - this.__funloop = [] - // console.log (`The number of active threads is ${Object.keys(this.__alive).length}`) - // console.log (`The number of blocked threads is ${this.__blocked.length}`) - } - - done () { - this.notifyMonitors(); - // console.log (this.__currentThread.processDebuggingName, this.currentThreadId.val.toString(), "done") - delete this.__alive [this.currentThreadId.val.toString()]; - } - - - halt (persist=null) { - this.raiseCurrentThreadPCToBlockingLev(); - let retVal = new LVal (this.__currentThread.r0_val, - lub(this.__currentThread.bl, this.__currentThread.r0_lev), - lub(this.__currentThread.bl, this.__currentThread.r0_tlev)) - - this.notifyMonitors (); - - delete this.__alive[this.currentThreadId.val.toString()]; - console.log(">>> Main thread finished with value:", retVal.stringRep()); - if (persist) { - this.rtObj.persist (retVal, persist ) - console.log ("Saved the result value in file", persist) - } - return null; - } - - notifyMonitors (status = TerminationStatus.OK, errstr = null) { - let mkVal = this.__currentThread.mkVal - let ids = Object.keys (this.__currentThread.monitors); - for ( let i = 0; i < ids.length; i ++ ) { - let id = ids[i]; - let toPid = this.__currentThread.monitors[id].pid; - let refUUID = this.__currentThread.monitors[id].uuid; - let thisPid = this.__currentThread.tid; - let statusVal = this.__currentThread.mkVal ( status ) ; - let reason = TerminationStatus.OK == status ? statusVal : - mkTuple ( [statusVal, mkVal (errstr)] ); - let message = mkVal (mkTuple ([ mkVal("DONE"), refUUID, thisPid, reason])) - this.rtObj.sendMessageNoChecks ( toPid, message , false) // false flag means no need to return in the process - } - } - - raiseCurrentThreadPC (l) { - this.__currentThread.raiseCurrentThreadPC(l); - } - - raiseCurrentThreadPCToBlockingLev () { - this.__currentThread.raiseCurrentThreadPCToBlockingLev() - } - - - raiseBlockingThreadLev (l) { - this.__currentThread.raiseBlockingThreadLev(l); - } - - - pinipush (l, cap) { - this.__currentThread.pcpinipush(l, cap) - } - - pinipop (cap) { - return this.__currentThread.pinipop(cap); - } - - mkVal(x) { - return this.__currentThread.mkVal (x); - } - - mkValPos (x,p) { - return this.__currentThread.mkValPos (x,p); - } - - mkCopy (x) { - return this.__currentThread.mkCopy (x); - } - - - initScheduler(node, stopWhenAllThreadsAreDone = false, stopRuntime = () => {}) { - this.__node = node; - this.__stopWhenAllThreadsAreDone = stopWhenAllThreadsAreDone; - this.__stopRuntime = stopRuntime - } - - - - get currentThreadId() { - return this.__currentThread.tid; + rt_uuid: any; + __funloop: Thread[]; + __blocked: any[]; + __alive: {}; + __currentThread: Thread; + stackcounter: number; + __unit: any; + rtObj: RuntimeInterface; + __node: any; + __stopWhenAllThreadsAreDone: boolean; + __stopRuntime: () => void; + constructor(rtObj: RuntimeInterface) { + this.rt_uuid = runId; + this.rtObj = rtObj; + this.__funloop = []; + this.__blocked = []; + this.__alive = {}; // new Set(); + + this.__currentThread = null; // current thread object + + this.stackcounter = 0; + + // the unit value + this.__unit = __unit; + } + + resetScheduler() { + // console.log (`The current length of __funloop is ${this.__funloop.length}`) + // console.log (`The number of active threads is ${Object.keys(this.__alive).length}`) + for (const x in this.__alive) { + if (this.currentThreadId.val.toString() == x) { + // console.log (x, "ACTIVE") + } else { + // console.log (x, "KILLING"); + delete this.__alive[x]; + } } - - set handlerState (st) { - this.__currentThread.handlerState = st; - } - - get handlerState () { - return this.__currentThread.handlerState; - } - - resumeLoopAsync() { - setImmediate(() => {this.loop()}); + this.__blocked = []; + this.__funloop = []; + // console.log (`The number of active threads is ${Object.keys(this.__alive).length}`) + // console.log (`The number of blocked threads is ${this.__blocked.length}`) + } + + done() { + this.notifyMonitors(); + // console.log (this.__currentThread.processDebuggingName, this.currentThreadId.val.toString(), "done") + delete this.__alive[this.currentThreadId.val.toString()]; + } + + halt(persist = null) { + this.raiseCurrentThreadPCToBlockingLev(); + const retVal = new LVal( + this.__currentThread.r0_val, + lub(this.__currentThread.bl, this.__currentThread.r0_lev), + lub(this.__currentThread.bl, this.__currentThread.r0_tlev), + ); + + this.notifyMonitors(); + + delete this.__alive[this.currentThreadId.val.toString()]; + console.log(">>> Main thread finished with value:", retVal.stringRep()); + if (persist) { + this.rtObj.persist(retVal, persist); + console.log("Saved the result value in file", persist); } - - - - scheduleThread(t) { - this.__funloop.push(t) - } - - - createNewProcessIDAtLevel(pcArg, isSystem = false) { - let pid = isSystem ? SYSTEM_PROCESS_STRING : uuidv4(); - let pidObj = new ProcessID(this.rt_uuid, pid, this.__node); - return new LVal(pidObj, pcArg); - } - - - - scheduleNewThreadAtLevel (thefun, arg, levpc, levblock, ismain = false, persist=null, isSystem = false) { - let newPid = this.createNewProcessIDAtLevel(levpc, isSystem); - - let halt = ismain ? ()=> { this.halt (persist) } : - () => { this.done () }; - - - let t = new Thread - ( newPid - , halt - , thefun - , arg - , levpc - , levblock - , new SandboxStatus.NORMAL() - , this.rtObj - , this ); - - - this.__alive[newPid.val.toString()] = t; - this.scheduleThread (t) - return newPid; - } - - schedule(thefun, args, nm) { - this.__currentThread.runNext (thefun, args, nm); - this.scheduleThread(this.__currentThread) + return null; + } + + notifyMonitors(status = TerminationStatus.OK, errstr = null) { + const mkVal = this.__currentThread.mkVal; + const ids = Object.keys(this.__currentThread.monitors); + for (let i = 0; i < ids.length; i++) { + const id = ids[i]; + const toPid = this.__currentThread.monitors[id].pid; + const refUUID = this.__currentThread.monitors[id].uuid; + const thisPid = this.__currentThread.tid; + const statusVal = this.__currentThread.mkVal(status); + const reason = + TerminationStatus.OK == status + ? statusVal + : mkTuple([statusVal, mkVal(errstr)]); + const message = mkVal(mkTuple([mkVal("DONE"), refUUID, thisPid, reason])); + this.rtObj.sendMessageNoChecks(toPid, message, false); // false flag means no need to return in the process } - - - blockThread(t) { - this.__blocked.push(t) - } - - - unblockThread(pid) { - for (let i = 0; i < this.__blocked.length; i++) { - if (pid_equals(this.__blocked[i].tid, pid)) { - this.scheduleThread(this.__blocked[i]); - this.__blocked.splice(i, 1); - break; - } + } + + raiseCurrentThreadPC(l) { + this.__currentThread.raiseCurrentThreadPC(l); + } + + raiseCurrentThreadPCToBlockingLev() { + this.__currentThread.raiseCurrentThreadPCToBlockingLev(); + } + + raiseBlockingThreadLev(l) { + this.__currentThread.raiseBlockingThreadLev(l); + } + + pinipush(l, cap) { + this.__currentThread.pcpinipush(l, cap); + } + + pinipop(cap) { + return this.__currentThread.pinipop(cap); + } + + mkVal(x) { + return this.__currentThread.mkVal(x); + } + + mkValPos(x, p) { + return this.__currentThread.mkValPos(x, p); + } + + mkCopy(x) { + return this.__currentThread.mkCopy(x); + } + + initScheduler( + node, + stopWhenAllThreadsAreDone = false, + stopRuntime = () => {}, + ) { + this.__node = node; + this.__stopWhenAllThreadsAreDone = stopWhenAllThreadsAreDone; + this.__stopRuntime = stopRuntime; + } + + get currentThreadId() { + return this.__currentThread.tid; + } + + set handlerState(st) { + this.__currentThread.handlerState = st; + } + + get handlerState() { + return this.__currentThread.handlerState; + } + + resumeLoopAsync() { + setImmediate(() => { + this.loop(); + }); + } + + scheduleThread(t) { + this.__funloop.push(t); + } + + createNewProcessIDAtLevel(pcArg, isSystem = false) { + const pid = isSystem ? SYSTEM_PROCESS_STRING : uuidv4(); + const pidObj = new ProcessID(this.rt_uuid, pid, this.__node); + return new LVal(pidObj, pcArg); + } + + scheduleNewThreadAtLevel( + thefun, + arg, + levpc, + levblock, + ismain = false, + persist = null, + isSystem = false, + ) { + const newPid = this.createNewProcessIDAtLevel(levpc, isSystem); + + const halt = ismain + ? () => { + this.halt(persist); } + : () => { + this.done(); + }; + + const t = new Thread( + newPid, + halt, + thefun, + arg, + levpc, + levblock, + new SandboxStatus.NORMAL(), + this.rtObj, + this, + ); + + this.__alive[newPid.val.toString()] = t; + this.scheduleThread(t); + return newPid; + } + + schedule(thefun, args, nm) { + this.__currentThread.runNext(thefun, args, nm); + this.scheduleThread(this.__currentThread); + } + + blockThread(t) { + this.__blocked.push(t); + } + + unblockThread(pid) { + for (let i = 0; i < this.__blocked.length; i++) { + if (pid_equals(this.__blocked[i].tid, pid)) { + this.scheduleThread(this.__blocked[i]); + this.__blocked.splice(i, 1); + break; + } } + } + isAlive(tid) { + return this.__alive[tid.val.toString()] != null; + } - isAlive(tid) { - return (this.__alive[tid.val.toString()] != null); - } - - getThread (tid) { - return this.__alive[tid.val.toString()]; - } - + getThread(tid) { + return this.__alive[tid.val.toString()]; + } - stopThreadWithErrorMessage (t:Thread, s:string ) { - this.notifyMonitors(TerminationStatus.ERR, s) ; - delete this.__alive [t.tid.val.toString()]; - } + stopThreadWithErrorMessage(t: Thread, s: string) { + this.notifyMonitors(TerminationStatus.ERR, s); + delete this.__alive[t.tid.val.toString()]; + } - /*****************************************************************************\ + /*****************************************************************************\ 2018-02-18: AA: a hypothesis about memory management in V8 @@ -264,58 +270,65 @@ export class Scheduler implements SchedulerInterface { \*****************************************************************************/ - - loop() { - const $$LOOPBOUND = 500000; - let _FUNLOOP = this.__funloop - let _curThread: Thread; - let dest; - try { - for (let $$loopiter = 0; $$loopiter < $$LOOPBOUND && _FUNLOOP.length > 0; $$loopiter ++ ) { - _curThread = _FUNLOOP.shift(); - this.__currentThread = _curThread; - dest = _curThread.next - let ttl = 1000; // magic constant; 2021-04-29 - while (dest && ttl -- ) { - // if (showStack) { // 2021-04-24; AA; TODO: profile the addition of this conditional in this tight loop - // this.__currentThread.showStack() - // } - // console.log (">>>>>>>>>>") - // console.log (dest.toString()) - // console.log ("<<<<<<<<<<") - // if (dest.debugname ) { - // console.log (" -- ", dest.debugname) - // } - dest = dest () - } - - if (dest) { - _curThread.handlerState.checkGuard() - - _curThread.next = dest ; - _FUNLOOP.push (_curThread); - } - } - } catch (e) { - if (e instanceof TroupeError) { - e.handleError(this); - } else { - console.log ("--- Schedule module caught an internal exception ---") - console.log ("--- The following output may help identify a bug in the runtime ---") - console.log ("Destination function\n" , dest) - this.__currentThread.showStack() - throw e; - } + loop() { + const $$LOOPBOUND = 500000; + const _FUNLOOP = this.__funloop; + let _curThread: Thread; + let dest; + try { + for ( + let $$loopiter = 0; + $$loopiter < $$LOOPBOUND && _FUNLOOP.length > 0; + $$loopiter++ + ) { + _curThread = _FUNLOOP.shift(); + this.__currentThread = _curThread; + dest = _curThread.next; + let ttl = 1000; // magic constant; 2021-04-29 + while (dest && ttl--) { + // if (showStack) { // 2021-04-24; AA; TODO: profile the addition of this conditional in this tight loop + // this.__currentThread.showStack() + // } + // console.log (">>>>>>>>>>") + // console.log (dest.toString()) + // console.log ("<<<<<<<<<<") + // if (dest.debugname ) { + // console.log (" -- ", dest.debugname) + // } + dest = dest(); } - if (_FUNLOOP.length > 0) { - // we are not really done, but are just hacking around the V8's memory management - this.resumeLoopAsync(); - } - - if (this.__stopWhenAllThreadsAreDone && Object.keys(this.__alive).length == 0 ) { - this.__stopRuntime(); + if (dest) { + _curThread.handlerState.checkGuard(); + + _curThread.next = dest; + _FUNLOOP.push(_curThread); } + } + } catch (e) { + if (e instanceof TroupeError) { + e.handleError(this); + } else { + console.log("--- Schedule module caught an internal exception ---"); + console.log( + "--- The following output may help identify a bug in the runtime ---", + ); + console.log("Destination function\n", dest); + this.__currentThread.showStack(); + throw e; + } } - -} \ No newline at end of file + + if (_FUNLOOP.length > 0) { + // we are not really done, but are just hacking around the V8's memory management + this.resumeLoopAsync(); + } + + if ( + this.__stopWhenAllThreadsAreDone && + Object.keys(this.__alive).length == 0 + ) { + this.__stopRuntime(); + } + } +} diff --git a/rt/src/SchedulerInterface.mts b/rt/src/SchedulerInterface.mts index 742f3b81..901127cf 100644 --- a/rt/src/SchedulerInterface.mts +++ b/rt/src/SchedulerInterface.mts @@ -1,20 +1,19 @@ import { Thread } from "./Thread.mjs"; export interface SchedulerInterface { - // tailToTroupeFun(f: any, arg:any) - // tailToTroupeFun_raw(f: any) - // stepThread(); - resetScheduler(); - __alive: any; - scheduleNewThreadAtLevel(fun: any, arg: any, pc: any, blockingTopLev: any); - scheduleThread(theThread: any); - resumeLoopAsync(); - blockThread(__currentThread: Thread); - isAlive(toPid: any); - getThread(toPid: any); - unblockThread(toPid: any); - schedule(fun: any, args: any[], namespace: any); - __currentThread: Thread; - stopThreadWithErrorMessage (t:Thread, s:string) - -} \ No newline at end of file + // tailToTroupeFun(f: any, arg:any) + // tailToTroupeFun_raw(f: any) + // stepThread(); + resetScheduler(); + __alive: any; + scheduleNewThreadAtLevel(fun: any, arg: any, pc: any, blockingTopLev: any); + scheduleThread(theThread: any); + resumeLoopAsync(); + blockThread(__currentThread: Thread); + isAlive(toPid: any); + getThread(toPid: any); + unblockThread(toPid: any); + schedule(fun: any, args: any[], namespace: any); + __currentThread: Thread; + stopThreadWithErrorMessage(t: Thread, s: string); +} diff --git a/rt/src/SysState.mts b/rt/src/SysState.mts index 7bb42e19..b9b18df3 100644 --- a/rt/src/SysState.mts +++ b/rt/src/SysState.mts @@ -2,14 +2,13 @@ import { RuntimeInterface } from "./RuntimeInterface.mjs"; let __state: RuntimeInterface = null; -export function setRuntimeObject (x) { - if (__state) { - throw new Error ("Runtime object is already set") - } - __state = x +export function setRuntimeObject(x) { + if (__state) { + throw new Error("Runtime object is already set"); + } + __state = x; } - -export function getRuntimeObject () { - return __state; +export function getRuntimeObject() { + return __state; } diff --git a/rt/src/Thread.mts b/rt/src/Thread.mts index d7464d44..fef4b1f1 100644 --- a/rt/src/Thread.mts +++ b/rt/src/Thread.mts @@ -1,250 +1,254 @@ -import * as levels from './Level.mjs' -import { DowngradeDimension, DowngradeKind, DowngradeResult, DowngradeErrorReason, ValidateDowngradeParams } from './DowngradeEnums.mjs'; -import { LVal, LValCopyAt } from './Lval.mjs'; -import { HandlerError, ImplementationError, StrThreadError } from './TroupeError.mjs'; -import { getCliArgs, TroupeCliArg } from './TroupeCliArgs.mjs'; +import * as levels from "./Level.mjs"; import { - getDowngradeErrorMessage, -} from './DowngradeFormatter.mjs'; + DowngradeDimension, + DowngradeKind, + DowngradeResult, + DowngradeErrorReason, + ValidateDowngradeParams, +} from "./DowngradeEnums.mjs"; +import { LVal, LValCopyAt } from "./Lval.mjs"; +import { + HandlerError, + ImplementationError, + StrThreadError, +} from "./TroupeError.mjs"; +import { getCliArgs, TroupeCliArg } from "./TroupeCliArgs.mjs"; +import { getDowngradeErrorMessage } from "./DowngradeFormatter.mjs"; const argv = getCliArgs(); -let logLevel = argv[TroupeCliArg.Debug]? 'debug' : 'info' -import { mkLogger } from './logger.mjs' -const logger = mkLogger('thread', logLevel); -const debug = x => logger.debug(x) -let lub = levels.lub; -let flowsTo = levels.flowsTo -import { v4 as uuidv4} from 'uuid' - -import { TroupeType } from './TroupeTypes.mjs' -import { RuntimeInterface } from './RuntimeInterface.mjs'; -import { __unit } from './UnitVal.mjs'; -import { Level } from './Level.mjs'; -import { SchedulerInterface } from './SchedulerInterface.mjs'; -import { getRuntimeObject } from './SysState.mjs'; -import { HnState } from './SandboxStatus.mjs'; - +const logLevel = argv[TroupeCliArg.Debug] ? "debug" : "info"; +import { mkLogger } from "./logger.mjs"; +const logger = mkLogger("thread", logLevel); +const debug = (x) => logger.debug(x); +const lub = levels.lub; +const flowsTo = levels.flowsTo; +import { v4 as uuidv4 } from "uuid"; -let isPiniMode = argv[TroupeCliArg.Pini]?true:false; +import { TroupeType } from "./TroupeTypes.mjs"; +import { RuntimeInterface } from "./RuntimeInterface.mjs"; +import { __unit } from "./UnitVal.mjs"; +import { Level } from "./Level.mjs"; +import { SchedulerInterface } from "./SchedulerInterface.mjs"; +import { getRuntimeObject } from "./SysState.mjs"; +import { HnState } from "./SandboxStatus.mjs"; +const isPiniMode = argv[TroupeCliArg.Pini] ? true : false; export enum PCDeclassificationPurpose { - Full="pcpush", - Pini="pinipush" + Full = "pcpush", + Pini = "pinipush", } // stack frame configuration constants -export const CALLSIZE = 5 -const SPOFFSET = CALLSIZE -const PCOFFSET = 4 -export const RETOFFSET = 3 -const MCLEAROFFSET = 2 -const BRANCHFLAGOFFSET = 1 +export const CALLSIZE = 5; +const SPOFFSET = CALLSIZE; +const PCOFFSET = 4; +export const RETOFFSET = 3; +const MCLEAROFFSET = 2; +const BRANCHFLAGOFFSET = 1; -const BRANCH_FLAG_OFF = false -const BRANCH_FLAG_ON = true +const BRANCH_FLAG_OFF = false; +const BRANCH_FLAG_ON = true; export class Capability { - /* - - Linked capabilities with payload. - + /* + + Linked capabilities with payload. + The "token" aspect of the capability is represented as a string. These capabilites carry payload data that can be used by the runtime upon their successful check. This is useful because the runtime does not need to carry the data itself, and just - rely on the checks of the tokens. A special aspect of the payload is that - they carry a link to the previous capability, and this is represented in the `priv` - field of this class. + rely on the checks of the tokens. A special aspect of the payload is that + they carry a link to the previous capability, and this is represented in the `priv` + field of this class. We use these kinds of capabilities to enforce a scoping discipline on pcpush/pinipush and raise/lower mailbox mechanisms. */ - - _troupeType: TroupeType - uid : string - data : T - prev: string - dataLevel: Level - constructor (c: string, l:T,p: string , dataLevel ) { - this.uid = c; - this.data = l; - this.prev = p // provides scoping control; needs better name; AA; 2020-02-08 - this.dataLevel = dataLevel - this._troupeType = TroupeType.CAPABILITY - } - stringRep() : string { - return this.uid; - } + + _troupeType: TroupeType; + uid: string; + data: T; + prev: string; + dataLevel: Level; + constructor(c: string, l: T, p: string, dataLevel) { + this.uid = c; + this.data = l; + this.prev = p; // provides scoping control; needs better name; AA; 2020-02-08 + this.dataLevel = dataLevel; + this._troupeType = TroupeType.CAPABILITY; + } + stringRep(): string { + return this.uid; + } } -class MboxClearance { - boost_level: any; - pc_at_creation: any; - constructor (lclear:any, pc:any) { +class MboxClearance { + boost_level: any; + pc_at_creation: any; + constructor(lclear: any, pc: any) { this.boost_level = lclear; this.pc_at_creation = pc; } - stringRep () { - return this.boost_level.stringRep () + stringRep() { + return this.boost_level.stringRep(); } - - } - class Mailbox extends Array { - mclear : MboxClearance ; - caps : string; - - peek_cache_index : number - peek_cache_position: number - peek_cache_lowb : Level - peek_cache_highb : Level - - - constructor () { - super () - this.mclear = new MboxClearance (levels.BOT, levels.BOT); - this.caps = null; - - this.peek_cache_index = null; - this.peek_cache_position = null; - this.peek_cache_lowb = null; - this.peek_cache_highb = null - } - newMessage (x) { - this.push(x); - } - - - resetPeekCache () { - this.peek_cache_index = null; - this.peek_cache_lowb = null; - this.peek_cache_position = null; - this.peek_cache_lowb = null; - this.peek_cache_highb = null - } + mclear: MboxClearance; + caps: string; + + peek_cache_index: number; + peek_cache_position: number; + peek_cache_lowb: Level; + peek_cache_highb: Level; + + constructor() { + super(); + this.mclear = new MboxClearance(levels.BOT, levels.BOT); + this.caps = null; + + this.peek_cache_index = null; + this.peek_cache_position = null; + this.peek_cache_lowb = null; + this.peek_cache_highb = null; + } + newMessage(x) { + this.push(x); + } + resetPeekCache() { + this.peek_cache_index = null; + this.peek_cache_lowb = null; + this.peek_cache_position = null; + this.peek_cache_lowb = null; + this.peek_cache_highb = null; + } } class ThreadState { - callStack: any [] - constructor (s: any []) { - this.callStack = s + callStack: any[]; + constructor(s: any[]) { + this.callStack = s; } } +export class SleepTimeout { + sleepingUntil: number; + timeoutObject: any; + resumeThread: Thread; + timeLeft: number; + constructor(delay, th) { + this.timeoutObject = setTimeout(() => { + this.afterTimeout(); + }, delay); + this.sleepingUntil = Date.now() + delay; + this.resumeThread = th; + this.timeLeft = null; + } -export class SleepTimeout { - sleepingUntil : number - timeoutObject : any; - resumeThread : Thread - timeLeft : number; - constructor(delay, th) { - this.timeoutObject = setTimeout( () => {this.afterTimeout()}, delay); - this.sleepingUntil = Date.now () + delay - this.resumeThread = th - this.timeLeft = null; - } - - pause () { - clearTimeout(this.timeoutObject) - this.timeLeft = Math.max (0, this.sleepingUntil - Date.now()) - } + pause() { + clearTimeout(this.timeoutObject); + this.timeLeft = Math.max(0, this.sleepingUntil - Date.now()); + } - resume (newThread) { - this.resumeThread = newThread; - this.sleepingUntil = Date.now() + this.timeLeft; - this.timeoutObject = setTimeout (() => {this.afterTimeout()}, this.timeLeft) - this.timeLeft = null; - } + resume(newThread) { + this.resumeThread = newThread; + this.sleepingUntil = Date.now() + this.timeLeft; + this.timeoutObject = setTimeout(() => { + this.afterTimeout(); + }, this.timeLeft); + this.timeLeft = null; + } - resetTimeout(newDelay,newThread) { - this.resumeThread = newThread; - this.timeoutObject = setTimeout (() => {this.afterTimeout()}, newDelay) - this.sleepingUntil = Date.now() + newDelay - } + resetTimeout(newDelay, newThread) { + this.resumeThread = newThread; + this.timeoutObject = setTimeout(() => { + this.afterTimeout(); + }, newDelay); + this.sleepingUntil = Date.now() + newDelay; + } - afterTimeout () { - let theThread = this.resumeThread; - theThread.sleepTimeout = null; - theThread.returnSuspended (__unit); - let sched = getRuntimeObject().__sched - sched.scheduleThread (theThread) - sched.resumeLoopAsync() - } + afterTimeout() { + const theThread = this.resumeThread; + theThread.sleepTimeout = null; + theThread.returnSuspended(__unit); + const sched = getRuntimeObject().__sched; + sched.scheduleThread(theThread); + sched.resumeLoopAsync(); + } } export class Thread { - tid: any; - pc: Level; - bl: Level; + tid: any; + pc: Level; + bl: Level; + + // registers + r0_val: any; + private _r0_lev: any; + public get r0_lev(): any { + return this._r0_lev; + } + public set r0_lev(value: any) { + if (!value?.isLevel) { + console.log("RO-LEV debugging"); + console.log(new Error().stack); + this.showStack(); + } + this._r0_lev = value; + } + r0_tlev: any; + + pini_uuid: string; + + handlerState: HnState; + monitors: {}; + killCounter: number; + // sleeping: boolean; + // sleepingUntil: number; + // wakeupFn: () => void; + // timeoutObject: any; + sleepTimeout: SleepTimeout; + rtObj: RuntimeInterface; + sched: SchedulerInterface; + mailbox: Mailbox; + next: () => any; + callStack: any[]; + _sp: number; + sparseSlot: number; // slot on the stack holding the sparse bit (whether data is bounded by PC) + + processDebuggingName: string; + + failureRate = 0; + failureStartTime = 0; + + get sleeping() { + return this.sleepTimeout != null; + } + constructor(tid, ret, theFun, arg, pc, levblock, handlerState, rtObj, sched) { + this.tid = tid; + this.pc = pc; + this.bl = levblock; + this.pini_uuid = null; + this.handlerState = handlerState; + this.monitors = {}; + this.killCounter = 0; + this.sleepTimeout = null; // no sleep command + // this.sleeping = false; + // this.timeoutObject = null; + this.rtObj = rtObj; + this.sched = sched; + this.mailbox = new Mailbox(); + this.processDebuggingName = null; - // registers - r0_val: any; - private _r0_lev: any; - public get r0_lev(): any { - return this._r0_lev; - } - public set r0_lev(value: any) { - if (!value?.isLevel ) { - console.log ("RO-LEV debugging") - console.log ( (new Error().stack) ) - this.showStack() - } - this._r0_lev = value; - } - r0_tlev: any; - - pini_uuid : string; - - handlerState: HnState; - monitors: {}; - killCounter: number; - // sleeping: boolean; - // sleepingUntil: number; - // wakeupFn: () => void; - // timeoutObject: any; - sleepTimeout : SleepTimeout - rtObj: RuntimeInterface; - sched : SchedulerInterface; - mailbox: Mailbox; - next : () => any; - callStack : any [] - _sp : number; - sparseSlot : number; // slot on the stack holding the sparse bit (whether data is bounded by PC) - - processDebuggingName: string; - - failureRate: number = 0 - failureStartTime : number = 0 - - get sleeping () { - return (this.sleepTimeout != null); - } - - constructor(tid, ret, theFun, arg, pc, levblock, handlerState, rtObj, sched) { - this.tid = tid; - this.pc = pc; - this.bl = levblock; - this.pini_uuid = null; - this.handlerState = handlerState; - this.monitors = {}; - this.killCounter = 0; - this.sleepTimeout = null; // no sleep command - // this.sleeping = false; - // this.timeoutObject = null; - this.rtObj = rtObj; - this.sched = sched; - this.mailbox = new Mailbox(); - this.processDebuggingName = null; - - /* + /* The call frames have the structure @@ -257,600 +261,605 @@ export class Thread { |---------+-------------------+--------------+-----------------------------+---------------+-------------------------+--------------------| | sp - 5 | sp - 4 | sp - 3 | sp - 2 | sp - 1 | sp ... (sp + framesize) | sp + framesize + 1 | - - The branching bit indicates whether the execution of this frame invoked any branch - instructions. Upon returns we check whether the flag is set, and in that case - we enforce that the current mailbox clearance must match the one at the time of + + The branching bit indicates whether the execution of this frame invoked any branch + instructions. Upon returns we check whether the flag is set, and in that case + we enforce that the current mailbox clearance must match the one at the time of the invocation. - -- AA; 2020-02-12 + -- AA; 2020-02-12 - prev_sp | pc_at_ret_point | ret_cb | mclear | branch_bit | <... locals ... > + prev_sp | pc_at_ret_point | ret_cb | mclear | branch_bit | <... locals ... > ^ | | sp - - */ - - - /* + + */ + + /* this.callStack = [ 0, pc, null, null, BRANCH_FLAG_OFF - , 5, pc, ret, this.mailbox.mclear, BRANCH_FLAG_OFF] + , 5, pc, ret, this.mailbox.mclear, BRANCH_FLAG_OFF] // auxiliary bottom element of the call stack; never called - // but is convenient for keeping track of the PC + // but is convenient for keeping track of the PC this._sp = CALLSIZE * 2 */ - this.callStack = [ 0, pc, ret, this.mailbox.mclear, BRANCH_FLAG_OFF] - this._sp = CALLSIZE - // let arg0 = theArgs [0] - // let arg1 = theArgs [1] - this.r0_val = arg.val - this.r0_lev = arg.lev - this.r0_tlev = arg.tlev - this.next = theFun - // () => { - // return theFun(); - // } - } + this.callStack = [0, pc, ret, this.mailbox.mclear, BRANCH_FLAG_OFF]; + this._sp = CALLSIZE; + // let arg0 = theArgs [0] + // let arg1 = theArgs [1] + this.r0_val = arg.val; + this.r0_lev = arg.lev; + this.r0_tlev = arg.tlev; + this.next = theFun; + // () => { + // return theFun(); + // } + } + exportState() { + const __state = { + pc: this.pc, + bl: this.pc, + pini_uuid: this.pini_uuid, + sp: this._sp, + next: this.next, + callStack: this.callStack, + r0_val: this.r0_val, + r0_lev: this.r0_lev, + r0_tlev: this.r0_tlev, + }; + return __state; + } - exportState () { - let __state = { - pc : this.pc, - bl : this.pc, - pini_uuid : this.pini_uuid, - sp : this._sp, - next : this.next, - callStack : this.callStack, - r0_val : this.r0_val, - r0_lev : this.r0_lev, - r0_tlev : this.r0_tlev - - } - return __state; - } + importState(__state) { + this.pc = __state.pc; + this.bl = __state.bl; + this.pini_uuid = __state.pini_uuid; + this._sp = __state.sp; + this.next = __state.next; + this.callStack = __state.callStack; + this.r0_val = __state.r0_val; + this.r0_lev = __state.r0_lev; + this.r0_tlev = __state.r0_tlev; + } - importState (__state) { - this.pc = __state.pc - this.bl = __state.bl - this.pini_uuid = __state.pini_uuid - this._sp = __state.sp - this.next = __state.next - this.callStack = __state.callStack - this.r0_val = __state.r0_val - this.r0_lev = __state.r0_lev - this.r0_tlev = __state.r0_tlev - } + resetStackForSandboxing() { + this.callStack = []; + this._sp = 0; + } - resetStackForSandboxing () { - this.callStack = [] - this._sp = 0 + showStack() { + console.log("======== SHOW STACK ========= "); + console.log(`sp = ${this._sp} sparseSlot = ${this.sparseSlot}`); + let j = this._sp - 1; + const stack = this.callStack; + while (j > 0) { + console.log( + `-${j.toString().padStart(5, "-")} branch bit: ${stack[j--]}`, + ); + const mclear = stack[j]; + console.log( + ` ${j.toString().padStart(5, " ")} mclear : ${mclear?.stringRep()}`, + ); + j--; + const ret = stack[j]; + let ret_string = ret?.debugname; + if (!ret_string) { + ret_string = ret?.toString(); + } + + console.log( + ` ${j.toString().padStart(5, " ")} ret : ${ret_string}`, + ); + j--; + console.log( + ` ${j.toString().padStart(5, " ")} pc_ret : ${stack[j]?.stringRep()}`, + ); + j--; + console.log(` ${j.toString().padStart(5, " ")} sp_prev : ${stack[j]}`); + const sp_prev = stack[j]; + j = sp_prev - 1; } + } + addMonitor(pid, r) { + this.monitors[r.val] = { pid: pid, uuid: r }; + } - showStack () { - console.log ("======== SHOW STACK ========= ") - console.log (`sp = ${this._sp} sparseSlot = ${this.sparseSlot}`) - let j = this._sp - 1 - let stack = this.callStack - while ( j > 0) { - console.log (`-${j.toString().padStart(5,'-')} branch bit: ${stack[j--]}`) - let mclear = stack[j] - console.log (` ${j.toString().padStart(5,' ')} mclear : ${mclear?.stringRep()}`) - j -- - let ret = stack [j] - let ret_string = ret?.debugname - if (!ret_string) { - ret_string = ret?.toString () - } - - console.log (` ${j.toString().padStart(5,' ')} ret : ${ret_string}`) - j -- - console.log (` ${j.toString().padStart(5,' ')} pc_ret : ${stack[j]?.stringRep()}`) - j -- - console.log (` ${j.toString().padStart(5,' ')} sp_prev : ${stack[j]}`) - let sp_prev = stack[j]; - j = sp_prev - 1 ; + private _validateDowngradeOrThrow(params: ValidateDowngradeParams): void { + const downgradeCheckResult: DowngradeResult = levels.okToDowngrade( + params.downgradeKind, + params.downgradeDimension, + )(params.levFrom, params.levTo, params.authorityLevel, params.blockLevel); + + if (downgradeCheckResult.kind === "FAILURE") { + try { + const errorMessage = getDowngradeErrorMessage( + params, + downgradeCheckResult.reason, + ); + this.threadError(errorMessage); + } catch (e) { + if (e instanceof ImplementationError) { + this.threadError(e.message, true); + } else { + throw e; } + } } + } - - - - addMonitor (pid, r) { - this.monitors[r.val] = {pid: pid, uuid: r} - } - - private _validateDowngradeOrThrow( - params: ValidateDowngradeParams - ): void { - const downgradeCheckResult: DowngradeResult = - levels.okToDowngrade(params.downgradeKind, params.downgradeDimension) - (params.levFrom, params.levTo, params.authorityLevel, params.blockLevel as Level); - - if (downgradeCheckResult.kind === "FAILURE") { - try { - const errorMessage = getDowngradeErrorMessage(params, downgradeCheckResult.reason); - this.threadError(errorMessage); - } catch (e) { - if (e instanceof ImplementationError) { - this.threadError(e.message, true); - } else { - throw e; - } - } - } - } + tailCall(f, x) { + this.setR0ToLValue(x); + return f; + } - tailCall (f, x) { - this.setR0ToLValue (x); - return f; - } + getSparseBit() { + return this.callStack[this.sparseSlot]; + } - getSparseBit() { - return this.callStack[this.sparseSlot] - } + invalidateSparseBit() { + this.callStack[this.sparseSlot] = false; + } - invalidateSparseBit() { - this.callStack[this.sparseSlot] = false; - } + private setSparseBit(b: boolean) { + this.callStack[this.sparseSlot] = b; + } - private setSparseBit(b: boolean) { - this.callStack[this.sparseSlot] = b; - } + /** + * Check whether the label of R0 (argument), the data level of R0 and the given label are bound by PC. + */ + updateSparseBitOnEntry(x: Level) { + const _pc = this.pc; + this.setSparseBit( + flowsTo(this.r0_lev, _pc) && + flowsTo(x, _pc) && + // Only non-basic types (_troupeType is defined) have a data-level + (this.r0_val._troupeType == undefined || + flowsTo(this.r0_val.dataLevel, _pc)), + ); + } - /** - * Check whether the label of R0 (argument), the data level of R0 and the given label are bound by PC. - */ - updateSparseBitOnEntry(x: Level) { - const _pc = this.pc - this.setSparseBit( - flowsTo(this.r0_lev, _pc) - && flowsTo(x, _pc) - // Only non-basic types (_troupeType is defined) have a data-level - && (this.r0_val._troupeType == undefined || flowsTo (this.r0_val.dataLevel, _pc)) - ) + /** + * If the sparse bit is set, check whether it is still valid for the returned value: + * Check whether the label of R0 (return value) and the data level of R0 are bound by PC. + */ + updateSparseBitOnReturn() { + const _pc = this.pc; + if (this.getSparseBit()) { + // only invalidating sparse bit + this.setSparseBit( + flowsTo(this.r0_lev, _pc) && + // Only non-basic types (_troupeType is defined) have a data-level + (this.r0_val._troupeType == undefined || + flowsTo(this.r0_val.dataLevel, _pc)), + ); } + } - /** - * If the sparse bit is set, check whether it is still valid for the returned value: - * Check whether the label of R0 (return value) and the data level of R0 are bound by PC. - */ - updateSparseBitOnReturn() { - const _pc = this.pc - if(this.getSparseBit()) { // only invalidating sparse bit - this.setSparseBit( - flowsTo(this.r0_lev, _pc) - // Only non-basic types (_troupeType is defined) have a data-level - && (this.r0_val._troupeType == undefined || flowsTo (this.r0_val.dataLevel, _pc)) - ) - } - } + runNext(theFun, args, nm) { + this.next = () => { + theFun.apply(nm, args); + }; + } + block(cb) { + this.next = cb; // () => { return cb(); } + } - runNext (theFun, args, nm) { - this.next = () => { - theFun.apply (nm, args); - } - } + get arg_as_lval() { + return new LVal(this.r0_val, this.r0_lev, this.r0_tlev); + } - - + pushFrame(cb, framesize = 0) { + // console.log ("CALL", this._sp, this.r0_val, framesize ) + const _prev_sp = this._sp; + this._sp = this._sp + framesize + CALLSIZE; + this.callStack[this._sp - SPOFFSET] = _prev_sp; + this.callStack[this._sp - PCOFFSET] = this.pc; + this.callStack[this._sp - RETOFFSET] = cb; + this.callStack[this._sp - MCLEAROFFSET] = this.mailbox.mclear; + this.callStack[this._sp - BRANCHFLAGOFFSET] = BRANCH_FLAG_OFF; + + // this.callStack.push (this.pc) + // this.callStack.push ( cb ) + // this.callStack.push ( this.mailbox.mclear ) + // this.callStack.push (BRANCH_FLAG_OFF) + // this._sp += FRAMESIZE; + } - block(cb) { - this.next = cb // () => { return cb(); } - } + setBranchFlag() { + this.callStack[this._sp - BRANCHFLAGOFFSET] = BRANCH_FLAG_ON; + } - get arg_as_lval () { - return new LVal (this.r0_val, this.r0_lev, this.r0_tlev); - } + returnSuspended(arg) { + // console.log("RET", this._sp) + const rv = new LValCopyAt(arg, this.pc); + this.next = () => { + return this.returnImmediateLValue(rv); + }; + } - pushFrame (cb, framesize=0) { - // console.log ("CALL", this._sp, this.r0_val, framesize ) - let _prev_sp = this._sp - this._sp = this._sp + framesize + CALLSIZE - this.callStack[this._sp - SPOFFSET] = _prev_sp - this.callStack[this._sp - PCOFFSET] = this.pc - this.callStack[this._sp - RETOFFSET] = cb - this.callStack[this._sp - MCLEAROFFSET] = this.mailbox.mclear - this.callStack[this._sp - BRANCHFLAGOFFSET] = BRANCH_FLAG_OFF - -// this.callStack.push (this.pc) -// this.callStack.push ( cb ) -// this.callStack.push ( this.mailbox.mclear ) -// this.callStack.push (BRANCH_FLAG_OFF) -// this._sp += FRAMESIZE; + throwInSuspended(arg) { + this.next = () => { + this.threadError(arg); + }; + } - } + setR0ToLValue(arg: LVal) { + this.r0_val = arg.val; + this.r0_lev = arg.lev; + this.r0_tlev = arg.tlev; + } - setBranchFlag () { - this.callStack[this._sp - BRANCHFLAGOFFSET] = BRANCH_FLAG_ON - } - - returnSuspended (arg) { - // console.log("RET", this._sp) - let rv = new LValCopyAt (arg, this.pc); - this.next = () => { - return this.returnImmediateLValue (rv); - } - } + returnImmediateLValue(arg: LVal) { + this.r0_val = arg.val; + this.r0_lev = arg.lev; + this.r0_tlev = arg.tlev; + return this.returnImmediate(); + } - throwInSuspended (arg) { - this.next = () => { - this.threadError (arg); - } - } + returnImmediate() { + const _STACK = this.callStack; + const _SP = this._sp; - setR0ToLValue (arg:LVal) { - this.r0_val = arg.val - this.r0_lev = arg.lev - this.r0_tlev = arg.tlev - } + const branchFlag = _STACK[_SP - BRANCHFLAGOFFSET]; + const lclear = _STACK[_SP - MCLEAROFFSET]; + const ret = _STACK[_SP - RETOFFSET]; - returnImmediateLValue (arg:LVal) { - this.r0_val = arg.val - this.r0_lev = arg.lev - this.r0_tlev = arg.tlev - return this.returnImmediate() + // 2021-03-23; AA -- hack: in PINI mode the blocking label is restored back to the pc upon returns + if (isPiniMode) { + this.bl = this.pc; } - returnImmediate () { - let _STACK = this.callStack - let _SP = this._sp - - let branchFlag = _STACK[_SP - BRANCHFLAGOFFSET] - let lclear = _STACK[_SP - MCLEAROFFSET] - let ret = _STACK[_SP - RETOFFSET] - - // 2021-03-23; AA -- hack: in PINI mode the blocking label is restored back to the pc upon returns - if (isPiniMode) { - this.bl = this.pc - } - - if (branchFlag) { - if (lclear != this.mailbox.mclear) { - this.threadError (`Mailbox clearance label is not restorted after being raised in a branch; stack depth = ${this._sp}` ) - } - } - this.pc = _STACK [_SP - PCOFFSET]; - this._sp = _STACK [_SP - SPOFFSET]; - this.next = ret - return ret; + if (branchFlag) { + if (lclear != this.mailbox.mclear) { + this.threadError( + `Mailbox clearance label is not restorted after being raised in a branch; stack depth = ${this._sp}`, + ); + } } + this.pc = _STACK[_SP - PCOFFSET]; + this._sp = _STACK[_SP - SPOFFSET]; + this.next = ret; + return ret; + } - - mkUuidVal () { - let pid = uuidv4(); - let uuidval = this.mkVal ( pid ); - return uuidval; - } - - - pcpinipush ( auth: any, purpose: PCDeclassificationPurpose | string, bl = this.bl ) { - let uid = uuidv4() - let cap = this.mkVal (new Capability(uid, - { bl - , pc: this.pc - , auth : auth - , purpose: purpose - }, - this.pini_uuid, - this.pc)); // 2021-05-12; AA; TODO: revisit this; alternative might be te use auth level? - // also, why not block though that will require invalidating the - // sparse bit - - this.pini_uuid = uid; - return this.returnImmediateLValue(cap) - } + mkUuidVal() { + const pid = uuidv4(); + const uuidval = this.mkVal(pid); + return uuidval; + } + pcpinipush( + auth: any, + purpose: PCDeclassificationPurpose | string, + bl = this.bl, + ) { + const uid = uuidv4(); + const cap = this.mkVal( + new Capability( + uid, + { bl, pc: this.pc, auth: auth, purpose: purpose }, + this.pini_uuid, + this.pc, + ), + ); // 2021-05-12; AA; TODO: revisit this; alternative might be te use auth level? + // also, why not block though that will require invalidating the + // sparse bit + + this.pini_uuid = uid; + return this.returnImmediateLValue(cap); + } - pcpop (cap_lval) { - if (this.pini_uuid == null) { - this.threadError ("unmatched pcpop"); - } - - let cap: Capability = cap_lval.val; - let {bl, pc, auth, purpose} = cap.data; - - // check the capability - if (this.pini_uuid != cap.uid || purpose != PCDeclassificationPurpose.Full) { - this.threadError ("Ill-scoped pinipush/pinipop"); - return null; // does not schedule anything in this thread - // effectively terminating/blocking the thread - } + pcpop(cap_lval) { + if (this.pini_uuid == null) { + this.threadError("unmatched pcpop"); + } + + const cap: Capability = cap_lval.val; + const { bl, pc, auth, purpose } = cap.data; + + // check the capability + if ( + this.pini_uuid != cap.uid || + purpose != PCDeclassificationPurpose.Full + ) { + this.threadError("Ill-scoped pinipush/pinipop"); + return null; // does not schedule anything in this thread + // effectively terminating/blocking the thread + } + + // We declassify the current blocking level to the old blocking level. + // and also the current pc to the old pc. + // We check that there is sufficient authority to declassify from + // the current blocking level all the way down to the target pc + + const levFrom = this.bl; + const levTo = pc; + + debug(`Level to declassify to at pinipop ${levTo.stringRep()}`); + // check that the provided authority is sufficient for the declassification + this._validateDowngradeOrThrow({ + levFrom, + levTo, + authorityLevel: auth.val.authorityLevel, + downgradeKind: DowngradeKind.BLOCKING, + downgradeDimension: DowngradeDimension.CONFIDENTIALITY, + blockLevel: this.bl, + operationDescription: "pini declassification", + }); + + this.pc = pc; + this.bl = bl; + let loop_sp = this._sp; + let j = loop_sp - PCOFFSET; + while (j >= 0 && !levels.flowsTo(this.callStack[j], pc)) { + this.callStack[j] = pc; + loop_sp = this.callStack[loop_sp - SPOFFSET]; + j = loop_sp - PCOFFSET; + } + this.pini_uuid = cap.prev; + + return this.returnImmediateLValue(__unit); + } - - // We declassify the current blocking level to the old blocking level. - // and also the current pc to the old pc. - // We check that there is sufficient authority to declassify from - // the current blocking level all the way down to the target pc - - let levFrom = this.bl; - let levTo = pc - - - debug (`Level to declassify to at pinipop ${levTo.stringRep()}`) - // check that the provided authority is sufficient for the declassification - this._validateDowngradeOrThrow({ - levFrom, - levTo, - authorityLevel: auth.val.authorityLevel, - downgradeKind: DowngradeKind.BLOCKING, - downgradeDimension: DowngradeDimension.CONFIDENTIALITY, - blockLevel: this.bl, - operationDescription: "pini declassification" - }); - - this.pc = pc; - this.bl = bl; - let loop_sp = this._sp - let j = loop_sp - PCOFFSET; - while (j >= 0 && !levels.flowsTo (this.callStack[j], pc)) { - this.callStack[j] = pc; - loop_sp = this.callStack[loop_sp - SPOFFSET] - j = loop_sp - PCOFFSET - } - this.pini_uuid = cap.prev; - - return this.returnImmediateLValue (__unit); + pinipop(cap_lval) { + if (this.pini_uuid == null) { + this.threadError("unmatched pinipop"); } - - - pinipop (cap_lval) { - if (this.pini_uuid == null) { - this.threadError ("unmatched pinipop"); - } + debug(`Current pc level is ${this.pc.stringRep()}`); - debug (`Current pc level is ${this.pc.stringRep()}`) + this.raiseBlockingThreadLev(this.pc); // maintaining the invariant that the blocking level is as high as the pc level - this.raiseBlockingThreadLev(this.pc); // maintaining the invariant that the blocking level is as high as the pc level - - let cap: Capability = cap_lval.val; - let {bl, pc, auth, purpose} = cap.data; - - - if (this.pini_uuid != cap.uid || purpose != PCDeclassificationPurpose.Pini) { - this.threadError ("Ill-scoped pinipush/pinipop"); - return; // does not schedule anything in this thread - // effectively terminating the thread - } + const cap: Capability = cap_lval.val; + const { bl, pc, auth, purpose } = cap.data; - // If we are here then the pinipop is well-scoped - // so we check the declassifications now - - let levFrom = this.bl; - let levTo = bl; - - debug (`Level to declassify to at pinipop ${levTo.stringRep()}`) - // this.showStack() - // check that the provided authority is sufficient to perform declassification to the next level - this._validateDowngradeOrThrow({ - levFrom, - levTo, - authorityLevel: auth.val.authorityLevel, - downgradeKind: DowngradeKind.BLOCKING, - downgradeDimension: DowngradeDimension.CONFIDENTIALITY, - operationDescription: "pini declassification" - }); - - // Logic from former onSuccess callback - this.bl = levTo ; - this.pini_uuid = cap.prev; - - return this.returnImmediateLValue (__unit); + if ( + this.pini_uuid != cap.uid || + purpose != PCDeclassificationPurpose.Pini + ) { + this.threadError("Ill-scoped pinipush/pinipop"); + return; // does not schedule anything in this thread + // effectively terminating the thread } - blockEndorseTo (auth, bl_to = this.pc) { - // 2025-05-30; AA - // These are copy paste from declassify - // we should recheck - if (! flowsTo (this.pc, bl_to)) { - this.threadError ("The provided target blocking level is lower than the current pc\n" + - ` | the current pc: ${this.pc.stringRep()}\n` + - ` | target blocking level: ${bl_to.stringRep()}`) - } - + // If we are here then the pinipop is well-scoped + // so we check the declassifications now - let ok_to_use = levels.flowsTo (auth.lev, bl_to); - if (!ok_to_use) { - this.threadError ("The provided authority value is tainted\n" + - ` | the level of the authority value: ${auth.lev.stringRep()}\n` + - ` | target blocking level: ${bl_to.stringRep()}`) - } - - const current_bl = this.bl; // Capture this.bl as it's effectively levFrom - - this._validateDowngradeOrThrow({ - levFrom: current_bl, - levTo: bl_to, - authorityLevel: auth.val.authorityLevel, - downgradeKind: DowngradeKind.BLOCKING, - downgradeDimension: DowngradeDimension.INTEGRITY, - blockLevel: current_bl, - operationDescription: "blocking level integrity" - }); - - this.bl = bl_to; // the actual downgrade - return this.returnImmediateLValue (__unit); + const levFrom = this.bl; + const levTo = bl; - } + debug(`Level to declassify to at pinipop ${levTo.stringRep()}`); + // this.showStack() + // check that the provided authority is sufficient to perform declassification to the next level + this._validateDowngradeOrThrow({ + levFrom, + levTo, + authorityLevel: auth.val.authorityLevel, + downgradeKind: DowngradeKind.BLOCKING, + downgradeDimension: DowngradeDimension.CONFIDENTIALITY, + operationDescription: "pini declassification", + }); + // Logic from former onSuccess callback + this.bl = levTo; + this.pini_uuid = cap.prev; - blockDeclassifyTo (auth, bl_to = this.pc) { - if (! flowsTo (this.pc, bl_to)) { - this.threadError ("The provided target blocking level is lower than the current pc\n" + - ` | the current pc: ${this.pc.stringRep()}\n` + - ` | target blocking level: ${bl_to.stringRep()}`) - } - - - let ok_to_use = levels.flowsTo (auth.lev, bl_to); - if (!ok_to_use) { - this.threadError ("The provided authority value is tainted\n" + - ` | the level of the authority value: ${auth.lev.stringRep()}\n` + - ` | target blocking level: ${bl_to.stringRep()}`) - } - - const current_bl = this.bl; // Capture this.bl as it's effectively levFrom - - this._validateDowngradeOrThrow({ - levFrom: current_bl, - levTo: bl_to, - authorityLevel: auth.val.authorityLevel, - downgradeKind: DowngradeKind.BLOCKING, - downgradeDimension: DowngradeDimension.CONFIDENTIALITY, - blockLevel: current_bl, - operationDescription: "blocking level declassification" - }); - - this.bl = bl_to; // the actual downgrade - return this.returnImmediateLValue (__unit); - } + return this.returnImmediateLValue(__unit); + } - raiseBlockingThreadLev (l) { - this.bl = lub (this.bl, l) - } + blockEndorseTo(auth, bl_to = this.pc) { + // 2025-05-30; AA + // These are copy paste from declassify + // we should recheck + if (!flowsTo(this.pc, bl_to)) { + this.threadError( + "The provided target blocking level is lower than the current pc\n" + + ` | the current pc: ${this.pc.stringRep()}\n` + + ` | target blocking level: ${bl_to.stringRep()}`, + ); + } + + const ok_to_use = levels.flowsTo(auth.lev, bl_to); + if (!ok_to_use) { + this.threadError( + "The provided authority value is tainted\n" + + ` | the level of the authority value: ${auth.lev.stringRep()}\n` + + ` | target blocking level: ${bl_to.stringRep()}`, + ); + } + + const current_bl = this.bl; // Capture this.bl as it's effectively levFrom + + this._validateDowngradeOrThrow({ + levFrom: current_bl, + levTo: bl_to, + authorityLevel: auth.val.authorityLevel, + downgradeKind: DowngradeKind.BLOCKING, + downgradeDimension: DowngradeDimension.INTEGRITY, + blockLevel: current_bl, + operationDescription: "blocking level integrity", + }); + + this.bl = bl_to; // the actual downgrade + return this.returnImmediateLValue(__unit); + } - raiseCurrentThreadPCToBlockingLev () { - this.pc = lub(this.pc, this.bl ) ; - } + blockDeclassifyTo(auth, bl_to = this.pc) { + if (!flowsTo(this.pc, bl_to)) { + this.threadError( + "The provided target blocking level is lower than the current pc\n" + + ` | the current pc: ${this.pc.stringRep()}\n` + + ` | target blocking level: ${bl_to.stringRep()}`, + ); + } + + const ok_to_use = levels.flowsTo(auth.lev, bl_to); + if (!ok_to_use) { + this.threadError( + "The provided authority value is tainted\n" + + ` | the level of the authority value: ${auth.lev.stringRep()}\n` + + ` | target blocking level: ${bl_to.stringRep()}`, + ); + } + + const current_bl = this.bl; // Capture this.bl as it's effectively levFrom + + this._validateDowngradeOrThrow({ + levFrom: current_bl, + levTo: bl_to, + authorityLevel: auth.val.authorityLevel, + downgradeKind: DowngradeKind.BLOCKING, + downgradeDimension: DowngradeDimension.CONFIDENTIALITY, + blockLevel: current_bl, + operationDescription: "blocking level declassification", + }); + + this.bl = bl_to; // the actual downgrade + return this.returnImmediateLValue(__unit); + } - raiseCurrentThreadPC (l) { - this.pc = lub( this.pc, l ) - this.raiseBlockingThreadLev(this.pc); - // 2018-11-29: AA; observe that we are raise the blocking level - // automaticaly every time we raise the PC level. - } + raiseBlockingThreadLev(l) { + this.bl = lub(this.bl, l); + } + raiseCurrentThreadPCToBlockingLev() { + this.pc = lub(this.pc, this.bl); + } + raiseCurrentThreadPC(l) { + this.pc = lub(this.pc, l); + this.raiseBlockingThreadLev(this.pc); + // 2018-11-29: AA; observe that we are raise the blocking level + // automaticaly every time we raise the PC level. + } - mkVal(x) { - return new LVal(x, this.pc, this.pc ); - } + mkVal(x) { + return new LVal(x, this.pc, this.pc); + } - mkValPos(x: any, pos: string) { - return new LVal (x, this.pc, this.pc, pos); - } + mkValPos(x: any, pos: string) { + return new LVal(x, this.pc, this.pc, pos); + } - /* + /* mkValWithTroupeType(x, t) { return new LVal (x, this.pc, this.pc, null, t) } */ - mkValWithLev(x:any, l:any) { - return new LVal ( x - , lub(this.pc, l) - , this.pc ) - } - - mkCopy (x) { - return new LValCopyAt (x, this.pc); - // return new LVal(x.val, lub(x.lev, this.pc), lub (x.tlev, this.pc) ) - } + mkValWithLev(x: any, l: any) { + return new LVal(x, lub(this.pc, l), this.pc); + } - - printPc () { - console.log ("PC:", this.pc.stringRep()); - console.log ("BL:", this.bl.stringRep()); - } + mkCopy(x) { + return new LValCopyAt(x, this.pc); + // return new LVal(x.val, lub(x.lev, this.pc), lub (x.tlev, this.pc) ) + } + printPc() { + console.log("PC:", this.pc.stringRep()); + console.log("BL:", this.bl.stringRep()); + } - tidErrorStringRep() { - if (this.processDebuggingName) { - return ("[" + this.processDebuggingName + "]" + this.tid.stringRep() ) - } - else { - return this.tid.stringRep() - } + tidErrorStringRep() { + if (this.processDebuggingName) { + return "[" + this.processDebuggingName + "]" + this.tid.stringRep(); + } else { + return this.tid.stringRep(); } + } - - threadError (s:string, internal = false) { - if ( this.handlerState.isNormal()) { - if (internal) { - throw new ImplementationError(s) - } - else { - throw new StrThreadError(this, s); - } - } else { - this.raiseCurrentThreadPC(this.handlerState.lev); - throw new HandlerError (this, s) // "HandlerError" - } - } - - - addMessage (message) { - this.mailbox.newMessage (message); + threadError(s: string, internal = false) { + if (this.handlerState.isNormal()) { + if (internal) { + throw new ImplementationError(s); + } else { + throw new StrThreadError(this, s); + } + } else { + this.raiseCurrentThreadPC(this.handlerState.lev); + throw new HandlerError(this, s); // "HandlerError" } + } - raiseMboxClearance (new_lclear: any) { - /* + addMessage(message) { + this.mailbox.newMessage(message); + } + + raiseMboxClearance(new_lclear: any) { + /* if (!flowsTo(this.pc, this.mailbox.lclear)) { - this.threadError( `Cannot raise mailbox clearance level in a high context\n` + + this.threadError( `Cannot raise mailbox clearance level in a high context\n` + `| current thread's pc level: ${this.pc.stringRep()}\n` + `| current mailbox clearance level: ${this.mailbox.lclear.stringRep()}`) return; } */ - let uid = uuidv4() ; - let cap = this.mkVal (new Capability(uid, this.mailbox.mclear, this.mailbox.caps, this.pc)) - this.mailbox.caps = uid; - this.mailbox.mclear = new MboxClearance(lub (new_lclear.val, this.mailbox.mclear.boost_level), this.pc); + const uid = uuidv4(); + const cap = this.mkVal( + new Capability(uid, this.mailbox.mclear, this.mailbox.caps, this.pc), + ); + this.mailbox.caps = uid; + this.mailbox.mclear = new MboxClearance( + lub(new_lclear.val, this.mailbox.mclear.boost_level), + this.pc, + ); + + // this.returnSuspended( cap ); + // this.sched.stepThread(); + return this.returnImmediateLValue(cap); + } - // this.returnSuspended( cap ); - // this.sched.stepThread(); - return this.returnImmediateLValue(cap) + lowerMboxClearance(cap_lval: any, auth: any) { + if (this.mailbox.caps == null) { + this.threadError("unmatched lowering of mailbox clearance"); + return null; // threadError throws } - lowerMboxClearance (cap_lval:any, auth:any) { - if (this.mailbox.caps == null ) { - this.threadError ("unmatched lowering of mailbox clearance") - return null; // threadError throws - } - - let cap:Capability = cap_lval.val - - if (this.mailbox.caps != cap.uid ) { - this.threadError ("Ill-scoped raise/lower of mailbox clearance:\n" + - `expected cap: ${this.mailbox.caps}\n` + - `provided cap: ${cap.uid}`) - return null; // threadError throws - } - + const cap: Capability = cap_lval.val; - // since we are going to update the level of the current mailbox label - // we have to check that we do not affect it in a high context - // note: the intuition here follows the principle of non-sensitive upgrade - // 2020-02-12:AA + if (this.mailbox.caps != cap.uid) { + this.threadError( + "Ill-scoped raise/lower of mailbox clearance:\n" + + `expected cap: ${this.mailbox.caps}\n` + + `provided cap: ${cap.uid}`, + ); + return null; // threadError throws + } - if (!levels.flowsTo (this.pc , this.mailbox.mclear.pc_at_creation)) { - this.threadError ("Cannot lower mailbox when the pc more sensitive than the mailbox clearance level\n" + - `| current thread's pc level: ${this.pc.stringRep()}\n` + - `| mailbox clearance level: ${this.mailbox.mclear.pc_at_creation.stringRep()}`) - - } + // since we are going to update the level of the current mailbox label + // we have to check that we do not affect it in a high context + // note: the intuition here follows the principle of non-sensitive upgrade + // 2020-02-12:AA - const currentMboxBoostLevel = this.mailbox.mclear.boost_level; - const targetMboxBoostLevel = cap.data.boost_level; - - this._validateDowngradeOrThrow({ - levFrom: currentMboxBoostLevel, - levTo: targetMboxBoostLevel, - authorityLevel: auth.val.authorityLevel, - downgradeKind: DowngradeKind.MAILBOX, - downgradeDimension: DowngradeDimension.CONFIDENTIALITY, - blockLevel: this.bl - }); - - this.mailbox.mclear = cap.data; // restoring the clearance level - this.mailbox.caps = cap.prev; - - return this.returnImmediateLValue(__unit); + if (!levels.flowsTo(this.pc, this.mailbox.mclear.pc_at_creation)) { + this.threadError( + "Cannot lower mailbox when the pc more sensitive than the mailbox clearance level\n" + + `| current thread's pc level: ${this.pc.stringRep()}\n` + + `| mailbox clearance level: ${this.mailbox.mclear.pc_at_creation.stringRep()}`, + ); } -} + const currentMboxBoostLevel = this.mailbox.mclear.boost_level; + const targetMboxBoostLevel = cap.data.boost_level; + + this._validateDowngradeOrThrow({ + levFrom: currentMboxBoostLevel, + levTo: targetMboxBoostLevel, + authorityLevel: auth.val.authorityLevel, + downgradeKind: DowngradeKind.MAILBOX, + downgradeDimension: DowngradeDimension.CONFIDENTIALITY, + blockLevel: this.bl, + }); + + this.mailbox.mclear = cap.data; // restoring the clearance level + this.mailbox.caps = cap.prev; + + return this.returnImmediateLValue(__unit); + } +} diff --git a/rt/src/TroupeCliArgs.mts b/rt/src/TroupeCliArgs.mts index c8eb4ca2..5ef79940 100644 --- a/rt/src/TroupeCliArgs.mts +++ b/rt/src/TroupeCliArgs.mts @@ -1,86 +1,151 @@ -import yargs from 'yargs'; -import { hideBin } from 'yargs/helpers'; +import yargs from "yargs"; +import { hideBin } from "yargs/helpers"; export enum TroupeCliArg { - Debug = 'debug', - DebugSandbox = 'debugsandbox', - DebugMailbox = 'debugmailbox', - DebugP2p = 'debugp2p', - Pini = 'pini', - ShowStack = 'showStack', - Trustmap = 'trustmap', - Id = 'id', - LocalOnly = 'localonly', - Persist = 'persist', - Aliases = 'aliases', - Stdiolev = 'stdiolev', - Port = 'port', - File = 'file', - RSpawn = 'rspawn', - Relay = 'relay', - NoColor = 'no-color', + Debug = "debug", + DebugSandbox = "debugsandbox", + DebugMailbox = "debugmailbox", + DebugP2p = "debugp2p", + Pini = "pini", + ShowStack = "showStack", + Trustmap = "trustmap", + Id = "id", + LocalOnly = "localonly", + Persist = "persist", + Aliases = "aliases", + Stdiolev = "stdiolev", + Port = "port", + File = "file", + RSpawn = "rspawn", + Relay = "relay", + NoColor = "no-color", } export interface ParsedArgs { - [TroupeCliArg.Debug]?: boolean; - [TroupeCliArg.DebugSandbox]?: boolean; - [TroupeCliArg.DebugMailbox]?: boolean; - [TroupeCliArg.DebugP2p]?: boolean; - [TroupeCliArg.Pini]?: boolean; - [TroupeCliArg.ShowStack]?: boolean; - [TroupeCliArg.Trustmap]?: string; - [TroupeCliArg.Id]?: string; - [TroupeCliArg.LocalOnly]?: boolean; - [TroupeCliArg.Persist]?: boolean; - [TroupeCliArg.Aliases]?: string; - [TroupeCliArg.Stdiolev]?: string; - [TroupeCliArg.Port]?: number; - [TroupeCliArg.File]?: string; - [TroupeCliArg.RSpawn]?: boolean; - [TroupeCliArg.Relay]?: string | string[]; - [TroupeCliArg.NoColor]?: boolean; - [key: string]: any; + [TroupeCliArg.Debug]?: boolean; + [TroupeCliArg.DebugSandbox]?: boolean; + [TroupeCliArg.DebugMailbox]?: boolean; + [TroupeCliArg.DebugP2p]?: boolean; + [TroupeCliArg.Pini]?: boolean; + [TroupeCliArg.ShowStack]?: boolean; + [TroupeCliArg.Trustmap]?: string; + [TroupeCliArg.Id]?: string; + [TroupeCliArg.LocalOnly]?: boolean; + [TroupeCliArg.Persist]?: boolean; + [TroupeCliArg.Aliases]?: string; + [TroupeCliArg.Stdiolev]?: string; + [TroupeCliArg.Port]?: number; + [TroupeCliArg.File]?: string; + [TroupeCliArg.RSpawn]?: boolean; + [TroupeCliArg.Relay]?: string | string[]; + [TroupeCliArg.NoColor]?: boolean; + [key: string]: any; } let parsedArgs: ParsedArgs | null = null; export function getCliArgs(): ParsedArgs { - if (!parsedArgs) { - const rawArgs = yargs(hideBin(process.argv)) - .option(TroupeCliArg.Debug, { alias: 'd', type: 'boolean', default: false, describe: 'Enable general debug logging' }) - .option(TroupeCliArg.DebugSandbox, { type: 'boolean', default: false, describe: 'Enable debug logging for sandbox operations' }) - .option(TroupeCliArg.DebugMailbox, { type: 'boolean', default: false, describe: 'Enable debug logging for mailbox processing' }) - .option(TroupeCliArg.DebugP2p, { type: 'boolean', default: false, describe: 'Enable debug logging for P2P communication' }) - .option(TroupeCliArg.Pini, { type: 'boolean', default: false, describe: 'Enable Pini mode for declassification' }) - .option(TroupeCliArg.ShowStack, { alias: 'ss', type: 'boolean', default: false, describe: 'Show stack traces on errors' }) - .option(TroupeCliArg.Trustmap, { alias: 'tm', type: 'string', describe: 'Path to the trustmap JSON file' }) - .option(TroupeCliArg.Id, { alias: 'i', type: 'string', describe: 'Path to the node ID file' }) - .option(TroupeCliArg.LocalOnly, { alias: 'l', type: 'boolean', default: false, describe: 'Run in local-only mode, skipping network creation' }) - .option(TroupeCliArg.Persist, { alias: 'P', type: 'boolean', default: false, describe: 'Enable persistence mode' }) - .option(TroupeCliArg.Aliases, { alias: 'a', type: 'string', describe: 'Path to the aliases JSON file' }) - .option(TroupeCliArg.Stdiolev, { type: 'string', describe: 'Security level for stdio operations' }) - .option(TroupeCliArg.Port, { type: 'number', describe: 'Network port for P2P communication' }) - .option(TroupeCliArg.File, { alias: 'f', type: 'string', describe: 'Path to the main troupe program file to execute' }) - .option(TroupeCliArg.RSpawn, { type: 'boolean', default: false, describe: 'Allow remote spawning of troupe processes' }) - .option(TroupeCliArg.Relay, { type: 'array', describe: 'Relay server multiaddress(es) for P2P connectivity' }) - .option(TroupeCliArg.NoColor, { - type: 'boolean', - default: false, - describe: 'Disable colored output (also respects NO_COLOR env var)', - coerce: (arg) => { - // Handle the case where yargs interprets --no-color as negation - // When --no-color is passed, arg will be false (negation of color) - // We want to return true when --no-color is present - return process.argv.includes('--no-color'); - } - }) - .parseSync(); + if (!parsedArgs) { + const rawArgs = yargs(hideBin(process.argv)) + .option(TroupeCliArg.Debug, { + alias: "d", + type: "boolean", + default: false, + describe: "Enable general debug logging", + }) + .option(TroupeCliArg.DebugSandbox, { + type: "boolean", + default: false, + describe: "Enable debug logging for sandbox operations", + }) + .option(TroupeCliArg.DebugMailbox, { + type: "boolean", + default: false, + describe: "Enable debug logging for mailbox processing", + }) + .option(TroupeCliArg.DebugP2p, { + type: "boolean", + default: false, + describe: "Enable debug logging for P2P communication", + }) + .option(TroupeCliArg.Pini, { + type: "boolean", + default: false, + describe: "Enable Pini mode for declassification", + }) + .option(TroupeCliArg.ShowStack, { + alias: "ss", + type: "boolean", + default: false, + describe: "Show stack traces on errors", + }) + .option(TroupeCliArg.Trustmap, { + alias: "tm", + type: "string", + describe: "Path to the trustmap JSON file", + }) + .option(TroupeCliArg.Id, { + alias: "i", + type: "string", + describe: "Path to the node ID file", + }) + .option(TroupeCliArg.LocalOnly, { + alias: "l", + type: "boolean", + default: false, + describe: "Run in local-only mode, skipping network creation", + }) + .option(TroupeCliArg.Persist, { + alias: "P", + type: "boolean", + default: false, + describe: "Enable persistence mode", + }) + .option(TroupeCliArg.Aliases, { + alias: "a", + type: "string", + describe: "Path to the aliases JSON file", + }) + .option(TroupeCliArg.Stdiolev, { + type: "string", + describe: "Security level for stdio operations", + }) + .option(TroupeCliArg.Port, { + type: "number", + describe: "Network port for P2P communication", + }) + .option(TroupeCliArg.File, { + alias: "f", + type: "string", + describe: "Path to the main troupe program file to execute", + }) + .option(TroupeCliArg.RSpawn, { + type: "boolean", + default: false, + describe: "Allow remote spawning of troupe processes", + }) + .option(TroupeCliArg.Relay, { + type: "array", + describe: "Relay server multiaddress(es) for P2P connectivity", + }) + .option(TroupeCliArg.NoColor, { + type: "boolean", + default: false, + describe: "Disable colored output (also respects NO_COLOR env var)", + coerce: (arg) => { + // Handle the case where yargs interprets --no-color as negation + // When --no-color is passed, arg will be false (negation of color) + // We want to return true when --no-color is present + return process.argv.includes("--no-color"); + }, + }) + .parseSync(); - if (rawArgs.f && !rawArgs.file) { - rawArgs.file = String(rawArgs.f); - } - - parsedArgs = rawArgs as ParsedArgs; + if (rawArgs.f && !rawArgs.file) { + rawArgs.file = String(rawArgs.f); } - return parsedArgs; -} \ No newline at end of file + + parsedArgs = rawArgs as ParsedArgs; + } + return parsedArgs; +} diff --git a/rt/src/TroupeError.mts b/rt/src/TroupeError.mts index e53ec3e9..68a80d05 100644 --- a/rt/src/TroupeError.mts +++ b/rt/src/TroupeError.mts @@ -1,65 +1,76 @@ import { Thread } from "./Thread.mjs"; // import colors = require('colors/safe'); -import chalk from 'chalk' +import chalk from "chalk"; import { SchedulerInterface } from "./SchedulerInterface.mjs"; -import { configureColors } from './colorConfig.mjs'; +import { configureColors } from "./colorConfig.mjs"; // Ensure colors are configured when this module is loaded configureColors(); export abstract class TroupeError extends Error { - abstract handleError (sched: SchedulerInterface) : void + abstract handleError(sched: SchedulerInterface): void; } export abstract class ThreadError extends TroupeError { - abstract errorMessage: string - thread: Thread - constructor (thread:Thread) { - super () - this.thread = thread; - } + abstract errorMessage: string; + thread: Thread; + constructor(thread: Thread) { + super(); + this.thread = thread; + } } -export abstract class StopThreadError extends ThreadError { - handleError (sched) { - let console = this.thread.rtObj.xconsole - console.log (chalk.red ( "Runtime error in thread " + this.thread.tidErrorStringRep())) - console.log (chalk.red ( ">> " + this.errorMessage)); - sched.stopThreadWithErrorMessage(this.thread, this.errorMessage); - } +export abstract class StopThreadError extends ThreadError { + handleError(sched) { + const console = this.thread.rtObj.xconsole; + console.log( + chalk.red("Runtime error in thread " + this.thread.tidErrorStringRep()), + ); + console.log(chalk.red(">> " + this.errorMessage)); + sched.stopThreadWithErrorMessage(this.thread, this.errorMessage); + } } export class StrThreadError extends StopThreadError { - errstr: string; - get errorMessage () { return this.errstr } - constructor (thread:Thread, errstr:string ) { - super (thread) ; - this.errstr = errstr; - } + errstr: string; + get errorMessage() { + return this.errstr; + } + constructor(thread: Thread, errstr: string) { + super(thread); + this.errstr = errstr; + } } export class HandlerError extends ThreadError { - constructor (thread: Thread, errstr: string) { - super (thread); - this.errstr = errstr; - } - errstr: string - get errorMessage () { return this.errstr } - handleError( sched:SchedulerInterface ) { - // we have an error inside of an receive pattern or guard; - // we are discarding the rest of the current thread and are - // scheduling the execution of the handler - let console = this.thread.rtObj.xconsole - console.log (chalk.yellow (`Warning: runtime exception in the handler or sandbox: ${this.errstr}`)) - this.thread.next = this.thread.handlerState.getTrapper(); - sched.scheduleThread(this.thread) - } + constructor(thread: Thread, errstr: string) { + super(thread); + this.errstr = errstr; + } + errstr: string; + get errorMessage() { + return this.errstr; + } + handleError(sched: SchedulerInterface) { + // we have an error inside of an receive pattern or guard; + // we are discarding the rest of the current thread and are + // scheduling the execution of the handler + const console = this.thread.rtObj.xconsole; + console.log( + chalk.yellow( + `Warning: runtime exception in the handler or sandbox: ${this.errstr}`, + ), + ); + this.thread.next = this.thread.handlerState.getTrapper(); + sched.scheduleThread(this.thread); + } } -export class ImplementationError extends Error { // observe that this does not inherit from TroupeError - errstr :string - constructor (s: string) { - super () - this.errstr = s - } -} \ No newline at end of file +export class ImplementationError extends Error { + // observe that this does not inherit from TroupeError + errstr: string; + constructor(s: string) { + super(); + this.errstr = s; + } +} diff --git a/rt/src/TroupeRawValue.mts b/rt/src/TroupeRawValue.mts index 78d5e0d3..5212f9aa 100644 --- a/rt/src/TroupeRawValue.mts +++ b/rt/src/TroupeRawValue.mts @@ -1,12 +1,12 @@ -import {TroupeType} from './TroupeTypes.mjs' -import { Level } from './Level.mjs' +import { TroupeType } from "./TroupeTypes.mjs"; +import { Level } from "./Level.mjs"; export interface TroupeRawValue { - _troupeType: TroupeType; - dataLevel: Level ; - stringRep (omitLevels?: boolean, taintRef?: any): string; + _troupeType: TroupeType; + dataLevel: Level; + stringRep(omitLevels?: boolean, taintRef?: any): string; } export interface TroupeAggregateRawValue extends TroupeRawValue { - dataLevel: Level -} \ No newline at end of file + dataLevel: Level; +} diff --git a/rt/src/TroupeTypes.mts b/rt/src/TroupeTypes.mts index a0fe1fa9..4a1df4ba 100644 --- a/rt/src/TroupeTypes.mts +++ b/rt/src/TroupeTypes.mts @@ -1,63 +1,69 @@ export const enum TroupeType { - UNIT=0, - BOOLEAN=1, - NUMBER=2, - STRING=3, - PROCESS_ID=4, - LEVEL=5, - AUTHORITY=6, - CAPABILITY=7, - ATOM=8, - /* up until this point only base types */ + UNIT = 0, + BOOLEAN = 1, + NUMBER = 2, + STRING = 3, + PROCESS_ID = 4, + LEVEL = 5, + AUTHORITY = 6, + CAPABILITY = 7, + ATOM = 8, + /* up until this point only base types */ /* aggregate types */ - CLOSURE=100, - LVAL=101, // TODO: AA; 2020-03-03 ; this should be only used for transports; - TUPLE=102, - LIST=103, - RECORD=104, + CLOSURE = 100, + LVAL = 101, // TODO: AA; 2020-03-03 ; this should be only used for transports; + TUPLE = 102, + LIST = 103, + RECORD = 104, /* meaningless to serialize */ - LOCALOBJECT=200 + LOCALOBJECT = 200, } -export const enum ClosureType { +export const enum ClosureType { /* okay to serialize */ - REGULARFN = 0, + REGULARFN = 0, /* meaningless to serialize */ - BUILTINFN = 1, - SANDBOXKONT = 2 , - SERVICEFN = 3 + BUILTINFN = 1, + SANDBOXKONT = 2, + SERVICEFN = 3, } export function isLVal(x) { - return (typeof x.val != "undefined" && - typeof x.lev != "undefined" && - typeof x.tlev != "undefined" ); + return ( + typeof x.val != "undefined" && + typeof x.lev != "undefined" && + typeof x.tlev != "undefined" + ); } -export function isSerializableClosure (ct) { - return (ct == ClosureType.REGULARFN); +export function isSerializableClosure(ct) { + return ct == ClosureType.REGULARFN; } -export function getTypeForBasicValue (x:any) { - switch (typeof(x)) { - case 'number': - return TroupeType.NUMBER - case 'boolean': - return TroupeType.BOOLEAN - case 'string': - return TroupeType.STRING - } - throw new Error (`Cannot identify troupe type for value ${JSON.stringify(x)} of type ${typeof x}`); +export function getTypeForBasicValue(x: any) { + switch (typeof x) { + case "number": + return TroupeType.NUMBER; + case "boolean": + return TroupeType.BOOLEAN; + case "string": + return TroupeType.STRING; + } + throw new Error( + `Cannot identify troupe type for value ${JSON.stringify(x)} of type ${typeof x}`, + ); } -export function getTroupeType (x:any) { - if (x._troupeType != undefined) { +export function getTroupeType(x: any) { + if (x._troupeType != undefined) { return x._troupeType; } - throw new Error (`Cannot identify troupe type for value ${x.toString()} of type ${typeof x}`); + throw new Error( + `Cannot identify troupe type for value ${x.toString()} of type ${typeof x}`, + ); } /* @@ -68,4 +74,4 @@ export function isBaseType (t:TroupeType) { export function isAggregate(t:TroupeType) { return t >= TroupeType.CLOSURE } -*/ \ No newline at end of file +*/ diff --git a/rt/src/TrustManager.mts b/rt/src/TrustManager.mts index a565e064..159dd799 100644 --- a/rt/src/TrustManager.mts +++ b/rt/src/TrustManager.mts @@ -1,53 +1,48 @@ -import * as levels from './Level.mjs'; +import * as levels from "./Level.mjs"; import { getCliArgs, TroupeCliArg } from "./TroupeCliArgs.mjs"; -import * as fs from 'node:fs'; +import * as fs from "node:fs"; import { Level } from "./Level.mjs"; import { __nodeManager } from "./NodeManager.mjs"; -const { readFile } = fs.promises - +const { readFile } = fs.promises; const argv = getCliArgs(); -let logLevel = argv[TroupeCliArg.Debug] ? 'debug' : 'info'; -import { mkLogger } from './logger.mjs' -const logger = mkLogger('RTM', logLevel); - +const logLevel = argv[TroupeCliArg.Debug] ? "debug" : "info"; +import { mkLogger } from "./logger.mjs"; +const logger = mkLogger("RTM", logLevel); -export let _trustMap = {} +export let _trustMap = {}; async function loadTrustMap(trustMapFile) { - try { - let s = await readFile(trustMapFile, 'utf-8'); - let trustList = JSON.parse(s); - let trustMap = {} - trustList.map(x => trustMap[x.id] = levels.mkLevel(x.level)); - _trustMap = trustMap; - } catch (err) { - logger.error("cannot load trust map file: " + err); - } + try { + const s = await readFile(trustMapFile, "utf-8"); + const trustList = JSON.parse(s); + const trustMap = {}; + trustList.map((x) => (trustMap[x.id] = levels.mkLevel(x.level))); + _trustMap = trustMap; + } catch (err) { + logger.error("cannot load trust map file: " + err); + } } - export async function initTrustMap() { - if (argv[TroupeCliArg.Trustmap]) { - await loadTrustMap(argv[TroupeCliArg.Trustmap]); - } else { - let default_trustmap = "trustmap.json" - if (fs.existsSync(default_trustmap)) { - await loadTrustMap(default_trustmap) - } + if (argv[TroupeCliArg.Trustmap]) { + await loadTrustMap(argv[TroupeCliArg.Trustmap]); + } else { + const default_trustmap = "trustmap.json"; + if (fs.existsSync(default_trustmap)) { + await loadTrustMap(default_trustmap); } - + } } - -export function nodeTrustLevel(nodeid):Level { - if (__nodeManager.isLocalNode(nodeid)) { - return levels.ROOT - } - if (_trustMap) { - // console.log ("true"); - return _trustMap[nodeid] ? _trustMap[nodeid] : levels.BOT; - } - return levels.BOT; -} \ No newline at end of file +export function nodeTrustLevel(nodeid): Level { + if (__nodeManager.isLocalNode(nodeid)) { + return levels.ROOT; + } + if (_trustMap) { + // console.log ("true"); + return _trustMap[nodeid] ? _trustMap[nodeid] : levels.BOT; + } + return levels.BOT; +} diff --git a/rt/src/UnitBase.mts b/rt/src/UnitBase.mts index fe001a65..a826cd4b 100644 --- a/rt/src/UnitBase.mts +++ b/rt/src/UnitBase.mts @@ -1,8 +1,8 @@ -import * as levels from './Level.mjs' +import * as levels from "./Level.mjs"; - -export let __unitbase = { stringRep: () => "()" - , _is_unit : true - , _troupeType : 0 /* UNIT */ - , dataLevel : levels.BOT - } ; +export const __unitbase = { + stringRep: () => "()", + _is_unit: true, + _troupeType: 0 /* UNIT */, + dataLevel: levels.BOT, +}; diff --git a/rt/src/UnitVal.mts b/rt/src/UnitVal.mts index 8c21ecbe..ceb02f86 100644 --- a/rt/src/UnitVal.mts +++ b/rt/src/UnitVal.mts @@ -1,6 +1,5 @@ -import {__unitbase} from './UnitBase.mjs' -import * as levels from './Level.mjs'; -import { LVal } from './Lval.mjs'; - -export let __unit = new LVal (__unitbase, levels.BOT, levels.BOT) +import { __unitbase } from "./UnitBase.mjs"; +import * as levels from "./Level.mjs"; +import { LVal } from "./Lval.mjs"; +export const __unit = new LVal(__unitbase, levels.BOT, levels.BOT); diff --git a/rt/src/UserRuntime.mts b/rt/src/UserRuntime.mts index d5668b9e..1ceca4d4 100644 --- a/rt/src/UserRuntime.mts +++ b/rt/src/UserRuntime.mts @@ -1,68 +1,98 @@ -import { UserRuntimeZero } from './builtins/UserRuntimeZero.mjs' -import { BuiltinStdIo } from './builtins/stdio.mjs' -import { BuiltinMath } from './builtins/math.mjs' -import { BuiltinDebugUtils } from './builtins/debugutils.mjs' -import { BuiltinPini } from './builtins/pini.mjs' -import { BuiltinMonitors } from './builtins/monitor.mjs' -import { BuiltinSleep } from './builtins/sleep.mjs' -import { BuiltinLevOps } from './builtins/levelops.mjs' -import { BuiltinMboxClear } from './builtins/mboxclear.mjs' -import { BuiltinMkUuid } from './builtins/mkuuid.mjs' -import { BuiltinPersist } from './builtins/persist.mjs' -import { BuiltinNodeUtils } from './builtins/nodeutil.mjs' -import { BuiltinSelf } from './builtins/self.mjs' -import { BuiltinExit } from './builtins/exit.mjs' -import { BuiltinAdv } from './builtins/adv.mjs' -import { BuiltinGetTime } from './builtins/getTime.mjs' -import { BuiltinStringToInt } from './builtins/stringToInt.mjs' -import { BuiltinToString } from './builtins/toString.mjs' -import { BuiltinSend } from './builtins/send.mjs' -import { BuiltinSpawn } from './builtins/spawn.mjs' -import { BuiltinReceive } from './builtins/receive.mjs' -import { BuiltinAttenuate } from './builtins/attenuate.mjs' -import { BuiltinRegistry } from './builtins/whereis.mjs' -import { BuiltinDeclassify } from './builtins/declassify.mjs' -import { BuiltinRaiseTrust } from './builtins/raiseTrust.mjs' -import { BuiltinSandbox } from './builtins/sandbox.mjs' -import { BuiltinLocalArrays } from './builtins/localarrays.mjs' -import { RuntimeAssert } from './builtins/runtimeassert.mjs' -import { BuiltinService } from './builtins/service.mjs' -import { BuiltinString } from './builtins/string.mjs' -import { BuiltinRecordReflection } from './builtins/recordReflection.mjs' -import { BuiltinTypeInformation } from './builtins/types.mjs' -import { BuiltinListToTuple } from './builtins/listToTuple.mjs' +import { UserRuntimeZero } from "./builtins/UserRuntimeZero.mjs"; +import { BuiltinStdIo } from "./builtins/stdio.mjs"; +import { BuiltinMath } from "./builtins/math.mjs"; +import { BuiltinDebugUtils } from "./builtins/debugutils.mjs"; +import { BuiltinPini } from "./builtins/pini.mjs"; +import { BuiltinMonitors } from "./builtins/monitor.mjs"; +import { BuiltinSleep } from "./builtins/sleep.mjs"; +import { BuiltinLevOps } from "./builtins/levelops.mjs"; +import { BuiltinMboxClear } from "./builtins/mboxclear.mjs"; +import { BuiltinMkUuid } from "./builtins/mkuuid.mjs"; +import { BuiltinPersist } from "./builtins/persist.mjs"; +import { BuiltinNodeUtils } from "./builtins/nodeutil.mjs"; +import { BuiltinSelf } from "./builtins/self.mjs"; +import { BuiltinExit } from "./builtins/exit.mjs"; +import { BuiltinAdv } from "./builtins/adv.mjs"; +import { BuiltinGetTime } from "./builtins/getTime.mjs"; +import { BuiltinStringToInt } from "./builtins/stringToInt.mjs"; +import { BuiltinToString } from "./builtins/toString.mjs"; +import { BuiltinSend } from "./builtins/send.mjs"; +import { BuiltinSpawn } from "./builtins/spawn.mjs"; +import { BuiltinReceive } from "./builtins/receive.mjs"; +import { BuiltinAttenuate } from "./builtins/attenuate.mjs"; +import { BuiltinRegistry } from "./builtins/whereis.mjs"; +import { BuiltinDeclassify } from "./builtins/declassify.mjs"; +import { BuiltinRaiseTrust } from "./builtins/raiseTrust.mjs"; +import { BuiltinSandbox } from "./builtins/sandbox.mjs"; +import { BuiltinLocalArrays } from "./builtins/localarrays.mjs"; +import { RuntimeAssert } from "./builtins/runtimeassert.mjs"; +import { BuiltinService } from "./builtins/service.mjs"; +import { BuiltinString } from "./builtins/string.mjs"; +import { BuiltinRecordReflection } from "./builtins/recordReflection.mjs"; +import { BuiltinTypeInformation } from "./builtins/types.mjs"; +import { BuiltinListToTuple } from "./builtins/listToTuple.mjs"; -let BuiltSpawnSendReceive = x => BuiltinSpawn(BuiltinSend(BuiltinReceive(x))) +const BuiltSpawnSendReceive = (x) => + BuiltinSpawn(BuiltinSend(BuiltinReceive(x))); -export const UserRuntime = - BuiltinListToTuple ( - BuiltinString ( - BuiltinService ( - RuntimeAssert( - BuiltinLocalArrays( - BuiltinSandbox( - BuiltinRaiseTrust( - BuiltinDeclassify ( - BuiltinRegistry( - BuiltinAttenuate( - BuiltSpawnSendReceive( - BuiltinStringToInt( - BuiltinToString( - BuiltinGetTime( - BuiltinAdv( - BuiltinExit( - BuiltinSelf( - BuiltinNodeUtils( - BuiltinPersist( - BuiltinMkUuid( - BuiltinMboxClear( - BuiltinLevOps( - BuiltinSleep( - BuiltinMonitors( - BuiltinPini( - BuiltinDebugUtils( - BuiltinMath( - BuiltinRecordReflection( - BuiltinTypeInformation( - BuiltinStdIo(UserRuntimeZero) - ))))))))))))))))))))))))))))) +export const UserRuntime = BuiltinListToTuple( + BuiltinString( + BuiltinService( + RuntimeAssert( + BuiltinLocalArrays( + BuiltinSandbox( + BuiltinRaiseTrust( + BuiltinDeclassify( + BuiltinRegistry( + BuiltinAttenuate( + BuiltSpawnSendReceive( + BuiltinStringToInt( + BuiltinToString( + BuiltinGetTime( + BuiltinAdv( + BuiltinExit( + BuiltinSelf( + BuiltinNodeUtils( + BuiltinPersist( + BuiltinMkUuid( + BuiltinMboxClear( + BuiltinLevOps( + BuiltinSleep( + BuiltinMonitors( + BuiltinPini( + BuiltinDebugUtils( + BuiltinMath( + BuiltinRecordReflection( + BuiltinTypeInformation( + BuiltinStdIo( + UserRuntimeZero, + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), +); diff --git a/rt/src/ValuesUtil.mts b/rt/src/ValuesUtil.mts index 9fc5d0fc..292311b2 100644 --- a/rt/src/ValuesUtil.mts +++ b/rt/src/ValuesUtil.mts @@ -1,23 +1,22 @@ -import { LVal, listStringRep} from './Lval.mjs' -import { RawList } from './RawList.mjs' -import { RawTuple } from './RawTuple.mjs' +import { LVal, listStringRep } from "./Lval.mjs"; +import { RawList } from "./RawList.mjs"; +import { RawTuple } from "./RawTuple.mjs"; -export function isListFlagSet (x:any) { - return (x.isList == true ) +export function isListFlagSet(x: any) { + return x.isList == true; } -export function isTupleFlagSet (x:any) { - return (x.isTuple == true) +export function isTupleFlagSet(x: any) { + return x.isTuple == true; } /** * Takes an array of labelled values and makes a new Troupe tuple object out of it. */ export function mkTuple(x: LVal[]) { - return new RawTuple(x) + return new RawTuple(x); } - /** * Takes an array of labelled values and makes a new Troupe list object out of it. */ diff --git a/rt/src/_experiments/cnf_test.mts b/rt/src/_experiments/cnf_test.mts index 2e4b70a0..3a309dfb 100644 --- a/rt/src/_experiments/cnf_test.mts +++ b/rt/src/_experiments/cnf_test.mts @@ -1,31 +1,38 @@ -import {Category, CNF, CNF_FALSE, CNF_TRUE, implies} from '../levels/DCLabels/cnf.mjs' -import { Delimiterification } from '../levels/DCLabels/dcl_pp_config.mjs'; +import { + Category, + CNF, + CNF_FALSE, + CNF_TRUE, + implies, +} from "../levels/DCLabels/cnf.mjs"; +import { Delimiterification } from "../levels/DCLabels/dcl_pp_config.mjs"; -function test1 () { - let cat1 : Category = new Category (new Set (["Alice", "Bob"]) ) // Alice \/ Bob - let cat2 : Category = new Category (new Set (["Charlie"])) // Charlie - let cnf1 : CNF = new CNF ( new Set ([cat1, cat2])) // (Alice \/ Bob ) /\ Charlie - let cat3 : Category = new Category (new Set (["Alice"])); - let cnf2 : CNF = new CNF ( new Set ([cat1])) // Alice \/ Bob - let cnf3 : CNF = new CNF ( new Set ([cat3])) // Alice - let cnf4 : CNF = new CNF ( new Set ([new Category (new Set (["Alice"])) - , new Category (new Set (["Bob" ]))])) - - - - let cnfs = [cnf1, cnf2, cnf3, cnf4, CNF_TRUE, CNF_FALSE] - - // console.log ( implies (cnf4, CNF_TRUE)) - // console.log ( implies (CNF_FALSE, cnf4)) +function test1() { + const cat1: Category = new Category(new Set(["Alice", "Bob"])); // Alice \/ Bob + const cat2: Category = new Category(new Set(["Charlie"])); // Charlie + const cnf1: CNF = new CNF(new Set([cat1, cat2])); // (Alice \/ Bob ) /\ Charlie + const cat3: Category = new Category(new Set(["Alice"])); + const cnf2: CNF = new CNF(new Set([cat1])); // Alice \/ Bob + const cnf3: CNF = new CNF(new Set([cat3])); // Alice + const cnf4: CNF = new CNF( + new Set([new Category(new Set(["Alice"])), new Category(new Set(["Bob"]))]), + ); - cnfs.map ((x: CNF) => { console.log (x.stringRep(Delimiterification.AsNeeded))}) - cnfs.map ((x: CNF) => { - console.log (JSON.stringify(x.toJSON())) - }) - } - -function main () { -test1() + const cnfs = [cnf1, cnf2, cnf3, cnf4, CNF_TRUE, CNF_FALSE]; + + // console.log ( implies (cnf4, CNF_TRUE)) + // console.log ( implies (CNF_FALSE, cnf4)) + + cnfs.map((x: CNF) => { + console.log(x.stringRep(Delimiterification.AsNeeded)); + }); + cnfs.map((x: CNF) => { + console.log(JSON.stringify(x.toJSON())); + }); +} + +function main() { + test1(); } -main () \ No newline at end of file +main(); diff --git a/rt/src/_experiments/dclabels_test.mts b/rt/src/_experiments/dclabels_test.mts index 7893e097..74c64ea1 100644 --- a/rt/src/_experiments/dclabels_test.mts +++ b/rt/src/_experiments/dclabels_test.mts @@ -1,26 +1,24 @@ -import { DCLabel, IFC_TOP, IFC_BOT } - from "../levels/DCLabels/dclabel.mjs" +import { DCLabel, IFC_TOP, IFC_BOT } from "../levels/DCLabels/dclabel.mjs"; -function test1() { - console.log (IFC_BOT.flowsTo(IFC_TOP)); +function test1() { + console.log(IFC_BOT.flowsTo(IFC_TOP)); } function test2() { - let a = DCLabel.fromSingleTag ("alice") - let b = DCLabel.fromSingleTag ("bob") - let c = a.join (b); - console.log (c.stringRep ()); + const a = DCLabel.fromSingleTag("alice"); + const b = DCLabel.fromSingleTag("bob"); + const c = a.join(b); + console.log(c.stringRep()); } function test3() { - let a = DCLabel.fromSingleTag ("alice") - let c = a.join (IFC_BOT); - console.log (c.stringRep ()); + const a = DCLabel.fromSingleTag("alice"); + const c = a.join(IFC_BOT); + console.log(c.stringRep()); } - -function main () { - test3(); +function main() { + test3(); } -main () \ No newline at end of file +main(); diff --git a/rt/src/builtins/UserRuntimeZero.mts b/rt/src/builtins/UserRuntimeZero.mts index 1f34839c..13daf9df 100644 --- a/rt/src/builtins/UserRuntimeZero.mts +++ b/rt/src/builtins/UserRuntimeZero.mts @@ -1,54 +1,60 @@ -'use strict' -import { runtimeEquals } from '../EqualityChecker.mjs' -import { isListFlagSet, isTupleFlagSet, mkTuple, mkList } from '../ValuesUtil.mjs' -import { LVal, LValCopyAt, LCopyVal } from '../Lval.mjs' -import { Nil, Cons, RawList } from '../RawList.mjs' -import { loadLibsAsync } from '../loadLibsAsync.mjs'; -import * as levels from '../Level.mjs' -import { BaseFunctionWithExplicitArg, ServiceFunction } from '../BaseFunction.mjs' -import { Atom } from '../Atom.mjs' -import { __unit } from '../UnitVal.mjs' -import { RuntimeInterface } from '../RuntimeInterface.mjs'; -import { Record } from '../Record.mjs' -import { TroupeType } from '../TroupeTypes.mjs' -import { RawClosure } from '../RawClosure.mjs' -import { __unitbase } from '../UnitBase.mjs' -import { Thread } from '../Thread.mjs' -import { TroupeRawValue } from '../TroupeRawValue.mjs' -import { RawTuple } from '../RawTuple.mjs' -import { Level } from '../Level.mjs' -import { rawAssertNotZero } from '../Asserts.mjs' +"use strict"; +import { runtimeEquals } from "../EqualityChecker.mjs"; +import { + isListFlagSet, + isTupleFlagSet, + mkTuple, + mkList, +} from "../ValuesUtil.mjs"; +import { LVal, LValCopyAt, LCopyVal } from "../Lval.mjs"; +import { Nil, Cons, RawList } from "../RawList.mjs"; +import { loadLibsAsync } from "../loadLibsAsync.mjs"; +import * as levels from "../Level.mjs"; +import { + BaseFunctionWithExplicitArg, + ServiceFunction, +} from "../BaseFunction.mjs"; +import { Atom } from "../Atom.mjs"; +import { __unit } from "../UnitVal.mjs"; +import { RuntimeInterface } from "../RuntimeInterface.mjs"; +import { Record } from "../Record.mjs"; +import { TroupeType } from "../TroupeTypes.mjs"; +import { RawClosure } from "../RawClosure.mjs"; +import { __unitbase } from "../UnitBase.mjs"; +import { Thread } from "../Thread.mjs"; +import { TroupeRawValue } from "../TroupeRawValue.mjs"; +import { RawTuple } from "../RawTuple.mjs"; +import { Level } from "../Level.mjs"; +import { rawAssertNotZero } from "../Asserts.mjs"; // import { builtin_sandbox } from './builtins/sandox' export type Constructor = new (...args: any[]) => T; - -const {lub} = levels +const { lub } = levels; class RtEnv { - _is_rt_env: boolean; - constructor() { - this._is_rt_env = true; - } + _is_rt_env: boolean; + constructor() { + this._is_rt_env = true; + } } class LibEnv { - ret: any; - _is_rt_env: boolean - constructor() { - this._is_rt_env = false; - this.ret = null; - } + ret: any; + _is_rt_env: boolean; + constructor() { + this._is_rt_env = false; + this.ret = null; + } } - -export function mkBase(f,name=null) { - return BaseFunctionWithExplicitArg(f,name) +export function mkBase(f, name = null) { + return BaseFunctionWithExplicitArg(f, name); } export function mkService(f, name = null) { - return ServiceFunction(f, name) + return ServiceFunction(f, name); } /** @@ -63,241 +69,242 @@ export function mkService(f, name = null) { * Functions marked with "SpecialRT" do not work on values and are special control instructions. */ export class UserRuntimeZero { - runtime: RuntimeInterface - - mkuuid: any - // SimpleRT with array of labelled values as parameter - mkRecord = Record.mkRecord - // SimpleRT with array of labelled values as parameter - mkTuple = mkTuple - // SimpleRT with array of labelled values as parameter - mkList = mkList - sandbox: any - sleep: any - - Env = RtEnv - RawClosure = RawClosure - constructLVal = (x,y,z) => new LVal (x,y,z) - mkVal : (x:any) => LVal = this.default_mkVal - mkValPos : (x:any, pos:string) => LVal = this.default_mkValPos - __unit = __unit - __unitbase = __unitbase - Atom = Atom - - constructor(runtime:RuntimeInterface) { - this.runtime = runtime - } - - - debug (x) { - this.runtime.debug(x); - } - - ret (x) { - this.runtime.ret (x) - } - - // SimpleRT - raw_join(...xs) : Level { - return lub.apply (null, xs) - } - - // SpecialRT - raw_invalidateSparseBit() { - this.runtime.$t.invalidateSparseBit() - } - - // SpecialRT - rawErrorPos(x: TroupeRawValue, pos: string) { - if (pos != '') { - this.runtime.$t.threadError(x + " at " + pos); - } else { - this.runtime.$t.threadError("" + x); - } - } - - // ComplexRT - eq(x: TroupeRawValue, y: TroupeRawValue): LVal { - return runtimeEquals(x, y) - } - - // ComplexRT - neq(x: TroupeRawValue, y: TroupeRawValue): LVal { - let b = runtimeEquals(x, y); - b.val = !b.val; - return b; - } - - // SimpleRT - intdiv(x: number, y: number): number { - return Math.trunc(x / y) - } - - // SimpleRT - rawAssertNotZero = rawAssertNotZero - - // ComplexRT - raw_indexTuple(x: TroupeRawValue, y: number): LVal { - return x[y]; - } - - // SimpleRT - raw_islist(x: TroupeRawValue): boolean { - return isListFlagSet(x) // TODO check _troupeType instead? - } - - // SimpleRT - raw_istuple(x: TroupeRawValue): boolean { - return (x._troupeType == TroupeType.TUPLE) - } - - // ComplexRT - getField(x: Record, f: string): LVal { - return x.getField(f) - } - - // SimpleRT - hasField(x: Record, f: string): boolean { - return x.hasField(f) - } - - // SimpleRT - isRecord(x: TroupeRawValue): boolean { - return (x._troupeType == TroupeType.RECORD) - } - - // SimpleRT - withRecord(r: Record, fields: Array<[string, LVal]>): Record { - return Record.mkWithRecord(r, fields) - } - - // SimpleRT - cons(a: LVal, b: RawList): RawList { - return new Cons(a, b) - } - - // SimpleRT - raw_listLength(x: RawList): number { - return x.length - } - - // SimpleRT - raw_tupleLength(x: RawTuple): number { - return x.length - } - - // SimpleRT - raw_recordSize(x: Record): number { - return x.__obj.size - } - - // ComplexRT - head(x: RawList): LVal { - return x.head; - } - - // SimpleRT - tail(x: RawList): RawList { - return x.tail - } - - // SimpleRT - mkV1Label(x: string): Level { - return levels.mkV1Level(x) - } - - mkDCLabel(x:any):Level { - return levels.mkLevel(x); - } - - /** - * ComplexRT. - * Lookup a definition from a library. - * @param lib the library - * @param decl the declaration to look up - * @param obj the object to store the result in, under "libs["lib.decl"]" - * @returns the unlabelled value from the definition - */ - loadLib(lib: string, decl: string, obj: { libs: { [x: string]: any } }): any { - // load the lib from the linked data structure - let r = obj.libs[lib + "." + decl]; - // rt_debug("loading lib " + decl); - return r; - } - - - /* - * ============================================================== - * The remaining functions are not referred to by generated code. - * ============================================================== - */ - - branch = function (x) { - this.runtime.$t.setBranchFlag() - this.runtime.$t.raiseCurrentThreadPC(x.lev); - } - - push(x, frameSize) { - this.runtime.$t.pushFrame(x, frameSize); - } - - assertOrError(x) { - this.runtime.$t.raiseBlockingThreadLev(x.lev); - } - - default_mkVal(x) { - return this.runtime.$t.mkVal(x) - } - - default_mkValPos(x,p) { - return this.runtime.$t.mkValPos(x, p) - } - - mkCopy (x):LVal { - return this.runtime.$t.mkCopy(x) - } - - - libLoadingPseudoThread = new Thread(null, null, null, __unit, levels.BOT, levels.BOT, null, this, null); - savedThread = null ;// this.runtime.__sched.__currentThread; - setLibloadMode() { - this.mkVal = (x) => new LVal(x, levels.BOT); - this.mkValPos = (x, pos) => new LVal(x, levels.BOT, levels.BOT, pos); - this.Env = LibEnv; - this.savedThread = this.runtime.__sched.__currentThread; - this.runtime.__sched.__currentThread = this.libLoadingPseudoThread; - } - - - setNormalMode() { - this.mkVal = this.default_mkVal; - this.mkValPos = this.default_mkValPos - this.Env = RtEnv; - this.runtime.__sched.__currentThread = this.savedThread; - } - - // tailcall(lff, arg) { - // this.runtime.tailcall (lff, arg) - // } - - // raw_tailcall(x) { - // this.runtime.__sched.tailToTroupeFun_raw (x); - // } - - - async linkLibs (f) { - await loadLibsAsync(f, this) - } - - errorPos (x: { val: string }, pos: string) { - if (pos != '') { - this.runtime.$t.threadError(x.val + " at " + pos); - } else { - this.runtime.$t.threadError(x.val); - } - } - + runtime: RuntimeInterface; + + mkuuid: any; + // SimpleRT with array of labelled values as parameter + mkRecord = Record.mkRecord; + // SimpleRT with array of labelled values as parameter + mkTuple = mkTuple; + // SimpleRT with array of labelled values as parameter + mkList = mkList; + sandbox: any; + sleep: any; + + Env = RtEnv; + RawClosure = RawClosure; + constructLVal = (x, y, z) => new LVal(x, y, z); + mkVal: (x: any) => LVal = this.default_mkVal; + mkValPos: (x: any, pos: string) => LVal = this.default_mkValPos; + __unit = __unit; + __unitbase = __unitbase; + Atom = Atom; + + constructor(runtime: RuntimeInterface) { + this.runtime = runtime; + } + + debug(x) { + this.runtime.debug(x); + } + + ret(x) { + this.runtime.ret(x); + } + + // SimpleRT + raw_join(...xs): Level { + return lub.apply(null, xs); + } + + // SpecialRT + raw_invalidateSparseBit() { + this.runtime.$t.invalidateSparseBit(); + } + + // SpecialRT + rawErrorPos(x: TroupeRawValue, pos: string) { + if (pos != "") { + this.runtime.$t.threadError(x + " at " + pos); + } else { + this.runtime.$t.threadError("" + x); + } + } + + // ComplexRT + eq(x: TroupeRawValue, y: TroupeRawValue): LVal { + return runtimeEquals(x, y); + } + + // ComplexRT + neq(x: TroupeRawValue, y: TroupeRawValue): LVal { + const b = runtimeEquals(x, y); + b.val = !b.val; + return b; + } + + // SimpleRT + intdiv(x: number, y: number): number { + return Math.trunc(x / y); + } + + // SimpleRT + rawAssertNotZero = rawAssertNotZero; + + // ComplexRT + raw_indexTuple(x: TroupeRawValue, y: number): LVal { + return x[y]; + } + + // SimpleRT + raw_islist(x: TroupeRawValue): boolean { + return isListFlagSet(x); // TODO check _troupeType instead? + } + + // SimpleRT + raw_istuple(x: TroupeRawValue): boolean { + return x._troupeType == TroupeType.TUPLE; + } + + // ComplexRT + getField(x: Record, f: string): LVal { + return x.getField(f); + } + + // SimpleRT + hasField(x: Record, f: string): boolean { + return x.hasField(f); + } + + // SimpleRT + isRecord(x: TroupeRawValue): boolean { + return x._troupeType == TroupeType.RECORD; + } + + // SimpleRT + withRecord(r: Record, fields: [string, LVal][]): Record { + return Record.mkWithRecord(r, fields); + } + + // SimpleRT + cons(a: LVal, b: RawList): RawList { + return new Cons(a, b); + } + + // SimpleRT + raw_listLength(x: RawList): number { + return x.length; + } + + // SimpleRT + raw_tupleLength(x: RawTuple): number { + return x.length; + } + + // SimpleRT + raw_recordSize(x: Record): number { + return x.__obj.size; + } + + // ComplexRT + head(x: RawList): LVal { + return x.head; + } + + // SimpleRT + tail(x: RawList): RawList { + return x.tail; + } + + // SimpleRT + mkV1Label(x: string): Level { + return levels.mkV1Level(x); + } + + mkDCLabel(x: any): Level { + return levels.mkLevel(x); + } + + /** + * ComplexRT. + * Lookup a definition from a library. + * @param lib the library + * @param decl the declaration to look up + * @param obj the object to store the result in, under "libs["lib.decl"]" + * @returns the unlabelled value from the definition + */ + loadLib(lib: string, decl: string, obj: { libs: { [x: string]: any } }): any { + // load the lib from the linked data structure + const r = obj.libs[lib + "." + decl]; + // rt_debug("loading lib " + decl); + return r; + } + + /* + * ============================================================== + * The remaining functions are not referred to by generated code. + * ============================================================== + */ + + branch = function (x) { + this.runtime.$t.setBranchFlag(); + this.runtime.$t.raiseCurrentThreadPC(x.lev); + }; + + push(x, frameSize) { + this.runtime.$t.pushFrame(x, frameSize); + } + + assertOrError(x) { + this.runtime.$t.raiseBlockingThreadLev(x.lev); + } + + default_mkVal(x) { + return this.runtime.$t.mkVal(x); + } + + default_mkValPos(x, p) { + return this.runtime.$t.mkValPos(x, p); + } + + mkCopy(x): LVal { + return this.runtime.$t.mkCopy(x); + } + + libLoadingPseudoThread = new Thread( + null, + null, + null, + __unit, + levels.BOT, + levels.BOT, + null, + this, + null, + ); + savedThread = null; // this.runtime.__sched.__currentThread; + setLibloadMode() { + this.mkVal = (x) => new LVal(x, levels.BOT); + this.mkValPos = (x, pos) => new LVal(x, levels.BOT, levels.BOT, pos); + this.Env = LibEnv; + this.savedThread = this.runtime.__sched.__currentThread; + this.runtime.__sched.__currentThread = this.libLoadingPseudoThread; + } + + setNormalMode() { + this.mkVal = this.default_mkVal; + this.mkValPos = this.default_mkValPos; + this.Env = RtEnv; + this.runtime.__sched.__currentThread = this.savedThread; + } + + // tailcall(lff, arg) { + // this.runtime.tailcall (lff, arg) + // } + + // raw_tailcall(x) { + // this.runtime.__sched.tailToTroupeFun_raw (x); + // } + + async linkLibs(f) { + await loadLibsAsync(f, this); + } + + errorPos(x: { val: string }, pos: string) { + if (pos != "") { + this.runtime.$t.threadError(x.val + " at " + pos); + } else { + this.runtime.$t.threadError(x.val); + } + } } - - - diff --git a/rt/src/builtins/adv.mts b/rt/src/builtins/adv.mts index 93ccafaf..5d8e8ca2 100644 --- a/rt/src/builtins/adv.mts +++ b/rt/src/builtins/adv.mts @@ -1,114 +1,120 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import * as levels from '../Level.mjs' -import { assertIsNTuple, assertNormalState } from '../Asserts.mjs'; -import { __unit } from '../UnitVal.mjs'; -import { getCliArgs, TroupeCliArg } from '../TroupeCliArgs.mjs'; - -const {lub, flowsTo} = levels +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import * as levels from "../Level.mjs"; +import { assertIsNTuple, assertNormalState } from "../Asserts.mjs"; +import { __unit } from "../UnitVal.mjs"; +import { getCliArgs, TroupeCliArg } from "../TroupeCliArgs.mjs"; + +const { lub, flowsTo } = levels; const argv = getCliArgs(); -/* - - ┌────────┐ - │ TOP │ - └────────┘ - Λ - ╱ ╲ - ╱ ╲ - ╱ ╲ - ╱ ╲ - ╱ ╲ - ╱ ╲ - ╱ ╲ +/* + + ┌────────┐ + │ TOP │ + └────────┘ + Λ + ╱ ╲ + ╱ ╲ + ╱ ╲ + ╱ ╲ + ╱ ╲ + ╱ ╲ + ╱ ╲ ┌────────┐ ┌────────┐ │ NULL │ │ ROOT │ └────────┘ └────────┘ - ╲ ╱ - ╲ ╱ - ╲ ╱ - ╲ ╱ - ╲ ╱ - ╲ ╱ - ╲ ╱ - V - ┌────────┐ - │ BOT │ - └────────┘ - - -*/ - - - -export function BuiltinAdv >(Base: TBase) { - return class extends Base { - mkSecret = mkBase((x) => { - // debug ("making secret " + x.val) - this.runtime.$t.invalidateSparseBit() - return this.runtime.ret(new LVal(x.val, levels.TOP)) - }) - - adv = mkBase((x) => { - assertNormalState("baseDisclose"); - - // Check if running in network mode (i.e., NOT local-only) - if (!argv[TroupeCliArg.LocalOnly]) { - this.runtime.$t.threadError("adv function is disabled in network mode."); - } - - // assert that - // pc ⊔ x.lev ⊑ NULL - - if (!flowsTo(lub(this.runtime.$t.bl, x.dlev), levels.NULL)) { - this.runtime.$t. - threadError("Illegal flow in adv function:\n" + - ` | pc: ${this.runtime.$t.pc.stringRep()}\n` + - ` | block: ${this.runtime.$t.bl.stringRep()}\n` + - ` | value: ${x.stringRep()}`) - } - return this.runtime.ret(__unit); - }) - - cert = mkBase ((x) =>{ - assertNormalState("baseCertify"); - - // Check if running in network mode (i.e., NOT local-only) - if (!argv[TroupeCliArg.LocalOnly]) { - this.runtime.$t.threadError("cert function is disabled in network mode."); - } - - // assert that - // pc ⊔ x.lev ⊑ ROOT - - if (!flowsTo(lub(this.runtime.$t.bl, x.dlev), levels.ROOT)) { - this.runtime.$t. - threadError("Illegal flow in cert function:\n" + - ` | pc: ${this.runtime.$t.pc.stringRep()}\n` + - ` | block: ${this.runtime.$t.bl.stringRep()}\n` + - ` | value: ${x.stringRep()}`) - } - return this.runtime.ret(__unit); - }) - - ladv = mkBase((x) => { - assertNormalState("ladv"); - assertIsNTuple(x, 2) - let l_adv = x.val[0] - let value = x.val[1] - // assert that - // pc ⊔ x.lev ⊑ LOW - - if (!flowsTo(lub(this.runtime.$t.bl, value.lev, l_adv.lev), l_adv.val)) { - this.runtime.$t. - threadError("Illegal flow in adv function:\n" + - ` | pc: ${this.runtime.$t.pc.stringRep()}\n` + - ` | block: ${this.runtime.$t.bl.stringRep()}\n` + - ` | l_adv: ${l_adv.stringRep()} \n` + - ` | value: ${value.stringRep()}`) - } - return this.runtime.ret(__unit); - }) - - } -} \ No newline at end of file + ╲ ╱ + ╲ ╱ + ╲ ╱ + ╲ ╱ + ╲ ╱ + ╲ ╱ + ╲ ╱ + V + ┌────────┐ + │ BOT │ + └────────┘ + + +*/ + +export function BuiltinAdv>( + Base: TBase, +) { + return class extends Base { + mkSecret = mkBase((x) => { + // debug ("making secret " + x.val) + this.runtime.$t.invalidateSparseBit(); + return this.runtime.ret(new LVal(x.val, levels.TOP)); + }); + + adv = mkBase((x) => { + assertNormalState("baseDisclose"); + + // Check if running in network mode (i.e., NOT local-only) + if (!argv[TroupeCliArg.LocalOnly]) { + this.runtime.$t.threadError( + "adv function is disabled in network mode.", + ); + } + + // assert that + // pc ⊔ x.lev ⊑ NULL + + if (!flowsTo(lub(this.runtime.$t.bl, x.dlev), levels.NULL)) { + this.runtime.$t.threadError( + "Illegal flow in adv function:\n" + + ` | pc: ${this.runtime.$t.pc.stringRep()}\n` + + ` | block: ${this.runtime.$t.bl.stringRep()}\n` + + ` | value: ${x.stringRep()}`, + ); + } + return this.runtime.ret(__unit); + }); + + cert = mkBase((x) => { + assertNormalState("baseCertify"); + + // Check if running in network mode (i.e., NOT local-only) + if (!argv[TroupeCliArg.LocalOnly]) { + this.runtime.$t.threadError( + "cert function is disabled in network mode.", + ); + } + + // assert that + // pc ⊔ x.lev ⊑ ROOT + + if (!flowsTo(lub(this.runtime.$t.bl, x.dlev), levels.ROOT)) { + this.runtime.$t.threadError( + "Illegal flow in cert function:\n" + + ` | pc: ${this.runtime.$t.pc.stringRep()}\n` + + ` | block: ${this.runtime.$t.bl.stringRep()}\n` + + ` | value: ${x.stringRep()}`, + ); + } + return this.runtime.ret(__unit); + }); + + ladv = mkBase((x) => { + assertNormalState("ladv"); + assertIsNTuple(x, 2); + const l_adv = x.val[0]; + const value = x.val[1]; + // assert that + // pc ⊔ x.lev ⊑ LOW + + if (!flowsTo(lub(this.runtime.$t.bl, value.lev, l_adv.lev), l_adv.val)) { + this.runtime.$t.threadError( + "Illegal flow in adv function:\n" + + ` | pc: ${this.runtime.$t.pc.stringRep()}\n` + + ` | block: ${this.runtime.$t.bl.stringRep()}\n` + + ` | l_adv: ${l_adv.stringRep()} \n` + + ` | value: ${value.stringRep()}`, + ); + } + return this.runtime.ret(__unit); + }); + }; +} diff --git a/rt/src/builtins/attenuate.mts b/rt/src/builtins/attenuate.mts index 1fabbb36..f0ad0195 100644 --- a/rt/src/builtins/attenuate.mts +++ b/rt/src/builtins/attenuate.mts @@ -1,30 +1,37 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import * as levels from '../Level.mjs' -import { Authority } from '../Authority.mjs'; -import { assertIsNTuple, assertIsAuthority, assertIsLevel } from '../Asserts.mjs' -const {lub, flowsTo} = levels +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import * as levels from "../Level.mjs"; +import { Authority } from "../Authority.mjs"; +import { + assertIsNTuple, + assertIsAuthority, + assertIsLevel, +} from "../Asserts.mjs"; +const { lub, flowsTo } = levels; +export function BuiltinAttenuate>( + Base: TBase, +) { + return class extends Base { + attenuate = mkBase((arg) => { + assertIsNTuple(arg, 2); + const argv = arg.val; + const authFrom = argv[0]; + assertIsAuthority(authFrom); + const levTo = argv[1]; + assertIsLevel(levTo); -export function BuiltinAttenuate>(Base: TBase) { - return class extends Base { - attenuate = mkBase((arg) => { - assertIsNTuple(arg, 2); - let argv = arg.val; - let authFrom = argv[0]; - assertIsAuthority(authFrom); - let levTo = argv[1]; - assertIsLevel(levTo); + const ok_to_attenuate = levels.actsFor( + authFrom.val.authorityLevel, + levTo.val, + ); - let ok_to_attenuate = levels.actsFor(authFrom.val.authorityLevel, levTo.val); + // todo: 2018-10-18: AA; are we missing anything? + const l_meta = lub(this.runtime.$t.pc, arg.lev, authFrom.lev, levTo.lev); + const l_auth = ok_to_attenuate ? levTo.val : levels.BOT; + const r = new LVal(new Authority(l_auth), l_meta); - // todo: 2018-10-18: AA; are we missing anything? - let l_meta = lub(this.runtime.$t.pc, arg.lev, authFrom.lev, levTo.lev) - let l_auth = ok_to_attenuate ? levTo.val : levels.BOT; - let r = new LVal(new Authority(l_auth), l_meta) - - return this.runtime.ret(r) - }, "attenuate") - - } -} \ No newline at end of file + return this.runtime.ret(r); + }, "attenuate"); + }; +} diff --git a/rt/src/builtins/debugutils.mts b/rt/src/builtins/debugutils.mts index f712e7a3..aafc1b74 100644 --- a/rt/src/builtins/debugutils.mts +++ b/rt/src/builtins/debugutils.mts @@ -1,47 +1,49 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' -import { assertIsString, assertIsNumber, assertIsNTuple } from '../Asserts.mjs' -import { __unit } from '../UnitVal.mjs'; -import { TroupeType } from '../TroupeTypes.mjs'; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { assertIsString, assertIsNumber, assertIsNTuple } from "../Asserts.mjs"; +import { __unit } from "../UnitVal.mjs"; +import { TroupeType } from "../TroupeTypes.mjs"; +export function BuiltinDebugUtils>( + Base: TBase, +) { + return class extends Base { + _setProcessDebuggingName = mkBase((arg) => { + assertIsString(arg); + this.runtime.$t.processDebuggingName = arg.val; + return this.runtime.ret(__unit); + }); -export function BuiltinDebugUtils > (Base:TBase) { - return class extends Base { - _setProcessDebuggingName = mkBase((arg) => { - assertIsString(arg) - this.runtime.$t.processDebuggingName = arg.val - return this.runtime.ret(__unit) - }) + debugpc = mkBase((arg) => { + this.runtime.debug(""); + // this.runtime.$t.showStack() + return this.runtime.ret(__unit); + }); - debugpc = mkBase((arg) => { - this.runtime.debug(""); - // this.runtime.$t.showStack() - return this.runtime.ret(__unit); - }) + _debug = mkBase((arg) => { + console.log(arg.stringRep(true)); + return this.runtime.ret(__unit); + }); - _debug = mkBase ((arg) => { - console.log (arg.stringRep(true)) - return this.runtime.ret(__unit); - }) - - _setFailureRate = mkBase((arg) => { - let _tt = arg.getTroupeType; - switch (_tt) { - case TroupeType.NUMBER: - this.runtime.$t.failureRate = arg.val - this.runtime.$t.failureStartTime = 0; - break; - case TroupeType.TUPLE: - assertIsNTuple(arg, 2) - assertIsNumber (arg.val[0]) - assertIsNumber (arg.val[1]) - this.runtime.$t.failureRate = arg.val[0].val - this.runtime.$t.failureStartTime = Date.now() + arg.val[1].val - break; - default: - this.runtime.$t.threadError ("Invalid argument type in function _setFailureRate"); - } - return this.runtime.ret(__unit); - }) - } + _setFailureRate = mkBase((arg) => { + const _tt = arg.getTroupeType; + switch (_tt) { + case TroupeType.NUMBER: + this.runtime.$t.failureRate = arg.val; + this.runtime.$t.failureStartTime = 0; + break; + case TroupeType.TUPLE: + assertIsNTuple(arg, 2); + assertIsNumber(arg.val[0]); + assertIsNumber(arg.val[1]); + this.runtime.$t.failureRate = arg.val[0].val; + this.runtime.$t.failureStartTime = Date.now() + arg.val[1].val; + break; + default: + this.runtime.$t.threadError( + "Invalid argument type in function _setFailureRate", + ); + } + return this.runtime.ret(__unit); + }); + }; } - diff --git a/rt/src/builtins/declassify.mts b/rt/src/builtins/declassify.mts index 96e540b8..274c417c 100644 --- a/rt/src/builtins/declassify.mts +++ b/rt/src/builtins/declassify.mts @@ -1,17 +1,20 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { __unit } from '../UnitVal.mjs'; -import { downgrader } from '../downgrading.mjs'; -import { DowngradeDimension } from '../DowngradeEnums.mjs'; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { __unit } from "../UnitVal.mjs"; +import { downgrader } from "../downgrading.mjs"; +import { DowngradeDimension } from "../DowngradeEnums.mjs"; -export function BuiltinDeclassify>(Base: TBase) { - return class extends Base { - endorse = mkBase - ( downgrader (this.runtime, DowngradeDimension.INTEGRITY, false) - , "endorse") +export function BuiltinDeclassify>( + Base: TBase, +) { + return class extends Base { + endorse = mkBase( + downgrader(this.runtime, DowngradeDimension.INTEGRITY, false), + "endorse", + ); - - declassify = mkBase - ( downgrader (this.runtime, DowngradeDimension.CONFIDENTIALITY, false) - , "declassify") - } -} \ No newline at end of file + declassify = mkBase( + downgrader(this.runtime, DowngradeDimension.CONFIDENTIALITY, false), + "declassify", + ); + }; +} diff --git a/rt/src/builtins/exit.mts b/rt/src/builtins/exit.mts index 25e1c0e6..7773b65f 100644 --- a/rt/src/builtins/exit.mts +++ b/rt/src/builtins/exit.mts @@ -1,31 +1,36 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { assertNormalState, assertIsNTuple, assertIsAuthority, assertIsNumber, assertIsRootAuthority } from '../Asserts.mjs' -import { __unit } from '../UnitVal.mjs'; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { + assertNormalState, + assertIsNTuple, + assertIsAuthority, + assertIsNumber, + assertIsRootAuthority, +} from "../Asserts.mjs"; +import { __unit } from "../UnitVal.mjs"; +export function BuiltinExit>( + Base: TBase, +) { + return class extends Base { + exit = mkBase((arg) => { + const $r = this.runtime; + assertNormalState("exit"); + assertIsNTuple(arg, 2); + assertIsAuthority(arg.val[0]); + assertIsNumber(arg.val[1]); + assertIsRootAuthority(arg.val[0]); + (async () => { + await $r.cleanup(); + process.exit(arg.val[1].val); + })(); + }, "exit"); -export function BuiltinExit >(Base: TBase) { - return class extends Base { - exit = mkBase((arg) => { - let $r = this.runtime - assertNormalState("exit"); - assertIsNTuple(arg, 2); - assertIsAuthority(arg.val[0]); - assertIsNumber(arg.val[1]); - assertIsRootAuthority(arg.val[0]); - (async () => { - await $r.cleanup() - process.exit(arg.val[1].val); - }) () - - }, "exit") - - _resetScheduler = mkBase((arg) => { - assertNormalState("exit"); - assertIsAuthority(arg); - assertIsRootAuthority(arg); - this.runtime.__sched.resetScheduler () - return this.runtime.ret(__unit) - - }) - } -} \ No newline at end of file + _resetScheduler = mkBase((arg) => { + assertNormalState("exit"); + assertIsAuthority(arg); + assertIsRootAuthority(arg); + this.runtime.__sched.resetScheduler(); + return this.runtime.ret(__unit); + }); + }; +} diff --git a/rt/src/builtins/getTime.mts b/rt/src/builtins/getTime.mts index 79e024ea..f10de9ff 100644 --- a/rt/src/builtins/getTime.mts +++ b/rt/src/builtins/getTime.mts @@ -1,26 +1,26 @@ -'use strict' -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import { assertIsUnit, assertNormalState } from '../Asserts.mjs' +"use strict"; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import { assertIsUnit, assertNormalState } from "../Asserts.mjs"; +export function BuiltinGetTime>( + Base: TBase, +) { + return class extends Base { + getTime = mkBase((arg) => { + assertNormalState("getTime"); + assertIsUnit(arg); + const d = new Date(); + const t = d.getTime(); + const v = new LVal(t, this.runtime.$t.pc); + return this.runtime.ret(v); + }); -export function BuiltinGetTime>(Base: TBase) { - return class extends Base { - getTime = mkBase((arg) => { - assertNormalState("getTime") - assertIsUnit(arg) - let d = new Date() - let t = d.getTime() - let v = new LVal(t, this.runtime.$t.pc); - return this.runtime.ret(v) - }) - - getNanoTime = mkBase((arg) => { - assertIsUnit(arg) - let t = process.hrtime.bigint() - let v = new LVal(t, this.runtime.$t.pc); - return this.runtime.ret(v) - }) - - } + getNanoTime = mkBase((arg) => { + assertIsUnit(arg); + const t = process.hrtime.bigint(); + const v = new LVal(t, this.runtime.$t.pc); + return this.runtime.ret(v); + }); + }; } diff --git a/rt/src/builtins/levelops.mts b/rt/src/builtins/levelops.mts index a106830e..05ae691c 100644 --- a/rt/src/builtins/levelops.mts +++ b/rt/src/builtins/levelops.mts @@ -1,36 +1,35 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import {lub, flowsTo, BOT} from '../Level.mjs' -import { v4 as uuidv4 } from 'uuid' -import { assertIsNTuple, assertIsLevel, assertIsUnit } from '../Asserts.mjs' - - -export function BuiltinLevOps > (Base:TBase) { - return class extends Base { - levelOf = mkBase((arg) => { - let l = arg.lev; - return this.runtime.ret(new LVal(l, lub(this.runtime.$t.pc, l), BOT)) - }) - - - flowsTo = mkBase((arg) => { - assertIsNTuple(arg, 2); - let x = arg.val[0]; - let y = arg.val[1]; - - assertIsLevel(x); - assertIsLevel(y); - - return this.runtime.ret(new LVal(flowsTo(x.val, y.val), lub (x.lev, y.lev), BOT)) // lub (__sched.pc, lub(x.lev, y.lev)))) - }) - - - newlabel = mkBase((arg) => { - assertIsUnit(arg); - let levid = uuidv4().toString() - return this.runtime.ret(this.runtime.mkLabel(levid)); - }) - } +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import { lub, flowsTo, BOT } from "../Level.mjs"; +import { v4 as uuidv4 } from "uuid"; +import { assertIsNTuple, assertIsLevel, assertIsUnit } from "../Asserts.mjs"; + +export function BuiltinLevOps>( + Base: TBase, +) { + return class extends Base { + levelOf = mkBase((arg) => { + const l = arg.lev; + return this.runtime.ret(new LVal(l, lub(this.runtime.$t.pc, l), BOT)); + }); + + flowsTo = mkBase((arg) => { + assertIsNTuple(arg, 2); + const x = arg.val[0]; + const y = arg.val[1]; + + assertIsLevel(x); + assertIsLevel(y); + + return this.runtime.ret( + new LVal(flowsTo(x.val, y.val), lub(x.lev, y.lev), BOT), + ); // lub (__sched.pc, lub(x.lev, y.lev)))) + }); + + newlabel = mkBase((arg) => { + assertIsUnit(arg); + const levid = uuidv4().toString(); + return this.runtime.ret(this.runtime.mkLabel(levid)); + }); + }; } - - diff --git a/rt/src/builtins/listToTuple.mts b/rt/src/builtins/listToTuple.mts index d5ed005e..d4b0a8b7 100644 --- a/rt/src/builtins/listToTuple.mts +++ b/rt/src/builtins/listToTuple.mts @@ -1,30 +1,32 @@ -'use strict' -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import { assertIsList } from '../Asserts.mjs' -import { mkTuple } from '../ValuesUtil.mjs' -import { lub } from '../Level.mjs'; +"use strict"; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import { assertIsList } from "../Asserts.mjs"; +import { mkTuple } from "../ValuesUtil.mjs"; +import { lub } from "../Level.mjs"; -export function BuiltinListToTuple>(Base: TBase) { - return class extends Base { - listToTuple = mkBase((larg) => { - // Assert that the argument is a list - assertIsList(larg); - - // Convert the list to an array of LVals - let arr = larg.val.toArray(); - - // Calculate the combined level (join of list level and all element levels) - let combinedLevel = lub(larg.lev, this.runtime.$t.pc); - for (let elem of arr) { - combinedLevel = lub(combinedLevel, elem.lev); - } - - // Create the tuple from the array - let tuple = mkTuple(arr); - - // Return the tuple with the combined security level - return this.runtime.ret(new LVal(tuple, combinedLevel)); - }, "listToTuple") - } -} \ No newline at end of file +export function BuiltinListToTuple>( + Base: TBase, +) { + return class extends Base { + listToTuple = mkBase((larg) => { + // Assert that the argument is a list + assertIsList(larg); + + // Convert the list to an array of LVals + const arr = larg.val.toArray(); + + // Calculate the combined level (join of list level and all element levels) + let combinedLevel = lub(larg.lev, this.runtime.$t.pc); + for (const elem of arr) { + combinedLevel = lub(combinedLevel, elem.lev); + } + + // Create the tuple from the array + const tuple = mkTuple(arr); + + // Return the tuple with the combined security level + return this.runtime.ret(new LVal(tuple, combinedLevel)); + }, "listToTuple"); + }; +} diff --git a/rt/src/builtins/localarrays.mts b/rt/src/builtins/localarrays.mts index 373d9862..b475d8fc 100644 --- a/rt/src/builtins/localarrays.mts +++ b/rt/src/builtins/localarrays.mts @@ -1,70 +1,80 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import {lub, flowsTo} from '../Level.mjs' -import { assertIsNumber, assertIsNTuple, assertIsLevel, assertIsLocalObject } from '../Asserts.mjs' -import { LocalObject } from '../LocalObject.mjs'; -import { __unit } from '../UnitVal.mjs'; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import { lub, flowsTo } from "../Level.mjs"; +import { + assertIsNumber, + assertIsNTuple, + assertIsLevel, + assertIsLocalObject, +} from "../Asserts.mjs"; +import { LocalObject } from "../LocalObject.mjs"; +import { __unit } from "../UnitVal.mjs"; +export function BuiltinLocalArrays>( + Base: TBase, +) { + return class extends Base { + arrayCreate = mkBase((arg) => { + assertIsNTuple(arg, 3); + const lev = arg.val[0]; + const size = arg.val[1]; + const def = arg.val[2]; + assertIsNumber(size); + assertIsLevel(lev); + const l1 = lub(lev.lev, size.lev, this.runtime.$t.bl); + if (!flowsTo(l1, lev.val)) { + this.runtime.$t.threadError( + `The declared array level is too low:\n` + + `| array declared level is: ${lev.val.stringRep()}\n` + + `| the level of the information affecting the array creation: ${l1.stringRep()}`, + ); + } + const rawArray = new Array(size.val); + const obj = { size, lev: lev.val, rawArray, def }; + return this.runtime.ret(this.mkVal(new LocalObject(obj))); + }); + arrayGet = mkBase((arg) => { + assertIsNTuple(arg, 2); + const obj = arg.val[0]; + const idx = arg.val[1]; + assertIsNumber(idx); + const { lev, size, rawArray, def } = obj.val._value; + assertIsLocalObject(obj); + this.runtime.$t.raiseBlockingThreadLev(lub(idx.lev, size.lev)); -export function BuiltinLocalArrays > (Base:TBase) { - return class extends Base { - arrayCreate = mkBase((arg) => { - assertIsNTuple(arg, 3) - let lev = arg.val[0] - let size = arg.val[1] - let def = arg.val[2] - assertIsNumber (size) - assertIsLevel (lev) - let l1 = lub(lev.lev, size.lev, this.runtime.$t.bl) - if (!flowsTo (l1, lev.val)) { - this.runtime.$t.threadError (`The declared array level is too low:\n` + - `| array declared level is: ${lev.val.stringRep()}\n` + - `| the level of the information affecting the array creation: ${l1.stringRep()}`) - } - let rawArray = new Array (size.val) - let obj = { size, lev: lev.val, rawArray, def } - return this.runtime.ret (this.mkVal (new LocalObject(obj))) - }) + if (idx.val >= size.val) { + this.runtime.$t.threadError("Array index out of bounds"); + } + const v = rawArray[idx.val]; + const u = v || def; // return default if the array element is not set + return this.runtime.ret( + new LVal(u.val, lub(this.runtime.$t.bl, u.lev, lev, obj.lev)), + ); + }); - arrayGet = mkBase((arg) => { - assertIsNTuple(arg, 2) - let obj = arg.val[0] - let idx = arg.val[1] - assertIsNumber (idx) - let {lev, size, rawArray, def } = obj.val._value - assertIsLocalObject(obj) - this.runtime.$t.raiseBlockingThreadLev(lub(idx.lev, size.lev)) - - if (idx.val >= size.val) { - this.runtime.$t.threadError("Array index out of bounds") - } - let v = rawArray [idx.val] - let u = v || def // return default if the array element is not set - return this.runtime.ret ( new LVal (u.val, lub (this.runtime.$t.bl, u.lev, lev, obj.lev))) - }) - - arraySet = mkBase((arg) => { - assertIsNTuple(arg, 3) - let obj = arg.val[0] - let idx = arg.val[1] - let value = arg.val[2] - assertIsLocalObject(obj) - assertIsNumber (idx) - let {lev, size, rawArray} = obj.val._value - this.runtime.$t.raiseBlockingThreadLev(lub(size.lev,idx.lev,obj.lev)) - let l1 = lub(idx.lev, obj.lev, this.runtime.$t.bl) - if (!flowsTo (l1, lev)) { - this.runtime.$t.threadError ("Information influencing the write to this array is too high:\n" + - `| array declared level is ${lev.stringRep()}\n` + - `| the level of information affecting the write is ${l1.stringRep()}`) - } - if (idx.val >= size.val) { - this.runtime.$t.threadError("Array index out of bounds") - } - rawArray [idx.val] = value - this.runtime.ret (__unit) - }) - } + arraySet = mkBase((arg) => { + assertIsNTuple(arg, 3); + const obj = arg.val[0]; + const idx = arg.val[1]; + const value = arg.val[2]; + assertIsLocalObject(obj); + assertIsNumber(idx); + const { lev, size, rawArray } = obj.val._value; + this.runtime.$t.raiseBlockingThreadLev(lub(size.lev, idx.lev, obj.lev)); + const l1 = lub(idx.lev, obj.lev, this.runtime.$t.bl); + if (!flowsTo(l1, lev)) { + this.runtime.$t.threadError( + "Information influencing the write to this array is too high:\n" + + `| array declared level is ${lev.stringRep()}\n` + + `| the level of information affecting the write is ${l1.stringRep()}`, + ); + } + if (idx.val >= size.val) { + this.runtime.$t.threadError("Array index out of bounds"); + } + rawArray[idx.val] = value; + this.runtime.ret(__unit); + }); + }; } - diff --git a/rt/src/builtins/math.mts b/rt/src/builtins/math.mts index e59ae0b4..653d564f 100644 --- a/rt/src/builtins/math.mts +++ b/rt/src/builtins/math.mts @@ -1,37 +1,35 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import * as levels from '../Level.mjs' -import { assertIsUnit, assertIsNumber } from '../Asserts.mjs' - - -export function BuiltinMath > (Base:TBase) { - return class extends Base { - - random = mkBase((arg) => { - assertIsUnit(arg); - return this.runtime.ret(new LVal(Math.random(), levels.BOT, levels.BOT)) - }) - - ceil = mkBase((arg) => { - assertIsNumber(arg); - return this.runtime.ret(new LVal(Math.ceil(arg.val), arg.lev, arg.tlev)); - }) - - round = mkBase((arg) => { - assertIsNumber(arg); - return this.runtime.ret(new LVal(Math.round(arg.val), arg.lev, arg.tlev)); - }) - - floor = mkBase((arg) => { - assertIsNumber(arg); - return this.runtime.ret(new LVal(Math.floor(arg.val), arg.lev, arg.tlev)); - }) - - sqrt = mkBase((arg) => { - assertIsNumber(arg); - return this.runtime.ret(new LVal(Math.sqrt(arg.val), arg.lev, arg.tlev)); - }) - - - } -} \ No newline at end of file +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import * as levels from "../Level.mjs"; +import { assertIsUnit, assertIsNumber } from "../Asserts.mjs"; + +export function BuiltinMath>( + Base: TBase, +) { + return class extends Base { + random = mkBase((arg) => { + assertIsUnit(arg); + return this.runtime.ret(new LVal(Math.random(), levels.BOT, levels.BOT)); + }); + + ceil = mkBase((arg) => { + assertIsNumber(arg); + return this.runtime.ret(new LVal(Math.ceil(arg.val), arg.lev, arg.tlev)); + }); + + round = mkBase((arg) => { + assertIsNumber(arg); + return this.runtime.ret(new LVal(Math.round(arg.val), arg.lev, arg.tlev)); + }); + + floor = mkBase((arg) => { + assertIsNumber(arg); + return this.runtime.ret(new LVal(Math.floor(arg.val), arg.lev, arg.tlev)); + }); + + sqrt = mkBase((arg) => { + assertIsNumber(arg); + return this.runtime.ret(new LVal(Math.sqrt(arg.val), arg.lev, arg.tlev)); + }); + }; +} diff --git a/rt/src/builtins/mboxclear.mts b/rt/src/builtins/mboxclear.mts index b231564c..e4a2a77a 100644 --- a/rt/src/builtins/mboxclear.mts +++ b/rt/src/builtins/mboxclear.mts @@ -1,23 +1,25 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' -import { assertIsLevel, assertIsNTuple, assertIsCapability, assertIsAuthority } from '../Asserts.mjs' +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { + assertIsLevel, + assertIsNTuple, + assertIsCapability, + assertIsAuthority, +} from "../Asserts.mjs"; +export function BuiltinMboxClear>( + Base: TBase, +) { + return class extends Base { + raisembox = mkBase((arg) => { + assertIsLevel(arg); + return this.runtime.$t.raiseMboxClearance(arg); + }); -export function BuiltinMboxClear > (Base:TBase) { - return class extends Base { - - raisembox = mkBase((arg) => { - assertIsLevel(arg); - return this.runtime.$t.raiseMboxClearance(arg) - }) - - lowermbox = mkBase((arg) => { - assertIsNTuple(arg, 2); - assertIsCapability(arg.val[0]); - assertIsAuthority(arg.val[1]); - return this.runtime.$t.lowerMboxClearance(arg.val[0], arg.val[1]) - }) - - } + lowermbox = mkBase((arg) => { + assertIsNTuple(arg, 2); + assertIsCapability(arg.val[0]); + assertIsAuthority(arg.val[1]); + return this.runtime.$t.lowerMboxClearance(arg.val[0], arg.val[1]); + }); + }; } - - diff --git a/rt/src/builtins/mkuuid.mts b/rt/src/builtins/mkuuid.mts index 00e38d1f..f8d31ef7 100644 --- a/rt/src/builtins/mkuuid.mts +++ b/rt/src/builtins/mkuuid.mts @@ -1,13 +1,13 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' -import { assertIsUnit } from '../Asserts.mjs' +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { assertIsUnit } from "../Asserts.mjs"; - -export function BuiltinMkUuid > (Base:TBase) { - return class extends Base { - - mkuuid = mkBase((arg) => { - assertIsUnit(arg); - return this.runtime.ret(this.runtime.rt_mkuuid()); - }); - } +export function BuiltinMkUuid>( + Base: TBase, +) { + return class extends Base { + mkuuid = mkBase((arg) => { + assertIsUnit(arg); + return this.runtime.ret(this.runtime.rt_mkuuid()); + }); + }; } diff --git a/rt/src/builtins/monitor.mts b/rt/src/builtins/monitor.mts index 2daf5d4a..c9ca4130 100644 --- a/rt/src/builtins/monitor.mts +++ b/rt/src/builtins/monitor.mts @@ -1,35 +1,39 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' -import { assertNormalState, assertIsProcessId, assertIsString } from '../Asserts.mjs' -import { __unit } from '../UnitVal.mjs'; - -export function BuiltinMonitors > (Base:TBase) { - - return class extends Base { - monitorlocal = mkBase((arg) => { - assertNormalState("monitor"); - this.runtime.$t.raiseCurrentThreadPC(arg.lev); - assertIsProcessId(arg); - - let tid = arg.val; - - // 1. find the thread corresponding to that tid - - let t = this.runtime.__sched.__alive[tid.toString()]; - // 2. update the monitor state of that thread - - let r = this.runtime.rt_mkuuid(); - if (t) { - t.addMonitor(this.runtime.__sched.__currentThread.tid, r); - } - - return this.runtime.ret(r); - }) - - - demonitorlocal = mkBase((arg) => { - assertIsString(arg); - // mutates state; so we should be careful... - return this.runtime.ret(__unit); - }) - } -} \ No newline at end of file +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { + assertNormalState, + assertIsProcessId, + assertIsString, +} from "../Asserts.mjs"; +import { __unit } from "../UnitVal.mjs"; + +export function BuiltinMonitors>( + Base: TBase, +) { + return class extends Base { + monitorlocal = mkBase((arg) => { + assertNormalState("monitor"); + this.runtime.$t.raiseCurrentThreadPC(arg.lev); + assertIsProcessId(arg); + + const tid = arg.val; + + // 1. find the thread corresponding to that tid + + const t = this.runtime.__sched.__alive[tid.toString()]; + // 2. update the monitor state of that thread + + const r = this.runtime.rt_mkuuid(); + if (t) { + t.addMonitor(this.runtime.__sched.__currentThread.tid, r); + } + + return this.runtime.ret(r); + }); + + demonitorlocal = mkBase((arg) => { + assertIsString(arg); + // mutates state; so we should be careful... + return this.runtime.ret(__unit); + }); + }; +} diff --git a/rt/src/builtins/nodeutil.mts b/rt/src/builtins/nodeutil.mts index b78a3045..980f9632 100644 --- a/rt/src/builtins/nodeutil.mts +++ b/rt/src/builtins/nodeutil.mts @@ -1,23 +1,25 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import { assertIsProcessId } from '../Asserts.mjs' +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import { assertIsProcessId } from "../Asserts.mjs"; /** * Returns a string corresponding to the node identify * from a process */ -export function BuiltinNodeUtils>(Base: TBase) { - return class extends Base { - node = mkBase((arg) => { - assertIsProcessId(arg); - let data = arg.val; - let nodeId = data.node.nodeId; - if (nodeId == null) { - nodeId = "" - } - let v = new LVal(nodeId, arg.lev); - return this.runtime.ret(v); - }, "node") - } -} \ No newline at end of file +export function BuiltinNodeUtils>( + Base: TBase, +) { + return class extends Base { + node = mkBase((arg) => { + assertIsProcessId(arg); + const data = arg.val; + let nodeId = data.node.nodeId; + if (nodeId == null) { + nodeId = ""; + } + const v = new LVal(nodeId, arg.lev); + return this.runtime.ret(v); + }, "node"); + }; +} diff --git a/rt/src/builtins/persist.mts b/rt/src/builtins/persist.mts index d36676a1..db2e737a 100644 --- a/rt/src/builtins/persist.mts +++ b/rt/src/builtins/persist.mts @@ -1,41 +1,46 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import * as levels from '../Level.mjs' -import {deserialize} from '../deserialize.mjs' -import * as fs from 'node:fs'; -import { assertIsNTuple, assertIsRootAuthority, assertIsString } from '../Asserts.mjs' -import { __unit } from '../UnitVal.mjs'; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import * as levels from "../Level.mjs"; +import { deserialize } from "../deserialize.mjs"; +import * as fs from "node:fs"; +import { + assertIsNTuple, + assertIsRootAuthority, + assertIsString, +} from "../Asserts.mjs"; +import { __unit } from "../UnitVal.mjs"; -export function BuiltinPersist>(Base: TBase) { - return class extends Base { - save = mkBase((larg) => { - assertIsNTuple(larg, 3); - this.runtime.$t.raiseCurrentThreadPC(larg.lev); - let arg = larg.val; - let auth = arg[0]; - let file = arg[1].val; - let data = arg[2]; - assertIsRootAuthority(auth); - this.runtime.persist(data, "./out/saved." + file + ".persist.json") - return this.runtime.ret(__unit); - }, "save") +export function BuiltinPersist>( + Base: TBase, +) { + return class extends Base { + save = mkBase((larg) => { + assertIsNTuple(larg, 3); + this.runtime.$t.raiseCurrentThreadPC(larg.lev); + const arg = larg.val; + const auth = arg[0]; + const file = arg[1].val; + const data = arg[2]; + assertIsRootAuthority(auth); + this.runtime.persist(data, "./out/saved." + file + ".persist.json"); + return this.runtime.ret(__unit); + }, "save"); + restore = mkBase((arg) => { + assertIsString(arg); + const theThread = this.runtime.$t; + const file = arg; - restore = mkBase((arg) => { - assertIsString(arg) - let theThread = this.runtime.$t; - let file = arg; - - (async () => { - let jsonStr = await fs.promises.readFile("./out/saved." + file.val + ".persist.json", 'utf8'); - let data = await deserialize(levels.TOP, JSON.parse(jsonStr)); - theThread.returnSuspended(data); - this.runtime.__sched.scheduleThread(theThread); - this.runtime.__sched.resumeLoopAsync(); - - })() - }, "restore") - - } - -} \ No newline at end of file + (async () => { + const jsonStr = await fs.promises.readFile( + "./out/saved." + file.val + ".persist.json", + "utf8", + ); + const data = await deserialize(levels.TOP, JSON.parse(jsonStr)); + theThread.returnSuspended(data); + this.runtime.__sched.scheduleThread(theThread); + this.runtime.__sched.resumeLoopAsync(); + })(); + }, "restore"); + }; +} diff --git a/rt/src/builtins/pini.mts b/rt/src/builtins/pini.mts index 846b017e..e5a17741 100644 --- a/rt/src/builtins/pini.mts +++ b/rt/src/builtins/pini.mts @@ -1,77 +1,84 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' -import * as levels from '../Level.mjs' -import { assertNormalState, assertIsAuthority, assertIsCapability, assertIsNTuple, assertIsLevel } from '../Asserts.mjs' +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import * as levels from "../Level.mjs"; +import { + assertNormalState, + assertIsAuthority, + assertIsCapability, + assertIsNTuple, + assertIsLevel, +} from "../Asserts.mjs"; const flowsTo = levels.flowsTo; +export function BuiltinPini>( + Base: TBase, +) { + return class extends Base { + pcpush = mkBase((arg) => { + assertNormalState("pcpush"); + assertIsAuthority(arg); + return this.runtime.$t.pcpinipush(arg, "pcpush"); + }); -export function BuiltinPini > (Base:TBase) { - - - return class extends Base { + pcpop = mkBase((arg) => { + assertNormalState("pcpop"); + assertIsCapability(arg); + return this.runtime.$t.pcpop(arg); + }); - pcpush = mkBase((arg) => { - assertNormalState("pcpush") - assertIsAuthority(arg); - return this.runtime.$t.pcpinipush(arg, "pcpush"); - }) + pinipush = mkBase((arg) => { + // assertNormalState("pinipush"); + assertIsAuthority(arg); + return this.runtime.$t.pcpinipush(arg, "pinipush"); + }); + pinipushto = mkBase((arg) => { + assertIsNTuple(arg, 2); + assertIsAuthority(arg.val[0]); + assertIsLevel(arg.val[1]); + const is_lev_ok = flowsTo(this.runtime.$t.bl, arg.val[1].val); + if (!is_lev_ok) { + this.runtime.$t.threadError( + `level argument of pinipushto operation must flow to the current blocking level\n` + + `| the blocking level: ${this.runtime.$t.bl.stringRep()}\n` + + `| the level argument: ${arg.val[1].stringRep()}`, + ); + } else { + return this.runtime.$t.pcpinipush( + arg.val[0], + "pinipush", + arg.val[1].val, + ); + } + }); - pcpop = mkBase((arg) => { - assertNormalState("pcpop"); - assertIsCapability(arg); - return this.runtime.$t.pcpop(arg) - }) + pinipop = mkBase((arg) => { + // assertNormalState("pinipop"); + assertIsCapability(arg); + return this.runtime.$t.pinipop(arg); + }); + blockdecl = mkBase((arg) => { + assertIsAuthority(arg); + return this.runtime.$t.blockDeclassifyTo(arg); + }); - pinipush = mkBase((arg) => { - // assertNormalState("pinipush"); - assertIsAuthority(arg); - return this.runtime.$t.pcpinipush(arg, "pinipush"); - }) + blockdeclto = mkBase((arg) => { + assertIsNTuple(arg, 2); + assertIsAuthority(arg.val[0]); + assertIsLevel(arg.val[1]); + return this.runtime.$t.blockDeclassifyTo(arg.val[0], arg.val[1].val); + }); - pinipushto = mkBase((arg) => { - assertIsNTuple(arg, 2) - assertIsAuthority(arg.val[0]) - assertIsLevel(arg.val[1]) - let is_lev_ok = flowsTo(this.runtime.$t.bl, arg.val[1].val); - if (!is_lev_ok) { - this.runtime.$t.threadError(`level argument of pinipushto operation must flow to the current blocking level\n` + - `| the blocking level: ${this.runtime.$t.bl.stringRep()}\n` + - `| the level argument: ${arg.val[1].stringRep()}`) - } else { - return this.runtime.$t.pcpinipush(arg.val[0], "pinipush", arg.val[1].val); - } - }) + blockendorse = mkBase((arg) => { + assertIsAuthority(arg); + return this.runtime.$t.blockEndorseTo(arg); + }); - pinipop = mkBase((arg) => { - // assertNormalState("pinipop"); - assertIsCapability(arg) - return this.runtime.$t.pinipop(arg); - }) - - blockdecl = mkBase((arg) => { - assertIsAuthority(arg); - return this.runtime.$t.blockDeclassifyTo(arg) - }) - - blockdeclto = mkBase((arg) => { - assertIsNTuple(arg, 2); - assertIsAuthority(arg.val[0]) - assertIsLevel(arg.val[1]); - return this.runtime.$t.blockDeclassifyTo(arg.val[0], arg.val[1].val) - }) - - blockendorse = mkBase ((arg) => { - assertIsAuthority(arg); - return this.runtime.$t.blockEndorseTo(arg); - }) - - blockendorseto = mkBase((arg) => { - assertIsNTuple(arg, 2); - assertIsAuthority(arg.val[0]) - assertIsLevel(arg.val[1]); - return this.runtime.$t.blockEndorseTo(arg.val[0], arg.val[1].val) - }) - - } -} \ No newline at end of file + blockendorseto = mkBase((arg) => { + assertIsNTuple(arg, 2); + assertIsAuthority(arg.val[0]); + assertIsLevel(arg.val[1]); + return this.runtime.$t.blockEndorseTo(arg.val[0], arg.val[1].val); + }); + }; +} diff --git a/rt/src/builtins/raiseTrust.mts b/rt/src/builtins/raiseTrust.mts index 01ccb4aa..9d76dc15 100644 --- a/rt/src/builtins/raiseTrust.mts +++ b/rt/src/builtins/raiseTrust.mts @@ -1,51 +1,58 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LCopyVal } from '../Lval.mjs'; -import { assertIsNTuple, assertIsAuthority, assertIsLevel, assertNormalState, assertIsString, assertIsRootAuthority } from '../Asserts.mjs' -import { __unit } from '../UnitVal.mjs'; -import * as levels from '../Level.mjs' -import { __nodeManager } from '../NodeManager.mjs'; -import { nodeTrustLevel, _trustMap } from '../TrustManager.mjs'; - -const { lub, flowsTo } = levels - -export function BuiltinRaiseTrust>(Base: TBase) { - return class extends Base { - - raiseTrust = mkBase((arg) => { - assertNormalState("raise trust"); - assertIsNTuple(arg, 3) - - let argv = arg.val; - let data = argv[0]; - assertIsString(data); - - let authFrom = argv[1]; - assertIsAuthority(authFrom); - assertIsRootAuthority(authFrom); // AA; 2019-03-07: may be a bit pessimistic, but okay for now - let levTo = argv[2]; - assertIsLevel(levTo); - - let ok_to_raise = - flowsTo(this.runtime.$t.bl, levels.BOT); - if (!ok_to_raise) { - this.runtime.$t.threadError("Cannot raise trust level when the process is tainted\n" + - ` | blocking label: ${this.runtime.$t.bl.stringRep()}`) - } - - - //flowsTo (levTo.val, authFrom.val.authorityLevel); - // AA, 2018-10-20 : beware that no information flow is enforced here - // let l_meta = lub (__sched.pc, arg.lev, authFrom.lev, levTo.lev) - let l_raise = ok_to_raise ? levTo.val : levels.BOT; - let nodeId = __nodeManager.getNode(data.val).nodeId; - if (!nodeId) { - this.runtime.$t.threadError(`Undefined node identifier ${data.val}`) - } - // let nodeId = data.val; - let currentLevel = nodeTrustLevel(nodeId) - _trustMap[nodeId] = lub(currentLevel, l_raise); - return this.runtime.ret(__unit); - }, "raiseTrust") - - } -} \ No newline at end of file +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LCopyVal } from "../Lval.mjs"; +import { + assertIsNTuple, + assertIsAuthority, + assertIsLevel, + assertNormalState, + assertIsString, + assertIsRootAuthority, +} from "../Asserts.mjs"; +import { __unit } from "../UnitVal.mjs"; +import * as levels from "../Level.mjs"; +import { __nodeManager } from "../NodeManager.mjs"; +import { nodeTrustLevel, _trustMap } from "../TrustManager.mjs"; + +const { lub, flowsTo } = levels; + +export function BuiltinRaiseTrust>( + Base: TBase, +) { + return class extends Base { + raiseTrust = mkBase((arg) => { + assertNormalState("raise trust"); + assertIsNTuple(arg, 3); + + const argv = arg.val; + const data = argv[0]; + assertIsString(data); + + const authFrom = argv[1]; + assertIsAuthority(authFrom); + assertIsRootAuthority(authFrom); // AA; 2019-03-07: may be a bit pessimistic, but okay for now + const levTo = argv[2]; + assertIsLevel(levTo); + + const ok_to_raise = flowsTo(this.runtime.$t.bl, levels.BOT); + if (!ok_to_raise) { + this.runtime.$t.threadError( + "Cannot raise trust level when the process is tainted\n" + + ` | blocking label: ${this.runtime.$t.bl.stringRep()}`, + ); + } + + //flowsTo (levTo.val, authFrom.val.authorityLevel); + // AA, 2018-10-20 : beware that no information flow is enforced here + // let l_meta = lub (__sched.pc, arg.lev, authFrom.lev, levTo.lev) + const l_raise = ok_to_raise ? levTo.val : levels.BOT; + const nodeId = __nodeManager.getNode(data.val).nodeId; + if (!nodeId) { + this.runtime.$t.threadError(`Undefined node identifier ${data.val}`); + } + // let nodeId = data.val; + const currentLevel = nodeTrustLevel(nodeId); + _trustMap[nodeId] = lub(currentLevel, l_raise); + return this.runtime.ret(__unit); + }, "raiseTrust"); + }; +} diff --git a/rt/src/builtins/receive.mts b/rt/src/builtins/receive.mts index 0bbbc459..4fcbf6fb 100644 --- a/rt/src/builtins/receive.mts +++ b/rt/src/builtins/receive.mts @@ -1,58 +1,69 @@ -import { UserRuntimeZero, Constructor, mkBase, mkService } from './UserRuntimeZero.mjs' -import { assertNormalState, assertIsNTuple, assertIsLevel, assertIsList, assertIsAtom, assertIsNumber, assertIsUnit, assertIsFunction } from '../Asserts.mjs' -import { flowsTo, lub, glb, BOT } from '../Level.mjs'; -import { RuntimeInterface } from '../RuntimeInterface.mjs'; -import { ReceiveTaintAction } from '../ReceiveTaintAction.mjs'; -import { LVal } from '../Lval.mjs'; -import { mkTuple } from '../ValuesUtil.mjs'; -import { __unit } from '../UnitVal.mjs'; -import SandboxStatus from '../SandboxStatus.mjs'; -import { Thread } from '../Thread.mjs'; -import { debug } from 'console'; - - +import { + UserRuntimeZero, + Constructor, + mkBase, + mkService, +} from "./UserRuntimeZero.mjs"; +import { + assertNormalState, + assertIsNTuple, + assertIsLevel, + assertIsList, + assertIsAtom, + assertIsNumber, + assertIsUnit, + assertIsFunction, +} from "../Asserts.mjs"; +import { flowsTo, lub, glb, BOT } from "../Level.mjs"; +import { RuntimeInterface } from "../RuntimeInterface.mjs"; +import { ReceiveTaintAction } from "../ReceiveTaintAction.mjs"; +import { LVal } from "../Lval.mjs"; +import { mkTuple } from "../ValuesUtil.mjs"; +import { __unit } from "../UnitVal.mjs"; +import SandboxStatus from "../SandboxStatus.mjs"; +import { Thread } from "../Thread.mjs"; +import { debug } from "console"; /* -// this function must only be called from -// one of the checked functions +// this function must only be called from +// one of the checked functions function _receiveFromMailbox ($r:RuntimeInterface, lowb, highb, handlers) { let mclear = $r.$t.mailbox.mclear - - let is_sufficient_clearance = + + let is_sufficient_clearance = flowsTo( lub (highb.val, $r.$t.pc) , lub (lowb.val, mclear.boost_level )) - if (!is_sufficient_clearance) { - let errorMessage = + if (!is_sufficient_clearance) { + let errorMessage = "Not enough mailbox clearance for this receive\n" + - ` | receive lower bound: ${lowb.val.stringRep()}\n` + + ` | receive lower bound: ${lowb.val.stringRep()}\n` + ` | receive upper bound: ${highb.val.stringRep()}\n` + ` | pc level : ${$r.$t.pc.stringRep()}\n` + - ` | mailbox clearance : ${mclear.boost_level.stringRep()}` + ` | mailbox clearance : ${mclear.boost_level.stringRep()}` $r.$t.threadError (errorMessage); - } - + } + let is_clearance_a_leak = flowsTo( mclear.pc_at_creation, glb ($r.$t.pc, lowb.val)) if (!is_clearance_a_leak) { - let errorMessage = + let errorMessage = "PC level at the time of raising the mailbox clearance is too sensitive for this receive\n" + - ` | receive lower bound: ${lowb.val.stringRep()}\n` + - ` | pc level at the time of receive: ${$r.$t.pc.stringRep()}\n` + - ` | pc level at the time of raise: ${mclear.pc_at_creation.stringRep()}` // we need better terminology for these + ` | receive lower bound: ${lowb.val.stringRep()}\n` + + ` | pc level at the time of receive: ${$r.$t.pc.stringRep()}\n` + + ` | pc level at the time of raise: ${mclear.pc_at_creation.stringRep()}` // we need better terminology for these $r.$t.threadError (errorMessage); } return $r.__mbox.rcv(lowb.val, highb.val, handlers, mclear.boost_level) - + } */ - -/** Receiving functionality; 2020-02-12; AA +/** Receiving functionality; 2020-02-12; AA * - * Observe that we have three receive functions. + * Observe that we have three receive functions. * * 1. The most general one is called `rcv` and it takes a 3-tuple of the form * (low_bound_lev, high_bound_lev handlers), and performs an @@ -61,7 +72,7 @@ function _receiveFromMailbox ($r:RuntimeInterface, lowb, highb, handlers) { * that leaks information, it is necessary that the mailbox has sufficient * clearance. The implementation of this function checks that the * clearance is sufficient; this check is perfomed similaly to how - * declassification checks are performed. + * declassification checks are performed. * * 2. Receive on a point interval, `rcvp`. A sugar for (1) * @@ -70,141 +81,163 @@ function _receiveFromMailbox ($r:RuntimeInterface, lowb, highb, handlers) { * examples. * * - */ - - - - -export function BuiltinReceive>(Base: TBase) { - return class extends Base { - peek = mkBase (arg => { - assertIsNTuple(arg, 3) - assertIsNumber(arg.val[0]) - assertIsLevel (arg.val[1]) - assertIsLevel (arg.val[2]) - let i = arg.val[0] - let lowb = arg.val[1] - let highb = arg.val[2] - let mclear = this.runtime.$t.mailbox.mclear - return this.runtime.__mbox.peek ( - lub (this.runtime.$t.pc, i.lev, lowb.lev, highb.lev, highb.val, mclear.boost_level), - i.val, lowb.val, highb.val ) - }) - - consume = mkBase (arg => { - assertIsNTuple(arg, 3) - assertIsNumber(arg.val[0]) - assertIsLevel (arg.val[1]) - assertIsLevel (arg.val[2]) - let i = arg.val[0] - let lowb = arg.val[1] - let highb = arg.val[2] - - let $r = this.runtime - let mclear = $r.$t.mailbox.mclear - let is_sufficient_clearance = - flowsTo( lub (highb.val, $r.$t.pc) - , lub (lowb.val, mclear.boost_level )) - - if (!is_sufficient_clearance) { - let errorMessage = - "Not enough mailbox clearance for this receive\n" + - ` | receive lower bound: ${lowb.val.stringRep()}\n` + - ` | receive upper bound: ${highb.val.stringRep()}\n` + - ` | pc level : ${$r.$t.pc.stringRep()}\n` + - ` | mailbox clearance : ${mclear.boost_level.stringRep()}` - $r.$t.threadError (errorMessage); - } - - let is_clearance_a_leak = flowsTo( mclear.pc_at_creation, glb ($r.$t.pc, lowb.val)) - - if (!is_clearance_a_leak) { - let errorMessage = - "PC level at the time of raising the mailbox clearance is too sensitive for this receive\n" + - ` | receive lower bound: ${lowb.val.stringRep()}\n` + - ` | pc level at the time of receive: ${$r.$t.pc.stringRep()}\n` + - ` | pc level at the time of raise: ${mclear.pc_at_creation.stringRep()}` // we need better terminology for these - $r.$t.threadError (errorMessage); - } - - let consume_l = lub (this.runtime.$t.pc, i.lev, lowb.lev, highb.lev, highb.val, mclear.boost_level) - return this.runtime.__mbox.consume ( consume_l, i.val, lowb.val, highb.val ) - }) - - _blockThread = mkBase ((arg) => { - assertIsUnit(arg) - this.runtime.__sched.blockThread(this.runtime.__sched.__currentThread); - return null; - }) - - _pc = mkBase ((arg) => { - assertIsUnit (arg) - return this.runtime.ret ( - new LVal (this.runtime.$t.pc, this.runtime.$t.pc, BOT)) - }) - - - guard = mkBase (arg => { - assertIsNTuple(arg, 3) - let f = arg.val[0] - let taintLimitArg = arg.val[1] - let def = arg.val[2] - assertIsFunction(f) - assertIsLevel(taintLimitArg) - let theThread = this.runtime.$t - theThread.raiseCurrentThreadPC(lub (f.lev, taintLimitArg.lev, taintLimitArg.val)) - - let tntLim = theThread.bl - let guard_sp : number = null - theThread.handlerState = new SandboxStatus.INHANDLER ( - () => { // trapper - invoked upon side-effects and guard check failure - theThread._sp = guard_sp - theThread.invalidateSparseBit() - theThread.pc = taintLimitArg.val - theThread.bl = taintLimitArg.val - theThread.handlerState = new SandboxStatus.NORMAL () - return theThread.returnImmediateLValue(def) - }, - theThread.pc, - () => { // guard checker -- called by the scheduler on context switches - if (!flowsTo(theThread.bl, tntLim)) { - theThread.threadError ("guard violation") - } - } - ) - - let guardFrame : any = () => { - let arg = theThread.arg_as_lval - let l_guard = lub (arg.lev, theThread.bl) - if (flowsTo(l_guard, tntLim)) { - theThread.invalidateSparseBit() - theThread.handlerState = new SandboxStatus.NORMAL () - return theThread.returnImmediate() - } else { - theThread.threadError ("guard violation") - } + */ + +export function BuiltinReceive>( + Base: TBase, +) { + return class extends Base { + peek = mkBase((arg) => { + assertIsNTuple(arg, 3); + assertIsNumber(arg.val[0]); + assertIsLevel(arg.val[1]); + assertIsLevel(arg.val[2]); + const i = arg.val[0]; + const lowb = arg.val[1]; + const highb = arg.val[2]; + const mclear = this.runtime.$t.mailbox.mclear; + return this.runtime.__mbox.peek( + lub( + this.runtime.$t.pc, + i.lev, + lowb.lev, + highb.lev, + highb.val, + mclear.boost_level, + ), + i.val, + lowb.val, + highb.val, + ); + }); + + consume = mkBase((arg) => { + assertIsNTuple(arg, 3); + assertIsNumber(arg.val[0]); + assertIsLevel(arg.val[1]); + assertIsLevel(arg.val[2]); + const i = arg.val[0]; + const lowb = arg.val[1]; + const highb = arg.val[2]; + + const $r = this.runtime; + const mclear = $r.$t.mailbox.mclear; + const is_sufficient_clearance = flowsTo( + lub(highb.val, $r.$t.pc), + lub(lowb.val, mclear.boost_level), + ); + + if (!is_sufficient_clearance) { + const errorMessage = + "Not enough mailbox clearance for this receive\n" + + ` | receive lower bound: ${lowb.val.stringRep()}\n` + + ` | receive upper bound: ${highb.val.stringRep()}\n` + + ` | pc level : ${$r.$t.pc.stringRep()}\n` + + ` | mailbox clearance : ${mclear.boost_level.stringRep()}`; + $r.$t.threadError(errorMessage); + } + + const is_clearance_a_leak = flowsTo( + mclear.pc_at_creation, + glb($r.$t.pc, lowb.val), + ); + + if (!is_clearance_a_leak) { + const errorMessage = + "PC level at the time of raising the mailbox clearance is too sensitive for this receive\n" + + ` | receive lower bound: ${lowb.val.stringRep()}\n` + + ` | pc level at the time of receive: ${$r.$t.pc.stringRep()}\n` + + ` | pc level at the time of raise: ${mclear.pc_at_creation.stringRep()}`; // we need better terminology for these + $r.$t.threadError(errorMessage); + } + + const consume_l = lub( + this.runtime.$t.pc, + i.lev, + lowb.lev, + highb.lev, + highb.val, + mclear.boost_level, + ); + return this.runtime.__mbox.consume(consume_l, i.val, lowb.val, highb.val); + }); + + _blockThread = mkBase((arg) => { + assertIsUnit(arg); + this.runtime.__sched.blockThread(this.runtime.__sched.__currentThread); + return null; + }); + + _pc = mkBase((arg) => { + assertIsUnit(arg); + return this.runtime.ret( + new LVal(this.runtime.$t.pc, this.runtime.$t.pc, BOT), + ); + }); + + guard = mkBase((arg) => { + assertIsNTuple(arg, 3); + const f = arg.val[0]; + const taintLimitArg = arg.val[1]; + const def = arg.val[2]; + assertIsFunction(f); + assertIsLevel(taintLimitArg); + const theThread = this.runtime.$t; + theThread.raiseCurrentThreadPC( + lub(f.lev, taintLimitArg.lev, taintLimitArg.val), + ); + + const tntLim = theThread.bl; + let guard_sp: number = null; + theThread.handlerState = new SandboxStatus.INHANDLER( + () => { + // trapper - invoked upon side-effects and guard check failure + theThread._sp = guard_sp; + theThread.invalidateSparseBit(); + theThread.pc = taintLimitArg.val; + theThread.bl = taintLimitArg.val; + theThread.handlerState = new SandboxStatus.NORMAL(); + return theThread.returnImmediateLValue(def); + }, + theThread.pc, + () => { + // guard checker -- called by the scheduler on context switches + if (!flowsTo(theThread.bl, tntLim)) { + theThread.threadError("guard violation"); } - - guardFrame.debugname = "" - theThread.pushFrame ( guardFrame) - guard_sp = theThread._sp - return theThread.tailCall (f.val, __unit) - - }) - - receive = mkService ( () => { - assertNormalState("receive"); - return this.runtime.$service.receive() - }, "receive") - rcvp = mkService ( () => { - assertNormalState ("rcvp") - return this.runtime.$service.rcvp() - }, "rcvp") - - rcv = mkService ( () => { - assertNormalState ("rcv") - return this.runtime.$service.rcv() - }, "rcv") - - } + }, + ); + + const guardFrame: any = () => { + const arg = theThread.arg_as_lval; + const l_guard = lub(arg.lev, theThread.bl); + if (flowsTo(l_guard, tntLim)) { + theThread.invalidateSparseBit(); + theThread.handlerState = new SandboxStatus.NORMAL(); + return theThread.returnImmediate(); + } else { + theThread.threadError("guard violation"); + } + }; + + guardFrame.debugname = ""; + theThread.pushFrame(guardFrame); + guard_sp = theThread._sp; + return theThread.tailCall(f.val, __unit); + }); + + receive = mkService(() => { + assertNormalState("receive"); + return this.runtime.$service.receive(); + }, "receive"); + rcvp = mkService(() => { + assertNormalState("rcvp"); + return this.runtime.$service.rcvp(); + }, "rcvp"); + + rcv = mkService(() => { + assertNormalState("rcv"); + return this.runtime.$service.rcv(); + }, "rcv"); + }; } diff --git a/rt/src/builtins/recordReflection.mts b/rt/src/builtins/recordReflection.mts index fc11395e..59c3fac6 100644 --- a/rt/src/builtins/recordReflection.mts +++ b/rt/src/builtins/recordReflection.mts @@ -1,25 +1,36 @@ -'use strict' -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import { assertIsNTuple, assertIsRecord, assertIsString, assertIsUnit, assertNormalState } from '../Asserts.mjs' +"use strict"; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import { + assertIsNTuple, + assertIsRecord, + assertIsString, + assertIsUnit, + assertNormalState, +} from "../Asserts.mjs"; import { Record } from "../Record.mjs"; -import { lub } from '../Level.mjs'; -import { __unit } from '../UnitVal.mjs'; +import { lub } from "../Level.mjs"; +import { __unit } from "../UnitVal.mjs"; -export function BuiltinRecordReflection>(Base: TBase) { - return class extends Base { - recordExtend = mkBase((larg) => { - assertIsNTuple(larg, 3); - let arg = larg.val; - assertIsRecord(arg[0]); - let raw_rec = arg[0].val; - assertIsString(arg[1]); - let new_field_str = arg[1]; - let raw_newfield = new_field_str.val; - let v = new LVal (arg[2].val, lub (arg[2].lev , new_field_str.lev)); - let new_raw_rec = Record.mkWithRecord (raw_rec, [[raw_newfield, v ]]); - let ret_val = new LVal (new_raw_rec, lub (this.runtime.$t.pc, larg.lev, new_field_str.lev)); - return this.runtime.ret(ret_val); - }) - } +export function BuiltinRecordReflection< + TBase extends Constructor, +>(Base: TBase) { + return class extends Base { + recordExtend = mkBase((larg) => { + assertIsNTuple(larg, 3); + const arg = larg.val; + assertIsRecord(arg[0]); + const raw_rec = arg[0].val; + assertIsString(arg[1]); + const new_field_str = arg[1]; + const raw_newfield = new_field_str.val; + const v = new LVal(arg[2].val, lub(arg[2].lev, new_field_str.lev)); + const new_raw_rec = Record.mkWithRecord(raw_rec, [[raw_newfield, v]]); + const ret_val = new LVal( + new_raw_rec, + lub(this.runtime.$t.pc, larg.lev, new_field_str.lev), + ); + return this.runtime.ret(ret_val); + }); + }; } diff --git a/rt/src/builtins/runtimeassert.mts b/rt/src/builtins/runtimeassert.mts index a9c3d0d7..3d1c3768 100644 --- a/rt/src/builtins/runtimeassert.mts +++ b/rt/src/builtins/runtimeassert.mts @@ -1,20 +1,32 @@ -import { rawAssertIsFunction, rawAssertIsBoolean, rawAssertIsList, rawAssertIsNumber, rawAssertIsRecord, rawAssertIsString, rawAssertIsTuple, rawAssertPairsAreStringsOrNumbers, rawAssertIsLevel, rawAssertTupleLengthGreaterThan, rawAssertRecordHasField } from '../Asserts.mjs' -import {UserRuntimeZero, Constructor } from './UserRuntimeZero.mjs' +import { + rawAssertIsFunction, + rawAssertIsBoolean, + rawAssertIsList, + rawAssertIsNumber, + rawAssertIsRecord, + rawAssertIsString, + rawAssertIsTuple, + rawAssertPairsAreStringsOrNumbers, + rawAssertIsLevel, + rawAssertTupleLengthGreaterThan, + rawAssertRecordHasField, +} from "../Asserts.mjs"; +import { UserRuntimeZero, Constructor } from "./UserRuntimeZero.mjs"; - -export function RuntimeAssert > (Base:TBase) { - return class extends Base { - - rawAssertIsNumber = rawAssertIsNumber - rawAssertIsBoolean = rawAssertIsBoolean - rawAssertIsString = rawAssertIsString - rawAssertIsList = rawAssertIsList - rawAssertIsFunction = rawAssertIsFunction - rawAssertIsRecord = rawAssertIsRecord - rawAssertIsTuple = rawAssertIsTuple - rawAssertTupleLengthGreaterThan = rawAssertTupleLengthGreaterThan - rawAssertRecordHasField = rawAssertRecordHasField - rawAssertPairsAreStringsOrNumbers = rawAssertPairsAreStringsOrNumbers - rawAssertIsLevel = rawAssertIsLevel - } +export function RuntimeAssert>( + Base: TBase, +) { + return class extends Base { + rawAssertIsNumber = rawAssertIsNumber; + rawAssertIsBoolean = rawAssertIsBoolean; + rawAssertIsString = rawAssertIsString; + rawAssertIsList = rawAssertIsList; + rawAssertIsFunction = rawAssertIsFunction; + rawAssertIsRecord = rawAssertIsRecord; + rawAssertIsTuple = rawAssertIsTuple; + rawAssertTupleLengthGreaterThan = rawAssertTupleLengthGreaterThan; + rawAssertRecordHasField = rawAssertRecordHasField; + rawAssertPairsAreStringsOrNumbers = rawAssertPairsAreStringsOrNumbers; + rawAssertIsLevel = rawAssertIsLevel; + }; } diff --git a/rt/src/builtins/sandbox.mts b/rt/src/builtins/sandbox.mts index 5c52f2d7..9ee96005 100644 --- a/rt/src/builtins/sandbox.mts +++ b/rt/src/builtins/sandbox.mts @@ -1,156 +1,154 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LVal, LValCopyAt } from '../Lval.mjs'; -import { assertNormalState, assertIsNTuple, assertIsNumber, assertIsFunction } from '../Asserts.mjs' -import { __unit } from '../UnitVal.mjs'; -import { getCliArgs, TroupeCliArg } from '../TroupeCliArgs.mjs'; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal, LValCopyAt } from "../Lval.mjs"; +import { + assertNormalState, + assertIsNTuple, + assertIsNumber, + assertIsFunction, +} from "../Asserts.mjs"; +import { __unit } from "../UnitVal.mjs"; +import { getCliArgs, TroupeCliArg } from "../TroupeCliArgs.mjs"; const argv = getCliArgs(); -let logLevel = argv[TroupeCliArg.DebugSandbox]? 'debug': 'info' -import { mkLogger } from '../logger.mjs' -const logger = mkLogger('MBX', logLevel); -const debug = x => logger.debug(x) +const logLevel = argv[TroupeCliArg.DebugSandbox] ? "debug" : "info"; +import { mkLogger } from "../logger.mjs"; +const logger = mkLogger("MBX", logLevel); +const debug = (x) => logger.debug(x); -import SandboxStatus from '../SandboxStatus.mjs' -import { mkTuple } from '../ValuesUtil.mjs'; -import { CALLSIZE, RETOFFSET, Thread } from '../Thread.mjs'; -import { RawClosure, SandboxResumption } from '../RawClosure.mjs'; -import { RuntimeInterface } from '../RuntimeInterface.mjs'; +import SandboxStatus from "../SandboxStatus.mjs"; +import { mkTuple } from "../ValuesUtil.mjs"; +import { CALLSIZE, RETOFFSET, Thread } from "../Thread.mjs"; +import { RawClosure, SandboxResumption } from "../RawClosure.mjs"; +import { RuntimeInterface } from "../RuntimeInterface.mjs"; function rt_raisedToLev(x, y) { - return new LValCopyAt(x, y) + return new LValCopyAt(x, y); } - - -function setupSandbox($r:RuntimeInterface, delay, resumeState = null) { - let theThread : Thread = $r.$t; - let done = false; - let trapperInvoked = false; - let retVal = null; - $r.$t.raiseCurrentThreadPC(delay.lev); - - let threadState = theThread.exportState() - let guard = () => { - retVal = $r.$t.arg_as_lval - done = true; - } - - if (resumeState) { - theThread.importState(resumeState) - theThread.callStack[CALLSIZE - RETOFFSET] = guard - } else { - theThread.resetStackForSandboxing() - $r.$t.pushFrame(guard); - } - - - - - - let trapper = () => { - trapperInvoked = true; - retVal = __unit; - } - - theThread.handlerState = new SandboxStatus.INSANDBOX(trapper, theThread.pc); - - - - function mk_tupleVal(x) { - return theThread.mkVal(mkTuple(x)); +function setupSandbox($r: RuntimeInterface, delay, resumeState = null) { + const theThread: Thread = $r.$t; + let done = false; + let trapperInvoked = false; + let retVal = null; + $r.$t.raiseCurrentThreadPC(delay.lev); + + const threadState = theThread.exportState(); + const guard = () => { + retVal = $r.$t.arg_as_lval; + done = true; + }; + + if (resumeState) { + theThread.importState(resumeState); + theThread.callStack[CALLSIZE - RETOFFSET] = guard; + } else { + theThread.resetStackForSandboxing(); + $r.$t.pushFrame(guard); + } + + const trapper = () => { + trapperInvoked = true; + retVal = __unit; + }; + + theThread.handlerState = new SandboxStatus.INSANDBOX(trapper, theThread.pc); + + function mk_tupleVal(x) { + return theThread.mkVal(mkTuple(x)); + } + + function ok(x, l) { + debug(`calling ok ${x.stringRep()}`); + const statusOk = $r.$t.mkValWithLev(0, l); + const y = rt_raisedToLev(x, l); + return mk_tupleVal([statusOk, y]); + } + + setTimeout(() => { + const sandboxState = theThread.exportState(); + theThread.handlerState = new SandboxStatus.NORMAL(); + const resultLabel = $r.$t.bl; + // Restore the state back to what it was before starting the sandboxing + theThread.importState(threadState); + function bad(x, l) { + const statusBad = $r.$t.mkValWithLev(1, l); + const y = rt_raisedToLev(x, l); + return mk_tupleVal([statusBad, y]); } - - function ok(x, l) { - debug (`calling ok ${x.stringRep()}`) - let statusOk = $r.$t.mkValWithLev(0, l); - let y = rt_raisedToLev(x, l); - return mk_tupleVal([statusOk, y]); + function resumeKont(sleepTimeout = null) { + const statusBad = $r.$t.mkValWithLev(2, resultLabel); + // console.log (sandboxState.callStack[sandboxState.callStack.length - 3].toString(), sandboxState.next.toString()) + const f = () => { + const thread = $r.$t; + const newdelay = thread.arg_as_lval; // new LVal (arg_val, arg_lev, arg_tlev); + assertIsNumber(newdelay); + setupSandbox($r, newdelay, sandboxState); + // console.log ("sandbox setup") + if (sleepTimeout) { + sleepTimeout.resume(thread); + return null; + } else { + return $r.$t.next; + } + }; + const kont = new LVal(SandboxResumption(f), resultLabel); + return mk_tupleVal([statusBad, kont]); } - - setTimeout(() => { - let sandboxState = theThread.exportState() - theThread.handlerState = new SandboxStatus.NORMAL(); - let resultLabel = $r.$t.bl; - // Restore the state back to what it was before starting the sandboxing - theThread.importState(threadState); - function bad(x, l) { - let statusBad = $r.$t.mkValWithLev(1, l); - let y = rt_raisedToLev(x, l); - return mk_tupleVal([statusBad, y]) - } - function resumeKont(sleepTimeout = null) { - let statusBad = $r.$t.mkValWithLev(2, resultLabel); - // console.log (sandboxState.callStack[sandboxState.callStack.length - 3].toString(), sandboxState.next.toString()) - let f = () => { - let thread = $r.$t; - let newdelay = thread.arg_as_lval // new LVal (arg_val, arg_lev, arg_tlev); - assertIsNumber(newdelay); - setupSandbox($r, newdelay, sandboxState) - // console.log ("sandbox setup") - if (sleepTimeout) { - sleepTimeout.resume(thread); - return null; - } else { - return $r.$t.next; - } - } - let kont = new LVal(SandboxResumption(f), resultLabel) - return mk_tupleVal([statusBad, kont]) + // __sched.raiseCurrentThreadPCToBlockingLev(); + + // 2019-01-31: AA; obs: this is subtle + + // we check whether the thread is no longer scheduled + if (done || trapperInvoked || theThread.sleeping) { + if (done) { + theThread.returnSuspended(ok(retVal, resultLabel)); + } else { + if (theThread.sleeping) { + // console.log ("Thread is sleeping") + const _sleepTO = theThread.sleepTimeout; + theThread.sleepTimeout = null; + _sleepTO.pause(); + theThread.returnSuspended(resumeKont(_sleepTO)); + } else if (trapperInvoked) { + theThread.returnSuspended(bad(__unit, resultLabel)); } + } - // __sched.raiseCurrentThreadPCToBlockingLev(); - - // 2019-01-31: AA; obs: this is subtle - - // we check whether the thread is no longer scheduled - if (done || trapperInvoked || theThread.sleeping) { - if (done) { - theThread.returnSuspended(ok(retVal, resultLabel)); - } else { - if (theThread.sleeping) { - // console.log ("Thread is sleeping") - let _sleepTO = theThread.sleepTimeout - theThread.sleepTimeout = null ; - _sleepTO.pause() - theThread.returnSuspended(resumeKont(_sleepTO)) - } else if (trapperInvoked) { - theThread.returnSuspended(bad(__unit, resultLabel)); - } - } - - // because the thread has finished, we need - // to push it back into the thread pool - - $r.__sched.scheduleThread(theThread); - $r.__sched.resumeLoopAsync(); + // because the thread has finished, we need + // to push it back into the thread pool - } else { - theThread.killCounter++; - // the thread is alive and is somewhere in the scheduler queue, so - // we just change its return kont - theThread.returnSuspended(resumeKont()) - } - }, delay.val) + $r.__sched.scheduleThread(theThread); + $r.__sched.resumeLoopAsync(); + } else { + theThread.killCounter++; + // the thread is alive and is somewhere in the scheduler queue, so + // we just change its return kont + theThread.returnSuspended(resumeKont()); + } + }, delay.val); } - -export function BuiltinSandbox>(Base: TBase) { - return class extends Base { - sandbox = mkBase((arg) => { - // return new Error ("not ported to new raw representation") - // /* - debug(`calling sandbox`) - assertIsNTuple(arg, 2); - assertIsNumber(arg.val[0]) - assertIsFunction(arg.val[1]) - let delay = arg.val[0]; - setupSandbox(this.runtime, delay) - return this.runtime.$t.tailCall ( arg.val[1].val, __unit) - }, - - // this.tailcall(arg.val[1], __unit); - // */ - "sandbox") - } -} \ No newline at end of file +export function BuiltinSandbox>( + Base: TBase, +) { + return class extends Base { + sandbox = mkBase( + (arg) => { + // return new Error ("not ported to new raw representation") + // /* + debug(`calling sandbox`); + assertIsNTuple(arg, 2); + assertIsNumber(arg.val[0]); + assertIsFunction(arg.val[1]); + const delay = arg.val[0]; + setupSandbox(this.runtime, delay); + return this.runtime.$t.tailCall(arg.val[1].val, __unit); + }, + + // this.tailcall(arg.val[1], __unit); + // */ + "sandbox", + ); + }; +} diff --git a/rt/src/builtins/self.mts b/rt/src/builtins/self.mts index 6b098337..a8241f68 100644 --- a/rt/src/builtins/self.mts +++ b/rt/src/builtins/self.mts @@ -1,14 +1,16 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; /** * Returns a string corresponding to the node identify * from a process */ -export function BuiltinSelf>(Base: TBase) { - return class extends Base { - self = mkBase((arg) => { - return this.runtime.ret(this.runtime.__sched.__currentThread.tid); - }, "self"); - } -} \ No newline at end of file +export function BuiltinSelf>( + Base: TBase, +) { + return class extends Base { + self = mkBase((arg) => { + return this.runtime.ret(this.runtime.__sched.__currentThread.tid); + }, "self"); + }; +} diff --git a/rt/src/builtins/send.mts b/rt/src/builtins/send.mts index 699a4169..1b302ee9 100644 --- a/rt/src/builtins/send.mts +++ b/rt/src/builtins/send.mts @@ -1,29 +1,33 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { assertNormalState, assertIsNTuple, assertIsProcessId } from '../Asserts.mjs' +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { + assertNormalState, + assertIsNTuple, + assertIsProcessId, +} from "../Asserts.mjs"; +export function BuiltinSend>( + Base: TBase, +) { + return class extends Base { + send = mkBase((larg) => { + const $r = this.runtime; + $r.$t.raiseCurrentThreadPCToBlockingLev(); + assertNormalState("send"); + $r.$t.raiseCurrentThreadPC(larg.lev); + assertIsNTuple(larg, 2); + assertIsProcessId(larg.val[0]); + const arg = larg.val; + // we need to check whether the recipient process is local + // if yes, then we just proceed by adding the message to the + // local mailbox; otherwise we need to proceed to serialization + // external call. -export function BuiltinSend>(Base: TBase) { - return class extends Base { - send = mkBase((larg) => { - let $r = this.runtime - $r.$t.raiseCurrentThreadPCToBlockingLev(); - assertNormalState("send") - $r.$t.raiseCurrentThreadPC(larg.lev); - assertIsNTuple(larg, 2); - assertIsProcessId(larg.val[0]); - let arg = larg.val; - // we need to check whether the recipient process is local - // if yes, then we just proceed by adding the message to the - // local mailbox; otherwise we need to proceed to serialization - // external call. + const lRecipientPid = arg[0]; + // debug ("* rt rt_send *", lRecipientPid); + $r.$t.raiseCurrentThreadPC(lRecipientPid.lev); // this feels a bit odd. + const message = arg[1]; - let lRecipientPid = arg[0]; - // debug ("* rt rt_send *", lRecipientPid); - $r.$t.raiseCurrentThreadPC(lRecipientPid.lev); // this feels a bit odd. - let message = arg[1]; - - return $r.sendMessageNoChecks(lRecipientPid, message) - - }, "send"); - } -} \ No newline at end of file + return $r.sendMessageNoChecks(lRecipientPid, message); + }, "send"); + }; +} diff --git a/rt/src/builtins/service.mts b/rt/src/builtins/service.mts index 1ce4a700..9726bcf2 100644 --- a/rt/src/builtins/service.mts +++ b/rt/src/builtins/service.mts @@ -1,7 +1,17 @@ -import {UserRuntimeZero, Constructor, mkBase, mkService} from './UserRuntimeZero.mjs' -import { __unit } from '../UnitVal.mjs' -export function BuiltinService > (Base:TBase) { - return class extends Base { - _servicetest = mkService(() => this.runtime.$service.servicetest(),"servicetest") - } -} \ No newline at end of file +import { + UserRuntimeZero, + Constructor, + mkBase, + mkService, +} from "./UserRuntimeZero.mjs"; +import { __unit } from "../UnitVal.mjs"; +export function BuiltinService>( + Base: TBase, +) { + return class extends Base { + _servicetest = mkService( + () => this.runtime.$service.servicetest(), + "servicetest", + ); + }; +} diff --git a/rt/src/builtins/sleep.mts b/rt/src/builtins/sleep.mts index 0e29825d..d52c863e 100644 --- a/rt/src/builtins/sleep.mts +++ b/rt/src/builtins/sleep.mts @@ -1,17 +1,19 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' -import { assertIsNumber } from '../Asserts.mjs' -import { __unit } from '../UnitVal.mjs' -import { SleepTimeout } from '../Thread.mjs' -export function BuiltinSleep > (Base:TBase) { - return class extends Base { - sleep = mkBase((arg) => { - let $r = this.runtime - assertIsNumber (arg); - let delay = arg.val; - let theThread = $r.$t; - theThread.raiseBlockingThreadLev(arg.lev); - theThread.sleepTimeout = new SleepTimeout ( delay, theThread ) - return null; - }, "sleep") - } -} \ No newline at end of file +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { assertIsNumber } from "../Asserts.mjs"; +import { __unit } from "../UnitVal.mjs"; +import { SleepTimeout } from "../Thread.mjs"; +export function BuiltinSleep>( + Base: TBase, +) { + return class extends Base { + sleep = mkBase((arg) => { + const $r = this.runtime; + assertIsNumber(arg); + const delay = arg.val; + const theThread = $r.$t; + theThread.raiseBlockingThreadLev(arg.lev); + theThread.sleepTimeout = new SleepTimeout(delay, theThread); + return null; + }, "sleep"); + }; +} diff --git a/rt/src/builtins/spawn.mts b/rt/src/builtins/spawn.mts index 930b5244..fa9c7b50 100644 --- a/rt/src/builtins/spawn.mts +++ b/rt/src/builtins/spawn.mts @@ -1,58 +1,63 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import {lub} from '../Level.mjs' -import { assertNormalState, assertIsFunction, assertIsNode } from '../Asserts.mjs' -import { __nodeManager } from '../NodeManager.mjs'; -import { __unit } from '../UnitVal.mjs'; -import {SYSTEM_PROCESS_STRING} from '../Constants.mjs' -import { ProcessID } from '../process.mjs'; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { lub } from "../Level.mjs"; +import { + assertNormalState, + assertIsFunction, + assertIsNode, +} from "../Asserts.mjs"; +import { __nodeManager } from "../NodeManager.mjs"; +import { __unit } from "../UnitVal.mjs"; +import { SYSTEM_PROCESS_STRING } from "../Constants.mjs"; +import { ProcessID } from "../process.mjs"; -export function BuiltinSpawn>(Base: TBase) { - return class extends Base { - _getSystemProcess = mkBase ((arg) => { - assertIsNode(arg.val) - let node = __nodeManager.getNode(arg.val) - let pid = new ProcessID (null, SYSTEM_PROCESS_STRING, node) - return this.runtime.$t.mkVal (pid); - }) +export function BuiltinSpawn>( + Base: TBase, +) { + return class extends Base { + _getSystemProcess = mkBase((arg) => { + assertIsNode(arg.val); + const node = __nodeManager.getNode(arg.val); + const pid = new ProcessID(null, SYSTEM_PROCESS_STRING, node); + return this.runtime.$t.mkVal(pid); + }); - spawn = mkBase((larg) => { - assertNormalState("spawn") - // debug ("* rt rt_spawn *", larg.val, larg.lev); - // console.log ("SPAWN ARGS", larg) - this.runtime.$t.raiseCurrentThreadPC(larg.lev); - let arg = larg.val; - let __sched = this.runtime.__sched - + spawn = mkBase((larg) => { + assertNormalState("spawn"); + // debug ("* rt rt_spawn *", larg.val, larg.lev); + // console.log ("SPAWN ARGS", larg) + this.runtime.$t.raiseCurrentThreadPC(larg.lev); + const arg = larg.val; + const __sched = this.runtime.__sched; - let spawnLocal = (arg) => { - // debug ("scheduled rt_spawn ", arg.fun); + const spawnLocal = (arg) => { + // debug ("scheduled rt_spawn ", arg.fun); - let newPid = __sched.scheduleNewThreadAtLevel( - arg, - __unit, // [arg.env, __unit], - // arg.namespace, - this.runtime.$t.pc, - this.runtime.$t.bl) - return this.runtime.$t.returnImmediateLValue(newPid) ; - } + const newPid = __sched.scheduleNewThreadAtLevel( + arg, + __unit, // [arg.env, __unit], + // arg.namespace, + this.runtime.$t.pc, + this.runtime.$t.bl, + ); + return this.runtime.$t.returnImmediateLValue(newPid); + }; - - if (Array.isArray(arg)) { - if (__nodeManager.isLocalNode(arg[0].val)) { // check if we are at the same node or note - // debug ("SAME NODE") - this.runtime.$t.raiseCurrentThreadPC(lub(arg[0].lev, arg[1].lev)); - assertIsFunction(arg[1]); - return spawnLocal(arg[1].val) - } else { - assertIsNode(arg[0]); - assertIsFunction(arg[1]); - (async () => this.runtime.spawnAtNode(arg[0], arg[1]))() - - } - } else { - assertIsFunction(larg); - return spawnLocal(arg) - } - }, "spawn"); - } -} \ No newline at end of file + if (Array.isArray(arg)) { + if (__nodeManager.isLocalNode(arg[0].val)) { + // check if we are at the same node or note + // debug ("SAME NODE") + this.runtime.$t.raiseCurrentThreadPC(lub(arg[0].lev, arg[1].lev)); + assertIsFunction(arg[1]); + return spawnLocal(arg[1].val); + } else { + assertIsNode(arg[0]); + assertIsFunction(arg[1]); + (async () => this.runtime.spawnAtNode(arg[0], arg[1]))(); + } + } else { + assertIsFunction(larg); + return spawnLocal(arg); + } + }, "spawn"); + }; +} diff --git a/rt/src/builtins/stdio.mts b/rt/src/builtins/stdio.mts index d46890e7..88446c7f 100644 --- a/rt/src/builtins/stdio.mts +++ b/rt/src/builtins/stdio.mts @@ -1,122 +1,132 @@ -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LocalObject } from '../LocalObject.mjs' -import * as levels from '../Level.mjs' -import { mkLevel } from '../Level.mjs' -import { assertIsAuthority, assertIsRootAuthority, assertIsNTuple, assertIsLocalObject, assertIsString, assertIsUnit, assertNormalState } from '../Asserts.mjs' -import { __unit } from '../UnitVal.mjs'; -import { getCliArgs, TroupeCliArg } from '../TroupeCliArgs.mjs'; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LocalObject } from "../LocalObject.mjs"; +import * as levels from "../Level.mjs"; +import { mkLevel } from "../Level.mjs"; +import { + assertIsAuthority, + assertIsRootAuthority, + assertIsNTuple, + assertIsLocalObject, + assertIsString, + assertIsUnit, + assertNormalState, +} from "../Asserts.mjs"; +import { __unit } from "../UnitVal.mjs"; +import { getCliArgs, TroupeCliArg } from "../TroupeCliArgs.mjs"; const argv = getCliArgs(); const flowsTo = levels.flowsTo; -import * as _rl from 'node:readline'; - +import * as _rl from "node:readline"; const readline = _rl.createInterface({ - input: process.stdin, - output: process.stdout -}) + input: process.stdin, + output: process.stdout, +}); const lineBuffer = []; -const readlineCallbacks = [] +const readlineCallbacks = []; -const __stdio_lev = argv[TroupeCliArg.Stdiolev] ? levels.mkV1Level (argv[TroupeCliArg.Stdiolev]): levels.ROOT +const __stdio_lev = argv[TroupeCliArg.Stdiolev] + ? levels.mkV1Level(argv[TroupeCliArg.Stdiolev]) + : levels.ROOT; function lineListener(input) { - if (readlineCallbacks.length > 0) { - let cb = readlineCallbacks.shift(); - cb(input); - } else { - lineBuffer.push(input); - } + if (readlineCallbacks.length > 0) { + const cb = readlineCallbacks.shift(); + cb(input); + } else { + lineBuffer.push(input); + } } -readline.on('line', lineListener) +readline.on("line", lineListener); export function closeReadline() { - readline.close() + readline.close(); } -export function BuiltinStdIo>(Base: TBase) { - return class extends Base { - getStdout = mkBase((arg) => { - assertIsAuthority(arg) - let sufficentAuthority = flowsTo(__stdio_lev, arg.val.authorityLevel) - if (sufficentAuthority) { - let obj = new LocalObject(process.stdout); - return this.runtime.ret(this.mkVal(obj)) - } else { - this.runtime.$t.threadError - (`Not sufficient authority in getStdout\n` + - ` | Provided authority level ${arg.val.authorityLevel.stringRep()}\n` + - ` | Required authority level ${__stdio_lev.stringRep()}`) - } - - }) - - fprintln = mkBase((arg) => { - assertNormalState("fprintln") - assertIsNTuple(arg, 2); - assertIsLocalObject(arg.val[0]); - - let out = arg.val[0].val._value; - out.write(arg.val[1].stringRep(true) + "\n"); - return this.runtime.ret(__unit); - }); - - fprintlnWithLabels = mkBase((arg) => { - assertNormalState("fprintlnWithLabels") - assertIsNTuple(arg, 2); - assertIsLocalObject(arg.val[0]); - let out = arg.val[0].val._value; - out.write(this.runtime.$t.mkCopy(arg.val[1]).stringRep(false) + "\n"); - // out.write((arg.val[1]).stringRep(false) + "\n"); - return this.runtime.ret(__unit); +export function BuiltinStdIo>( + Base: TBase, +) { + return class extends Base { + getStdout = mkBase((arg) => { + assertIsAuthority(arg); + const sufficentAuthority = flowsTo(__stdio_lev, arg.val.authorityLevel); + if (sufficentAuthority) { + const obj = new LocalObject(process.stdout); + return this.runtime.ret(this.mkVal(obj)); + } else { + this.runtime.$t.threadError( + `Not sufficient authority in getStdout\n` + + ` | Provided authority level ${arg.val.authorityLevel.stringRep()}\n` + + ` | Required authority level ${__stdio_lev.stringRep()}`, + ); + } + }); + + fprintln = mkBase((arg) => { + assertNormalState("fprintln"); + assertIsNTuple(arg, 2); + assertIsLocalObject(arg.val[0]); + + const out = arg.val[0].val._value; + out.write(arg.val[1].stringRep(true) + "\n"); + return this.runtime.ret(__unit); + }); + + fprintlnWithLabels = mkBase((arg) => { + assertNormalState("fprintlnWithLabels"); + assertIsNTuple(arg, 2); + assertIsLocalObject(arg.val[0]); + const out = arg.val[0].val._value; + out.write(this.runtime.$t.mkCopy(arg.val[1]).stringRep(false) + "\n"); + // out.write((arg.val[1]).stringRep(false) + "\n"); + return this.runtime.ret(__unit); + }); + + fwrite = mkBase((arg) => { + assertNormalState("fwrite"); + assertIsNTuple(arg, 2); + assertIsLocalObject(arg.val[0]); + assertIsString(arg.val[1]); + const out = arg.val[0].val._value; + out.write(arg.val[1].val); + return this.runtime.ret(__unit); + }, "fwrite"); + + inputLine = mkBase((arg) => { + assertNormalState("inputLine"); + assertIsUnit(arg); + const theThread = this.runtime.$t; + theThread.raiseBlockingThreadLev(__stdio_lev); + if (lineBuffer.length > 0) { + const s = lineBuffer.shift(); + const r = theThread.mkValWithLev(s, __stdio_lev); + return theThread.returnImmediateLValue(r); + } else { + readlineCallbacks.push((s) => { + const r = theThread.mkValWithLev(s, __stdio_lev); + theThread.returnSuspended(r); + this.runtime.__sched.scheduleThread(theThread); + this.runtime.__sched.resumeLoopAsync(); }); - - fwrite = mkBase((arg) => { - assertNormalState("fwrite") - assertIsNTuple(arg, 2); - assertIsLocalObject(arg.val[0]); - assertIsString(arg.val[1]); - let out = arg.val[0].val._value; - out.write(arg.val[1].val); - return this.runtime.ret(__unit); - }, "fwrite"); - - inputLine = mkBase((arg) => { - assertNormalState("inputLine") - assertIsUnit(arg) - let theThread = this.runtime.$t; - theThread.raiseBlockingThreadLev(__stdio_lev) - if (lineBuffer.length > 0) { - let s = lineBuffer.shift(); - let r = theThread.mkValWithLev(s, __stdio_lev); - return theThread.returnImmediateLValue(r); - } else { - readlineCallbacks.push((s) => { - let r = theThread.mkValWithLev(s, __stdio_lev) - theThread.returnSuspended(r) - this.runtime.__sched.scheduleThread(theThread); - this.runtime.__sched.resumeLoopAsync() - }) - } - }, "inputLine") - - rt_question = mkBase((arg) => { - assertNormalState("rt_question") - readline.removeListener('line', lineListener); - let theThread = this.runtime.$t; - assertIsString(arg); - theThread.raiseBlockingThreadLev(__stdio_lev) - readline.question(arg.val, (s) => { - let r = theThread.mkValWithLev(s, __stdio_lev) - theThread.returnSuspended(r) - this.runtime.__sched.scheduleThread(theThread); - this.runtime.__sched.resumeLoopAsync() - readline.on('line', lineListener) - }) - - }, "question") - } -} \ No newline at end of file + } + }, "inputLine"); + + rt_question = mkBase((arg) => { + assertNormalState("rt_question"); + readline.removeListener("line", lineListener); + const theThread = this.runtime.$t; + assertIsString(arg); + theThread.raiseBlockingThreadLev(__stdio_lev); + readline.question(arg.val, (s) => { + const r = theThread.mkValWithLev(s, __stdio_lev); + theThread.returnSuspended(r); + this.runtime.__sched.scheduleThread(theThread); + this.runtime.__sched.resumeLoopAsync(); + readline.on("line", lineListener); + }); + }, "question"); + }; +} diff --git a/rt/src/builtins/string.mts b/rt/src/builtins/string.mts index fd302ebd..ca26ae52 100644 --- a/rt/src/builtins/string.mts +++ b/rt/src/builtins/string.mts @@ -1,49 +1,49 @@ -import {UserRuntimeZero, Constructor, mkBase} from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import { assertIsString, assertIsNTuple, assertIsNumber } from '../Asserts.mjs' -import { lub } from '../Level.mjs'; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import { assertIsString, assertIsNTuple, assertIsNumber } from "../Asserts.mjs"; +import { lub } from "../Level.mjs"; +export function BuiltinString>( + Base: TBase, +) { + return class extends Base { + charCodeAtWithDefault = mkBase((arg) => { + assertIsNTuple(arg, 3); + assertIsString(arg.val[0]); + assertIsNumber(arg.val[1]); -export function BuiltinString > (Base:TBase) { - return class extends Base { - charCodeAtWithDefault = mkBase (arg => { - assertIsNTuple(arg, 3); - assertIsString(arg.val[0]) - assertIsNumber(arg.val[1]); + const s: string = arg.val[0].val; + const j = arg.val[1].val; + const lev = lub(arg.lev, arg.val[0].lev, arg.val[1].lev, arg.val[2].lev); - let s:string = arg.val[0].val - let j = arg.val[1].val - let lev = lub (arg.lev, arg.val[0].lev, arg.val[1].lev, arg.val[2].lev ) + if (j >= s.length || 0 > j) { + return this.runtime.ret(new LVal(arg.val[2].val, lev)); + } else { + return this.runtime.ret(new LVal(s.charCodeAt(j), lev)); + } + }); - if ( j >= s.length || 0 > j ) { - return this.runtime.ret (new LVal (arg.val[2].val, lev)); - } else { - return this.runtime.ret (new LVal (s.charCodeAt(j), lev)); - } + strlen = mkBase((arg) => { + assertIsString(arg); + const s: string = arg.val; + return this.runtime.ret(new LVal(s.length, arg.lev)); + }); - }) - - strlen = mkBase (arg => { - assertIsString(arg); - let s: string = arg.val ; - return this.runtime.ret (new LVal (s.length, arg.lev)) - }) - - substring = mkBase (arg => { - assertIsNTuple(arg, 3) - assertIsString(arg.val[0]) - assertIsNumber(arg.val[1]) - assertIsNumber(arg.val[2]) - let s = arg.val[0].val - let i = arg.val[1].val - let j = arg.val[2].val - let s2 = s.substring (i,j) - return this.runtime.ret (new LVal(s2, lub ( arg.lev - , arg.val[0].lev - , arg.val[1].lev - , arg.val[2].lev - ))) - }) - } - -} \ No newline at end of file + substring = mkBase((arg) => { + assertIsNTuple(arg, 3); + assertIsString(arg.val[0]); + assertIsNumber(arg.val[1]); + assertIsNumber(arg.val[2]); + const s = arg.val[0].val; + const i = arg.val[1].val; + const j = arg.val[2].val; + const s2 = s.substring(i, j); + return this.runtime.ret( + new LVal( + s2, + lub(arg.lev, arg.val[0].lev, arg.val[1].lev, arg.val[2].lev), + ), + ); + }); + }; +} diff --git a/rt/src/builtins/stringToInt.mts b/rt/src/builtins/stringToInt.mts index 45d70430..c6dc92c0 100644 --- a/rt/src/builtins/stringToInt.mts +++ b/rt/src/builtins/stringToInt.mts @@ -1,21 +1,22 @@ -'use strict' -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import { assertIsNumber, assertIsString } from '../Asserts.mjs'; +"use strict"; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import { assertIsNumber, assertIsString } from "../Asserts.mjs"; +export function BuiltinStringToInt>( + Base: TBase, +) { + return class extends Base { + stringToInt = mkBase((arg) => { + assertIsString(arg); + const r = this.runtime.$t.mkValWithLev(parseFloat(arg.val), arg.lev); + return this.runtime.ret(r); + }, "stringToInt"); -export function BuiltinStringToInt>(Base: TBase) { - return class extends Base { - stringToInt = mkBase((arg) => { - assertIsString(arg); - let r = this.runtime.$t.mkValWithLev(parseFloat(arg.val), arg.lev); - return this.runtime.ret(r); - }, "stringToInt") - - intToString = mkBase((arg) => { - assertIsNumber (arg); - let r = this.runtime.$t.mkValWithLev( arg.val.toString(), arg.lev ); - return this.runtime.ret (r); - }) - } + intToString = mkBase((arg) => { + assertIsNumber(arg); + const r = this.runtime.$t.mkValWithLev(arg.val.toString(), arg.lev); + return this.runtime.ret(r); + }); + }; } diff --git a/rt/src/builtins/toString.mts b/rt/src/builtins/toString.mts index f4506023..4bd953ec 100644 --- a/rt/src/builtins/toString.mts +++ b/rt/src/builtins/toString.mts @@ -1,32 +1,33 @@ -'use strict' -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; +"use strict"; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +export function BuiltinToString>( + Base: TBase, +) { + return class extends Base { + toString = mkBase((arg) => { + const taintRef = { lev: this.runtime.$t.pc }; + const s = this.runtime.$t.mkCopy(arg).stringRep( + true, // omit labels + taintRef, // accumulate taint into this reference + ); -export function BuiltinToString>(Base: TBase) { - return class extends Base { - toString = mkBase((arg) => { - let taintRef = { lev: this.runtime.$t.pc }; - let s = this.runtime.$t.mkCopy(arg).stringRep - (true, // omit labels - taintRef // accumulate taint into this reference - ) + const r = this.runtime.$t.mkValWithLev(s, taintRef.lev); + return this.runtime.ret(r); + }, "toString"); - let r = this.runtime.$t.mkValWithLev(s, taintRef.lev); - return this.runtime.ret(r); - }, "toString") + toStringL = mkBase((arg) => { + const v = this.runtime.$t.mkCopy(arg); + const taintRef = { lev: this.runtime.$t.pc }; + const s = v.stringRep( + false, // do not omit labels + taintRef, // accumulate taint into this reference + ); - toStringL = mkBase((arg) => { - let v = this.runtime.$t.mkCopy(arg); - let taintRef = { lev: this.runtime.$t.pc }; - - let s = v.stringRep(false, // do not omit labels - taintRef // accumulate taint into this reference - ) - - let r = this.runtime.$t.mkValWithLev(s, taintRef.lev); - return this.runtime.ret(r); - }, "toStringLabeled") - } -} \ No newline at end of file + const r = this.runtime.$t.mkValWithLev(s, taintRef.lev); + return this.runtime.ret(r); + }, "toStringLabeled"); + }; +} diff --git a/rt/src/builtins/types.mts b/rt/src/builtins/types.mts index 8acf157d..f0de8861 100644 --- a/rt/src/builtins/types.mts +++ b/rt/src/builtins/types.mts @@ -1,76 +1,79 @@ -'use strict' -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import { LVal } from '../Lval.mjs'; -import { assertIsNTuple, assertIsRecord, assertIsString, assertIsUnit, assertNormalState } from '../Asserts.mjs' +"use strict"; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import { LVal } from "../Lval.mjs"; +import { + assertIsNTuple, + assertIsRecord, + assertIsString, + assertIsUnit, + assertNormalState, +} from "../Asserts.mjs"; import { Record } from "../Record.mjs"; -import { lub } from '../Level.mjs'; -import { __unit } from '../UnitVal.mjs'; -import { TroupeType } from '../TroupeTypes.mjs'; +import { lub } from "../Level.mjs"; +import { __unit } from "../UnitVal.mjs"; +import { TroupeType } from "../TroupeTypes.mjs"; -export function BuiltinTypeInformation>(Base: TBase) { - return class extends Base { - // returns a string containing the type information - getType = mkBase((larg) => { - let _t = "unknown" // 2024-03-18; todo: add proper type - switch (larg.val._troupeType) { - case TroupeType.UNIT: - _t = "unit"; - break; - case TroupeType.BOOLEAN: - _t = "boolean"; - break; - case TroupeType.NUMBER: - _t = "number"; - break; - - case TroupeType.STRING: - _t = "string"; - break; - case TroupeType.PROCESS_ID: - _t = "process_id"; - break; - case TroupeType.LEVEL: - _t = "level"; - break; - case TroupeType.AUTHORITY: - _t = "authority"; - break; - case TroupeType.CLOSURE: - _t = "function"; - break; - case TroupeType.TUPLE: - _t = "tuple"; - break; - case TroupeType.LIST: - _t = "list"; - break; - case TroupeType.RECORD: - _t = "record"; - break; - case TroupeType.LOCALOBJECT: - _t = "localobject"; - break; - default: - switch (typeof larg.val) { - case 'string': - _t = "string"; - break; - case 'number': - _t = "number"; - break; - case 'boolean': - _t = "boolean" - break; - } - } - return this.runtime.ret ( - new LVal ( _t - , lub (larg.tlev, this.runtime.$t.pc) - , this.runtime.$t.pc) - ) +export function BuiltinTypeInformation< + TBase extends Constructor, +>(Base: TBase) { + return class extends Base { + // returns a string containing the type information + getType = mkBase((larg) => { + let _t = "unknown"; // 2024-03-18; todo: add proper type + switch (larg.val._troupeType) { + case TroupeType.UNIT: + _t = "unit"; + break; + case TroupeType.BOOLEAN: + _t = "boolean"; + break; + case TroupeType.NUMBER: + _t = "number"; + break; - - - }) - } + case TroupeType.STRING: + _t = "string"; + break; + case TroupeType.PROCESS_ID: + _t = "process_id"; + break; + case TroupeType.LEVEL: + _t = "level"; + break; + case TroupeType.AUTHORITY: + _t = "authority"; + break; + case TroupeType.CLOSURE: + _t = "function"; + break; + case TroupeType.TUPLE: + _t = "tuple"; + break; + case TroupeType.LIST: + _t = "list"; + break; + case TroupeType.RECORD: + _t = "record"; + break; + case TroupeType.LOCALOBJECT: + _t = "localobject"; + break; + default: + switch (typeof larg.val) { + case "string": + _t = "string"; + break; + case "number": + _t = "number"; + break; + case "boolean": + _t = "boolean"; + break; + } + } + return this.runtime.ret( + new LVal(_t, lub(larg.tlev, this.runtime.$t.pc), this.runtime.$t.pc), + ); + }); + }; } diff --git a/rt/src/builtins/whereis.mts b/rt/src/builtins/whereis.mts index 12e33980..ba811d65 100644 --- a/rt/src/builtins/whereis.mts +++ b/rt/src/builtins/whereis.mts @@ -1,108 +1,117 @@ -'use strict' -import { UserRuntimeZero, Constructor, mkBase } from './UserRuntimeZero.mjs' -import * as levels from '../Level.mjs' -import { ProcessID } from '../process.mjs'; -const { lub, flowsTo } = levels -import {deserialize} from '../deserialize.mjs' -import { __nodeManager } from '../NodeManager.mjs'; -import { assertNormalState, assertIsNTuple, assertIsString, assertIsProcessId, assertIsAuthority, assertIsRootAuthority, assertIsNode } from '../Asserts.mjs'; -import { __unit } from '../UnitVal.mjs'; -import { nodeTrustLevel } from '../TrustManager.mjs'; -export let __theRegister = {} -import {p2p} from '../p2p/p2p.mjs' +"use strict"; +import { UserRuntimeZero, Constructor, mkBase } from "./UserRuntimeZero.mjs"; +import * as levels from "../Level.mjs"; +import { ProcessID } from "../process.mjs"; +const { lub, flowsTo } = levels; +import { deserialize } from "../deserialize.mjs"; +import { __nodeManager } from "../NodeManager.mjs"; +import { + assertNormalState, + assertIsNTuple, + assertIsString, + assertIsProcessId, + assertIsAuthority, + assertIsRootAuthority, + assertIsNode, +} from "../Asserts.mjs"; +import { __unit } from "../UnitVal.mjs"; +import { nodeTrustLevel } from "../TrustManager.mjs"; +export const __theRegister = {}; +import { p2p } from "../p2p/p2p.mjs"; // import runId from '../runId.mjs'; -import { getCliArgs, TroupeCliArg } from '../TroupeCliArgs.mjs'; +import { getCliArgs, TroupeCliArg } from "../TroupeCliArgs.mjs"; const argv = getCliArgs(); -let logLevel = argv[TroupeCliArg.Debug] ? 'debug': 'info' -import { mkLogger } from '../logger.mjs' -const logger = mkLogger('RTM', logLevel); -const debug = x => logger.debug(x) - - -export function BuiltinRegistry>(Base: TBase) { - return class extends Base { - register = mkBase((arg) => { - let $r = this.runtime - assertNormalState("register") - assertIsNTuple(arg, 3); - assertIsString(arg.val[0]) - assertIsProcessId(arg.val[1]); - assertIsAuthority(arg.val[2]); - assertIsRootAuthority(arg.val[2]); - - - let ok_to_raise = - flowsTo($r.$t.bl, levels.BOT); - if (!ok_to_raise) { - $r.$t.threadError("Cannot raise trust level when the process is tainted\s" + - ` | blocking label: ${$r.$t.bl.stringRep()}`) - } - - - // TODO: 2018-07-29: info flow checks - // this is needed, because registration - // is stateful - - let k = arg.val[0].val; - let v = arg.val[1]; - - __theRegister[k] = v; - return $r.ret(__unit); - }, "register") - - - - whereis = mkBase((arg) => { - let $r = this.runtime - assertNormalState("whereis") - assertIsNTuple(arg, 2); - assertIsNode(arg.val[0]); - assertIsString(arg.val[1]); - $r.$t.raiseBlockingThreadLev(arg.val[0].lev); - $r.$t.raiseBlockingThreadLev(arg.val[1].lev); - - let __sched = $r.__sched - - // let n = dealias(arg.val[0].val); - let n = __nodeManager.getNode(arg.val[0].val).nodeId; - - let k = arg.val[1].val; - let nodeLev = nodeTrustLevel(n); - let theThread = $r.$t; - - - let okToLookup = flowsTo(lub($r.$t.pc, arg.val[0].lev, arg.val[1].lev), nodeLev); - if (!okToLookup) { - $r.$t.threadError("Information flow violation in whereis"); - return; - } - - if (__nodeManager.isLocalNode(n)) { - if (__theRegister[k]) { - return $r.ret(__theRegister[k]) - } - } else { - (async () => { - try { - let body1 = await p2p.whereisp2p(n, k); - let body = await deserialize(nodeTrustLevel(n), body1); - let pid = new ProcessID(body.val.uuid, body.val.pid, body.val.node); - - theThread.returnSuspended(theThread.mkValWithLev(pid, body.lev)); - __sched.scheduleThread(theThread); - __sched.resumeLoopAsync(); - - } catch (err) { - $r.debug("whereis error: " + err.toString()) - throw err; - } - - })() - } - }, "whereis") - - } -} \ No newline at end of file +const logLevel = argv[TroupeCliArg.Debug] ? "debug" : "info"; +import { mkLogger } from "../logger.mjs"; +const logger = mkLogger("RTM", logLevel); +const debug = (x) => logger.debug(x); + +export function BuiltinRegistry>( + Base: TBase, +) { + return class extends Base { + register = mkBase((arg) => { + const $r = this.runtime; + assertNormalState("register"); + assertIsNTuple(arg, 3); + assertIsString(arg.val[0]); + assertIsProcessId(arg.val[1]); + assertIsAuthority(arg.val[2]); + assertIsRootAuthority(arg.val[2]); + + const ok_to_raise = flowsTo($r.$t.bl, levels.BOT); + if (!ok_to_raise) { + $r.$t.threadError( + "Cannot raise trust level when the process is tainted\s" + + ` | blocking label: ${$r.$t.bl.stringRep()}`, + ); + } + + // TODO: 2018-07-29: info flow checks + // this is needed, because registration + // is stateful + + const k = arg.val[0].val; + const v = arg.val[1]; + + __theRegister[k] = v; + return $r.ret(__unit); + }, "register"); + + whereis = mkBase((arg) => { + const $r = this.runtime; + assertNormalState("whereis"); + assertIsNTuple(arg, 2); + assertIsNode(arg.val[0]); + assertIsString(arg.val[1]); + $r.$t.raiseBlockingThreadLev(arg.val[0].lev); + $r.$t.raiseBlockingThreadLev(arg.val[1].lev); + + const __sched = $r.__sched; + + // let n = dealias(arg.val[0].val); + const n = __nodeManager.getNode(arg.val[0].val).nodeId; + + const k = arg.val[1].val; + const nodeLev = nodeTrustLevel(n); + const theThread = $r.$t; + + const okToLookup = flowsTo( + lub($r.$t.pc, arg.val[0].lev, arg.val[1].lev), + nodeLev, + ); + if (!okToLookup) { + $r.$t.threadError("Information flow violation in whereis"); + return; + } + + if (__nodeManager.isLocalNode(n)) { + if (__theRegister[k]) { + return $r.ret(__theRegister[k]); + } + } else { + (async () => { + try { + const body1 = await p2p.whereisp2p(n, k); + const body = await deserialize(nodeTrustLevel(n), body1); + const pid = new ProcessID( + body.val.uuid, + body.val.pid, + body.val.node, + ); + + theThread.returnSuspended(theThread.mkValWithLev(pid, body.lev)); + __sched.scheduleThread(theThread); + __sched.resumeLoopAsync(); + } catch (err) { + $r.debug("whereis error: " + err.toString()); + throw err; + } + })(); + } + }, "whereis"); + }; +} diff --git a/rt/src/colorConfig.mts b/rt/src/colorConfig.mts index a9ea121f..b124752d 100644 --- a/rt/src/colorConfig.mts +++ b/rt/src/colorConfig.mts @@ -1,24 +1,24 @@ -import chalk from 'chalk'; -import { getCliArgs, TroupeCliArg } from './TroupeCliArgs.mjs'; +import chalk from "chalk"; +import { getCliArgs, TroupeCliArg } from "./TroupeCliArgs.mjs"; let colorConfigured = false; export function configureColors(): void { - if (colorConfigured) return; // Ensure we only configure once - - const argv = getCliArgs(); - - // NO_COLOR environment variable (standard from no-color.org) - // Any non-empty value disables colors - // CLI flag --disable-color overrides everything - if (process.env.NO_COLOR || argv[TroupeCliArg.NoColor]) { - chalk.level = 0; // Disable all colors - } - - colorConfigured = true; + if (colorConfigured) return; // Ensure we only configure once + + const argv = getCliArgs(); + + // NO_COLOR environment variable (standard from no-color.org) + // Any non-empty value disables colors + // CLI flag --disable-color overrides everything + if (process.env.NO_COLOR || argv[TroupeCliArg.NoColor]) { + chalk.level = 0; // Disable all colors + } + + colorConfigured = true; } export function isColorEnabled(): boolean { - const argv = getCliArgs(); - return !(process.env.NO_COLOR || argv[TroupeCliArg.NoColor]); -} \ No newline at end of file + const argv = getCliArgs(); + return !(process.env.NO_COLOR || argv[TroupeCliArg.NoColor]); +} diff --git a/rt/src/deserialize.mts b/rt/src/deserialize.mts index 2c194875..0d75b5b0 100644 --- a/rt/src/deserialize.mts +++ b/rt/src/deserialize.mts @@ -1,19 +1,19 @@ "use strict"; -import { strict as assert } from 'node:assert' -import {spawn} from 'child_process' -import * as Ty from './TroupeTypes.mjs' -import { LVal } from './Lval.mjs'; -import { mkTuple, mkList } from './ValuesUtil.mjs'; -import { ProcessID } from './process.mjs'; -import { Authority } from './Authority.mjs'; -import { Atom } from './Atom.mjs'; -import { __unitbase }from './UnitBase.mjs' -import { glb, mkLevel } from './Level.mjs'; -import { RuntimeInterface } from './RuntimeInterface.mjs'; -import { Level } from './Level.mjs'; -import { Record } from './Record.mjs'; -import { RawClosure } from './RawClosure.mjs'; -import * as levels from './Level.mjs'; +import { strict as assert } from "node:assert"; +import { spawn } from "child_process"; +import * as Ty from "./TroupeTypes.mjs"; +import { LVal } from "./Lval.mjs"; +import { mkTuple, mkList } from "./ValuesUtil.mjs"; +import { ProcessID } from "./process.mjs"; +import { Authority } from "./Authority.mjs"; +import { Atom } from "./Atom.mjs"; +import { __unitbase } from "./UnitBase.mjs"; +import { glb, mkLevel } from "./Level.mjs"; +import { RuntimeInterface } from "./RuntimeInterface.mjs"; +import { Level } from "./Level.mjs"; +import { Record } from "./Record.mjs"; +import { RawClosure } from "./RawClosure.mjs"; +import * as levels from "./Level.mjs"; let __compilerOsProcess = null; @@ -21,327 +21,328 @@ let __rtObj = null; // obs: these are global... let __isCurrentlyUsingCompiler = false; // simple flag to make sure we handle one deserialization at a time -let __currentCallback = null; // a callback for synchronizing with the caller +let __currentCallback = null; // a callback for synchronizing with the caller let __currentDeserializedJson = null; let __trustLevel = null; - export function setRuntimeObj(rt: RuntimeInterface) { - __rtObj = rt; + __rtObj = rt; } -const HEADER:string = - "this.libSet = new Set () \n\ +const HEADER = + "this.libSet = new Set () \n\ this.libs = [] \n\ this.addLib = function (lib, decl)\ { if (!this.libSet.has (lib +'.'+decl)) { \ this.libSet.add (lib +'.'+decl);\ - this.libs.push ({lib:lib, decl:decl})} }\n" + this.libs.push ({lib:lib, decl:decl})} }\n"; function startCompiler() { - __compilerOsProcess = spawn(process.env.TROUPE + '/bin/troupec', ['--json']); - __compilerOsProcess.on('exit', (code: number) => { - process.exit(code); - }); + __compilerOsProcess = spawn(process.env.TROUPE + "/bin/troupec", ["--json"]); + __compilerOsProcess.on("exit", (code: number) => { + process.exit(code); + }); - let marker = "/*-----*/\n\n" + const marker = "/*-----*/\n\n"; - // accumulator of communication with the compiler; reset after - // each deserialization; needed because we have no guarantees about - // how the data coming back from the compiler is chunked + // accumulator of communication with the compiler; reset after + // each deserialization; needed because we have no guarantees about + // how the data coming back from the compiler is chunked - let accum = ""; + let accum = ""; - __compilerOsProcess.stdout.on('data', (data: string) => { - accum += data; - let j = accum.indexOf(marker); - if (j >= 0) { - constructCurrent(accum.slice(0, j)); - accum = accum.slice(j + marker.length); - } - }); + __compilerOsProcess.stdout.on("data", (data: string) => { + accum += data; + const j = accum.indexOf(marker); + if (j >= 0) { + constructCurrent(accum.slice(0, j)); + accum = accum.slice(j + marker.length); + } + }); } startCompiler(); export function stopCompiler() { - __compilerOsProcess.stdin.end(); + __compilerOsProcess.stdin.end(); } - // -------------------------------------------------- // some rudimentary debugging mechanisms; probably should be rewritten function debuglog(...s) { - let spaces = ""; - for (let j = 0; j < indentcounter; j++) { - spaces = " " + spaces; - } + let spaces = ""; + for (let j = 0; j < indentcounter; j++) { + spaces = " " + spaces; + } - s.unshift("DEBUG:" + spaces) - console.log.apply(null, s) + s.unshift("DEBUG:" + spaces); + console.log.apply(null, s); } var indentcounter = 0; function indent() { - indentcounter++; + indentcounter++; } function unindent() { - indentcounter--; + indentcounter--; } - - function deserializationError() { - console.log("DESERIALIZATION ERROR HANDLING IS NOT IMPLEMENTED") - process.exit(1); + console.log("DESERIALIZATION ERROR HANDLING IS NOT IMPLEMENTED"); + process.exit(1); } function constructCurrent(compilerOutput: string) { - // debuglog (deserializationObject) - - __isCurrentlyUsingCompiler = false; - let serobj = __currentDeserializedJson; - let desercb = __currentCallback; - - // 1. reconstruct the namespaces - let snippets = compilerOutput.split("\n\n"); - let k = 0; - - - let ctxt = { // deserialization context - namespaces : new Array (serobj.namespaces.length), - closures : new Array (serobj.closures.length), - envs : new Array (serobj.envs.length) + // debuglog (deserializationObject) + + __isCurrentlyUsingCompiler = false; + const serobj = __currentDeserializedJson; + const desercb = __currentCallback; + + // 1. reconstruct the namespaces + const snippets = compilerOutput.split("\n\n"); + let k = 0; + + const ctxt = { + // deserialization context + namespaces: new Array(serobj.namespaces.length), + closures: new Array(serobj.closures.length), + envs: new Array(serobj.envs.length), + }; + + for (let i = 0; i < serobj.namespaces.length; i++) { + const ns = serobj.namespaces[i]; + let nsFun = HEADER; + + const atomSet = new Set(); + + // nsFun += "this.libSet = new Set () \n" + // nsFun += "this.libs = [] \n" + // nsFun += "this.addLib = function (lib, decl) " + + // " { if (!this.libSet.has (lib +'.'+decl)) { " + + // " this.libSet.add (lib +'.'+decl); " + + // " this.libs.push ({lib:lib, decl:decl})} } \n" + // nsFun += "this.loadlibs = function (cb) { rt.linkLibs (this.libs, this, cb) } \n" + + for (let j = 0; j < ns.length; j++) { + if (j > 0) { + nsFun += "\n\n"; // looks neater this way + } + const snippetJson = JSON.parse(snippets[k++]); + // console.log (snippetJson.libs); + // console.log (snippetJson.fname); + nsFun += snippetJson.code; + + for (const atom of snippetJson.atoms) { + atomSet.add(atom); + } + // console.log (snippetJson.atoms) } - - for (let i = 0; i < serobj.namespaces.length; i++) { - let ns = serobj.namespaces[i] - let nsFun = HEADER - - let atomSet = new Set() - - // nsFun += "this.libSet = new Set () \n" - // nsFun += "this.libs = [] \n" - // nsFun += "this.addLib = function (lib, decl) " + - // " { if (!this.libSet.has (lib +'.'+decl)) { " + - // " this.libSet.add (lib +'.'+decl); " + - // " this.libs.push ({lib:lib, decl:decl})} } \n" - // nsFun += "this.loadlibs = function (cb) { rt.linkLibs (this.libs, this, cb) } \n" - - - for (let j = 0; j < ns.length; j++) { - if (j > 0) { - nsFun += "\n\n" // looks neater this way - } - let snippetJson = JSON.parse(snippets[k++]); - // console.log (snippetJson.libs); - // console.log (snippetJson.fname); - nsFun += snippetJson.code; - - for (let atom of snippetJson.atoms) { - atomSet.add(atom) - } - // console.log (snippetJson.atoms) - } - let argNames = Array.from(atomSet); - let argValues = argNames.map( argName => {return new Atom(argName)}) - argNames.unshift('rt') - argNames.push(nsFun) - // Observe that there is some serious level of - // reflection going on in here - // Arguments to Function are - // 'rt', ATOM1, ..., ATOMk, nsFun - // - // - let NS: any = Reflect.construct (Function, argNames) - - // We now construct an instance of the newly constructed object - // that takes the runtime object + atoms as its arguments - - // console.log (NS.toString()); // debugging - argValues.unshift(__rtObj) - ctxt.namespaces[i] = Reflect.construct (NS, argValues) - - } - - // 2. reconstruct the closures and environments - let sercloss = serobj.closures; - - let serenvs = serobj.envs; - - function mkClosure(i: number) { - if (!ctxt.closures[i]) { - let nm = ctxt.namespaces[sercloss[i].namespacePtr.NamespaceID] - let fn = nm[sercloss[i].fun]; - let env = mkEnv(sercloss[i].envptr.EnvID, (env) => { - ctxt.closures[i] = RawClosure(env, nm, fn); - }) - ctxt.closures[i].__dataLevel = env.__dataLevel; - } - return ctxt.closures[i]; + const argNames = Array.from(atomSet); + const argValues = argNames.map((argName) => { + return new Atom(argName); + }); + argNames.unshift("rt"); + argNames.push(nsFun); + // Observe that there is some serious level of + // reflection going on in here + // Arguments to Function are + // 'rt', ATOM1, ..., ATOMk, nsFun + // + // + const NS: any = Reflect.construct(Function, argNames); + + // We now construct an instance of the newly constructed object + // that takes the runtime object + atoms as its arguments + + // console.log (NS.toString()); // debugging + argValues.unshift(__rtObj); + ctxt.namespaces[i] = Reflect.construct(NS, argValues); + } + + // 2. reconstruct the closures and environments + const sercloss = serobj.closures; + + const serenvs = serobj.envs; + + function mkClosure(i: number) { + if (!ctxt.closures[i]) { + const nm = ctxt.namespaces[sercloss[i].namespacePtr.NamespaceID]; + const fn = nm[sercloss[i].fun]; + const env = mkEnv(sercloss[i].envptr.EnvID, (env) => { + ctxt.closures[i] = RawClosure(env, nm, fn); + }); + ctxt.closures[i].__dataLevel = env.__dataLevel; } - - function mkEnv(i: number, post_init?: (any)=>void ) { - if (!ctxt.envs[i]) { - let env = {__dataLevel : levels.BOT}; - if (post_init) { - post_init (env) - } - ctxt.envs[i] = env; - for (var field in serenvs[i]) { - let v = mkValue(serenvs[i][field]); - env[field] = v - env.__dataLevel = levels.lub (env.__dataLevel, v.dataLevel) - } - } else { - if (post_init) { - post_init (ctxt.envs[i]); - } - } - return ctxt.envs[i] + return ctxt.closures[i]; + } + + function mkEnv(i: number, post_init?: (any) => void) { + if (!ctxt.envs[i]) { + const env = { __dataLevel: levels.BOT }; + if (post_init) { + post_init(env); + } + ctxt.envs[i] = env; + for (const field in serenvs[i]) { + const v = mkValue(serenvs[i][field]); + env[field] = v; + env.__dataLevel = levels.lub(env.__dataLevel, v.dataLevel); + } + } else { + if (post_init) { + post_init(ctxt.envs[i]); + } } + return ctxt.envs[i]; + } - - function deserializeArray(x) { - let a = []; - for (let i = 0; i < x.length; i++) { - a.push(mkValue(x[i])); - } - return a + function deserializeArray(x) { + const a = []; + for (let i = 0; i < x.length; i++) { + a.push(mkValue(x[i])); } + return a; + } + + /* + # # + # # # # # # ## # # # ###### + ## ## # # # # # # # # # # + # ## # #### # # # # # # # ##### + # # # # # # ###### # # # # + # # # # # # # # # # # # + # # # # # # # ###### #### ###### - /* - # # - # # # # # # ## # # # ###### - ## ## # # # # # # # # # # - # ## # #### # # # # # # # ##### - # # # # # # ###### # # # # - # # # # # # # # # # # # - # # # # # # # ###### #### ###### - */ - function mkValue(arg: { val: any; lev: any; tlev: any; troupeType: Ty.TroupeType; }) { - // debuglog ("*** mkValue", arg); - assert(Ty.isLVal(arg)); - let obj = arg.val; - let lev = mkLevel(arg.lev); - let tlev = mkLevel(arg.tlev); - - function _trustGLB(x: Level) { - return (glb(x, __trustLevel)) - } - - let _tt = arg.troupeType - - - function value() { - switch (_tt) { - case Ty.TroupeType.RECORD: - // for reords, the serialization format is [[key, value_json], ...] - let a = []; - for (let i = 0; i < obj.length; i++) { - a.push ([ obj[i][0], mkValue(obj[i][1]) ]) - } - return Record.mkRecord(a); - case Ty.TroupeType.LIST: - return mkList(deserializeArray(obj)) - case Ty.TroupeType.TUPLE: - return mkTuple(deserializeArray(obj)) - case Ty.TroupeType.CLOSURE: - return mkClosure(obj.ClosureID) - case Ty.TroupeType.NUMBER: - case Ty.TroupeType.BOOLEAN: - case Ty.TroupeType.STRING: - return obj; - case Ty.TroupeType.PROCESS_ID: - return new ProcessID(obj.uuid, obj.pid, obj.node) - case Ty.TroupeType.AUTHORITY: - // 2018-10-18: AA: authority attenuation based on the trust level of the sender - return new Authority(_trustGLB(mkLevel(obj.authorityLevel))) - case Ty.TroupeType.LEVEL: - return mkLevel(obj.lev) - case Ty.TroupeType.LVAL: - return mkValue(obj) - case Ty.TroupeType.ATOM: - return new Atom(obj.atom, obj.creation_uuid) - case Ty.TroupeType.UNIT: - return __unitbase - default: - return obj; - } - } - - return new LVal(value(), _trustGLB(lev), _trustGLB(tlev)); + function mkValue(arg: { + val: any; + lev: any; + tlev: any; + troupeType: Ty.TroupeType; + }) { + // debuglog ("*** mkValue", arg); + assert(Ty.isLVal(arg)); + const obj = arg.val; + const lev = mkLevel(arg.lev); + const tlev = mkLevel(arg.tlev); + + function _trustGLB(x: Level) { + return glb(x, __trustLevel); } - for (let i = 0; i < sercloss.length; i++) { - mkClosure(i); + const _tt = arg.troupeType; + + function value() { + switch (_tt) { + case Ty.TroupeType.RECORD: + // for reords, the serialization format is [[key, value_json], ...] + const a = []; + for (let i = 0; i < obj.length; i++) { + a.push([obj[i][0], mkValue(obj[i][1])]); + } + return Record.mkRecord(a); + case Ty.TroupeType.LIST: + return mkList(deserializeArray(obj)); + case Ty.TroupeType.TUPLE: + return mkTuple(deserializeArray(obj)); + case Ty.TroupeType.CLOSURE: + return mkClosure(obj.ClosureID); + case Ty.TroupeType.NUMBER: + case Ty.TroupeType.BOOLEAN: + case Ty.TroupeType.STRING: + return obj; + case Ty.TroupeType.PROCESS_ID: + return new ProcessID(obj.uuid, obj.pid, obj.node); + case Ty.TroupeType.AUTHORITY: + // 2018-10-18: AA: authority attenuation based on the trust level of the sender + return new Authority(_trustGLB(mkLevel(obj.authorityLevel))); + case Ty.TroupeType.LEVEL: + return mkLevel(obj.lev); + case Ty.TroupeType.LVAL: + return mkValue(obj); + case Ty.TroupeType.ATOM: + return new Atom(obj.atom, obj.creation_uuid); + case Ty.TroupeType.UNIT: + return __unitbase; + default: + return obj; + } } - for (let i = 0; i < serenvs.length; i++) { - mkEnv(i); - } + return new LVal(value(), _trustGLB(lev), _trustGLB(tlev)); + } - let v = mkValue(serobj.value); + for (let i = 0; i < sercloss.length; i++) { + mkClosure(i); + } - // go over the namespaces we have generated - // and load all libraries before calling the last callback + for (let i = 0; i < serenvs.length; i++) { + mkEnv(i); + } - function loadLib(i: number, cb) { - if (i < ctxt.namespaces.length) { - __rtObj.linkLibs(ctxt.namespaces[i]).then(() => loadLib(i + 1, cb)) - } else { - cb(); - } + const v = mkValue(serobj.value); + + // go over the namespaces we have generated + // and load all libraries before calling the last callback + + function loadLib(i: number, cb) { + if (i < ctxt.namespaces.length) { + __rtObj.linkLibs(ctxt.namespaces[i]).then(() => { + loadLib(i + 1, cb); + }); + } else { + cb(); } + } - loadLib(0, () => desercb(v)); + loadLib(0, () => desercb(v)); } -// 2018-11-30: AA: TODO: implement a proper deserialization queue instead of +// 2018-11-30: AA: TODO: implement a proper deserialization queue instead of // the coarse-grained piggybacking on the event loop function deserializeCb(lev: Level, jsonObj: any, cb: (body: LVal) => void) { - if (__isCurrentlyUsingCompiler) { - setImmediate(deserializeCb, lev, jsonObj, cb) // postpone; 2018-03-04;aa - } else { - __isCurrentlyUsingCompiler = true // prevent parallel deserialization attempts; important! -- leads to nasty - // race conditions otherwise; 2018-11-30; AA - __trustLevel = lev; - __currentCallback = cb; // obs: this is a global for this module; - // the access to it should be carefully controlled - - // we need to share this object with the callbacks - - __currentDeserializedJson = jsonObj; // obs: another global that we must be careful with - - if (jsonObj.namespaces.length > 0) { - for (let i = 0; i < jsonObj.namespaces.length; i++) { - let ns = jsonObj.namespaces[i]; - for (let j = 0; j < ns.length; j++) { - // debuglog("*s deserialize", ns[j]); - __compilerOsProcess.stdin.write(ns[j][1]); - __compilerOsProcess.stdin.write("\n") - // debuglog ("data out") - } - } - __compilerOsProcess.stdin.write("!ECHO /*-----*/\n") - } else { - // shortcutting the unnecessary interaction with the compiler - // 2018-09-20: AA - constructCurrent(""); + if (__isCurrentlyUsingCompiler) { + setImmediate(deserializeCb, lev, jsonObj, cb); // postpone; 2018-03-04;aa + } else { + __isCurrentlyUsingCompiler = true; // prevent parallel deserialization attempts; important! -- leads to nasty + // race conditions otherwise; 2018-11-30; AA + __trustLevel = lev; + __currentCallback = cb; // obs: this is a global for this module; + // the access to it should be carefully controlled + + // we need to share this object with the callbacks + + __currentDeserializedJson = jsonObj; // obs: another global that we must be careful with + + if (jsonObj.namespaces.length > 0) { + for (let i = 0; i < jsonObj.namespaces.length; i++) { + const ns = jsonObj.namespaces[i]; + for (let j = 0; j < ns.length; j++) { + // debuglog("*s deserialize", ns[j]); + __compilerOsProcess.stdin.write(ns[j][1]); + __compilerOsProcess.stdin.write("\n"); + // debuglog ("data out") } + } + __compilerOsProcess.stdin.write("!ECHO /*-----*/\n"); + } else { + // shortcutting the unnecessary interaction with the compiler + // 2018-09-20: AA + constructCurrent(""); } + } } export function deserialize(lev: Level, jsonObj: any): Promise { - return new Promise((resolve, reject) => { - deserializeCb(lev, jsonObj, (body: LVal) => { - resolve(body) - }) + return new Promise((resolve, reject) => { + deserializeCb(lev, jsonObj, (body: LVal) => { + resolve(body); }); + }); } diff --git a/rt/src/dev/id-listener.json b/rt/src/dev/id-listener.json index ec400a4c..b8eaca4d 100644 --- a/rt/src/dev/id-listener.json +++ b/rt/src/dev/id-listener.json @@ -1 +1,5 @@ -{"id":"QmeEoSjvhrSkmoBSUkEgXrazuqEP3JV8eZmoWkp83JVB1y","privKey":"CAASqQkwggSlAgEAAoIBAQC6YgZPFdCWy/OcLCSs929zlelDiCLPEi5AkIOSYju+Ru8oXXQsdZ6GbYSyYRfL/lC6NeVv9pZmmgh9GSseK3PVT/kEPzBWHd/ZDPDRBe8HQmgTG5sd4vFemUDaxV9NM7kJ3tc/zIxWnOr93TX2zQcYlbqo9ZcKlpmCga0Fb1XHj2ikIngUAlrV5wWUk+ULlBMvB8N7br8GxPkNw48x3dNrrJq5zxnvXvqnYWY9+aG+62XyCxGjtdGHd8x6y99+rPwMKanLVP/y5fLCzIDPnSmfniH6q3VBZ8ucL6ihgagPyaLNyY1X+RJ/uAScUGonses8QAY7JyCq6CIImRJxXuvjAgMBAAECggEBAJn4eLXEk7i/a9RMM1AgaJXX9gev4vGlV0hHGipHtIsQFmoGKf7Ae+EZgFHMG9iNkysBczT3RHAmN3UA4bnes6Y4lsKHYOsDavTn19kVSc15cni2iYI7BKLdf9I60uv4Gpio2rD9zcGPiCGIKRhlb8NDjhweJlS87Lv/XGvs+bQMv3XKXlu6Qi+TC1AtBqqRbAaV7qDm4Z8/YVitoTHci93S+4a7qvmTfsrjgYixdvIoilN3gRxr/0ksD42sY8lXceIlCH0JAEiaa4aqx4mrzsHYAct+ZP7ZBPCUHNSq8/54lfxfyb39XxoZ48pY3C1uu7SNFNuw0/NZYzrvJt8wOCECgYEA43tTj7SgQRtOC6ezvg8mr/5B6SJdvg93ZJEtpde9KnI9iqZDXiou62uPF0E7JIDs2dcEtcnA4VjKaffEr9TfvopqEvfk7Zc4ntHtNZj6I9QLrSDtbCwOhY0/gN/aTKk6T6xLW5vXqYKSVZURUbJgwD425u/ipNepeF4xzsydAzUCgYEA0b+x5J4i/p3XszqNsWtDMnfcbi9HRlnliB3elsHhku2swO6vt/ZyY49CRuj72QOqjFn2NB0Tu0FxZ8L+yBBDGLsLNqhh9KfZfcX7xItMc5oGANqS2kjSqgx5bQjT7xyVslHxKXrhs+2m6eMn1qCAsXlGamXG4MSZXJvY6NOmPbcCgYACgKvVq+YLcVJ1fF3U3HPPgduVxgQEAEWO/K3k4i+5lNIqgVPCaHJlsqQ7XENbTnPMnbn2igauM/zeF5S5Xn0rqngqR0Hkf0JnNOYILeuqkz2hpPgXtZBfVcN6FnxfVYlHsRyPIHLJ8Z7MhDxRisXXt5eBCOiUaa76nQatQMEFdQKBgQCbZgX7lnng4LrNrCUMfKbFfm5PKDILWlEnftHKKgzhGbwzGOQRTMLFJn95H+ZvizrRT1mMlLposvy9Xof7W6kKapHNRgWFCNKnT4bPwFC9GTE3crj4hpmlqSZRdQfoEOqLuhANpmAQOZO/ly+N4U5Xrr1P2OX241GofkK/hQeWkwKBgQDQHFDOsfvV4v538nwvG9z4GdAX32QuNwAlK1MJKJAEJT/OqenP7WFQnh3dUQ0INWY2OtM9PYYDTDYv3SpWyepQC2AqsZh8ObnnHGt3XktOIfFO00MgqPDcoKhhrihD8oVvT+xgwYaODwqZKQyFKTcQA3gUT0YXbNdzT/Keb0a/xw==","pubKey":"CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6YgZPFdCWy/OcLCSs929zlelDiCLPEi5AkIOSYju+Ru8oXXQsdZ6GbYSyYRfL/lC6NeVv9pZmmgh9GSseK3PVT/kEPzBWHd/ZDPDRBe8HQmgTG5sd4vFemUDaxV9NM7kJ3tc/zIxWnOr93TX2zQcYlbqo9ZcKlpmCga0Fb1XHj2ikIngUAlrV5wWUk+ULlBMvB8N7br8GxPkNw48x3dNrrJq5zxnvXvqnYWY9+aG+62XyCxGjtdGHd8x6y99+rPwMKanLVP/y5fLCzIDPnSmfniH6q3VBZ8ucL6ihgagPyaLNyY1X+RJ/uAScUGonses8QAY7JyCq6CIImRJxXuvjAgMBAAE="} \ No newline at end of file +{ + "id": "QmeEoSjvhrSkmoBSUkEgXrazuqEP3JV8eZmoWkp83JVB1y", + "privKey": "CAASqQkwggSlAgEAAoIBAQC6YgZPFdCWy/OcLCSs929zlelDiCLPEi5AkIOSYju+Ru8oXXQsdZ6GbYSyYRfL/lC6NeVv9pZmmgh9GSseK3PVT/kEPzBWHd/ZDPDRBe8HQmgTG5sd4vFemUDaxV9NM7kJ3tc/zIxWnOr93TX2zQcYlbqo9ZcKlpmCga0Fb1XHj2ikIngUAlrV5wWUk+ULlBMvB8N7br8GxPkNw48x3dNrrJq5zxnvXvqnYWY9+aG+62XyCxGjtdGHd8x6y99+rPwMKanLVP/y5fLCzIDPnSmfniH6q3VBZ8ucL6ihgagPyaLNyY1X+RJ/uAScUGonses8QAY7JyCq6CIImRJxXuvjAgMBAAECggEBAJn4eLXEk7i/a9RMM1AgaJXX9gev4vGlV0hHGipHtIsQFmoGKf7Ae+EZgFHMG9iNkysBczT3RHAmN3UA4bnes6Y4lsKHYOsDavTn19kVSc15cni2iYI7BKLdf9I60uv4Gpio2rD9zcGPiCGIKRhlb8NDjhweJlS87Lv/XGvs+bQMv3XKXlu6Qi+TC1AtBqqRbAaV7qDm4Z8/YVitoTHci93S+4a7qvmTfsrjgYixdvIoilN3gRxr/0ksD42sY8lXceIlCH0JAEiaa4aqx4mrzsHYAct+ZP7ZBPCUHNSq8/54lfxfyb39XxoZ48pY3C1uu7SNFNuw0/NZYzrvJt8wOCECgYEA43tTj7SgQRtOC6ezvg8mr/5B6SJdvg93ZJEtpde9KnI9iqZDXiou62uPF0E7JIDs2dcEtcnA4VjKaffEr9TfvopqEvfk7Zc4ntHtNZj6I9QLrSDtbCwOhY0/gN/aTKk6T6xLW5vXqYKSVZURUbJgwD425u/ipNepeF4xzsydAzUCgYEA0b+x5J4i/p3XszqNsWtDMnfcbi9HRlnliB3elsHhku2swO6vt/ZyY49CRuj72QOqjFn2NB0Tu0FxZ8L+yBBDGLsLNqhh9KfZfcX7xItMc5oGANqS2kjSqgx5bQjT7xyVslHxKXrhs+2m6eMn1qCAsXlGamXG4MSZXJvY6NOmPbcCgYACgKvVq+YLcVJ1fF3U3HPPgduVxgQEAEWO/K3k4i+5lNIqgVPCaHJlsqQ7XENbTnPMnbn2igauM/zeF5S5Xn0rqngqR0Hkf0JnNOYILeuqkz2hpPgXtZBfVcN6FnxfVYlHsRyPIHLJ8Z7MhDxRisXXt5eBCOiUaa76nQatQMEFdQKBgQCbZgX7lnng4LrNrCUMfKbFfm5PKDILWlEnftHKKgzhGbwzGOQRTMLFJn95H+ZvizrRT1mMlLposvy9Xof7W6kKapHNRgWFCNKnT4bPwFC9GTE3crj4hpmlqSZRdQfoEOqLuhANpmAQOZO/ly+N4U5Xrr1P2OX241GofkK/hQeWkwKBgQDQHFDOsfvV4v538nwvG9z4GdAX32QuNwAlK1MJKJAEJT/OqenP7WFQnh3dUQ0INWY2OtM9PYYDTDYv3SpWyepQC2AqsZh8ObnnHGt3XktOIfFO00MgqPDcoKhhrihD8oVvT+xgwYaODwqZKQyFKTcQA3gUT0YXbNdzT/Keb0a/xw==", + "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6YgZPFdCWy/OcLCSs929zlelDiCLPEi5AkIOSYju+Ru8oXXQsdZ6GbYSyYRfL/lC6NeVv9pZmmgh9GSseK3PVT/kEPzBWHd/ZDPDRBe8HQmgTG5sd4vFemUDaxV9NM7kJ3tc/zIxWnOr93TX2zQcYlbqo9ZcKlpmCga0Fb1XHj2ikIngUAlrV5wWUk+ULlBMvB8N7br8GxPkNw48x3dNrrJq5zxnvXvqnYWY9+aG+62XyCxGjtdGHd8x6y99+rPwMKanLVP/y5fLCzIDPnSmfniH6q3VBZ8ucL6ihgagPyaLNyY1X+RJ/uAScUGonses8QAY7JyCq6CIImRJxXuvjAgMBAAE=" +} diff --git a/rt/src/dev/id-relay.json b/rt/src/dev/id-relay.json index c09439a7..fdefc3e2 100644 --- a/rt/src/dev/id-relay.json +++ b/rt/src/dev/id-relay.json @@ -1 +1,5 @@ -{"id":"QmWJeEW5cdCtx7BNTMiJR7forsWP3VcDFup5aRpFFPY123","privKey":"CAASqQkwggSlAgEAAoIBAQDfLCDqpiso1doI5zjzlmCyYAZTvg8K4EnlX8Aj4N5HJmqIMPqoccgTFNQWZO35dLLH0e9oK+E/cCqLNF4LvQj/n0PKmPSAunZqoHtrR6qrISaa/vFEwCc8M1ObnfeK5B0KsTq28WbcwG+RlXvlkpwg+BY7WcEOnBMhp0+XAm7BVCt1GyYQyFil2+V1gan7ENVWQ49TFSuO9vT99IzqM9RiG55xv9GK0VhJr6vvJ/xVACS6BEkxdj2sOTDVJ3NJoQjf8eEsP0OGjltLlUWMMrn1NuyV9xguQWOYmnfRecgW4I7POah+GquahaRWrGHfu0Z8MIScpVd8IVdvrhc4yD8rAgMBAAECggEBALG+7tSU1kkm0gpHRrfTbF6FVmS6OjbaXmCeu2SYA9E9SpoAEJO6U7TG4QiZCGSnSoEVto0MbdFd37SRV9oXjCQz0AV7fzlLyWaxPLs8EDVOKPZH2Rd9x4IOCyglT3RCrNLIR1BPwjJN3k5gdZZqB4nGrcZFfRrKuf4SyLQoTtgQWYzsIui+dSauuxLw7WWvlj+eXJ3Dgru6/Ym/wfTUxNWvsTgruIPCPLpYMkvg76yPu9y1ID/Amo5hoCPa97tn6szDIA7MLhhicLnRlUBaslV68VfcZuHATe4yip3tZxbr844F8co1WD9T+OyvmMk7xc0OsnSR4yE2M0fFUgtVHYECgYEA+h7HNEB0CPDxmLhfNq8khxwlu/PRZb+JFqwua310GE0hxSg4SelfP6EK5PvY40Bv7MaqEePyS/L3UpkApVJl79ud4RMe1OytqAB+JOYVV8CeFSl2V4JP+mth9+uaNHPqze3bSgt6MrnycJviOu73cQLkYiBVfJQS3LelAnBM3usCgYEA5Gstr3ij2l2t9f/eu3paoKztgqS8fpOAovnu1t5gr+vksPVOBrBn1rDATExkosRHlzfgymxvH4Wcr+AUNW8ffAGEqebpzSbwMC9fntyLjgp9loxR1SMqXkqF0yZDrqsmeO015d/3jyAqZswEP5sk+iF/46wiTbmjh43ZVPhQkMECgYEAxs7IECRbFvBNWNLT+6djJXGeHLNEcde4o6jgjNf++4Hzob7CXx18dBsRickVMCz7yfxvGiFRakUJiUHMXZwNIoYyC8Ei9KPbtHoPykyIEmQsQy3dvtj5sVbBXEqNG7w3ms/BSi2tR7y9k/yT6bwgOlfOKKEC0i7wfzgJlNKmh1kCgYAH+z7DbOG81Z0ohWJRBrt39dLux7bWbW0HRNh1pZuXShTZohix3yQhuldd0yWJEna17/vo1tUjMtYAx0GthE6DVMI/9ZOh2YR3CpC6ylYOBovQ4OJTIkFuvgfjEuk2h0B25UMG30aVN7iDkwlq947ZNqZzXCZutNfj+q7nay3VgQKBgQDg/vL+VG1IS44hEQNwxC3wEQqkcHpOnGubIMt369mG+4Vz7LmjgUlnm8oyquvGq5GqraBDT18S5vD838vMAYgV5EW1nMbylz53TMxAsxgacYyN83pGsqzyEM7Ktr5EfA89hfxFiywEwbo0mYGKCGFLBBPnSWrejOlNc9Q9+eXecQ==","pubKey":"CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDfLCDqpiso1doI5zjzlmCyYAZTvg8K4EnlX8Aj4N5HJmqIMPqoccgTFNQWZO35dLLH0e9oK+E/cCqLNF4LvQj/n0PKmPSAunZqoHtrR6qrISaa/vFEwCc8M1ObnfeK5B0KsTq28WbcwG+RlXvlkpwg+BY7WcEOnBMhp0+XAm7BVCt1GyYQyFil2+V1gan7ENVWQ49TFSuO9vT99IzqM9RiG55xv9GK0VhJr6vvJ/xVACS6BEkxdj2sOTDVJ3NJoQjf8eEsP0OGjltLlUWMMrn1NuyV9xguQWOYmnfRecgW4I7POah+GquahaRWrGHfu0Z8MIScpVd8IVdvrhc4yD8rAgMBAAE="} \ No newline at end of file +{ + "id": "QmWJeEW5cdCtx7BNTMiJR7forsWP3VcDFup5aRpFFPY123", + "privKey": "CAASqQkwggSlAgEAAoIBAQDfLCDqpiso1doI5zjzlmCyYAZTvg8K4EnlX8Aj4N5HJmqIMPqoccgTFNQWZO35dLLH0e9oK+E/cCqLNF4LvQj/n0PKmPSAunZqoHtrR6qrISaa/vFEwCc8M1ObnfeK5B0KsTq28WbcwG+RlXvlkpwg+BY7WcEOnBMhp0+XAm7BVCt1GyYQyFil2+V1gan7ENVWQ49TFSuO9vT99IzqM9RiG55xv9GK0VhJr6vvJ/xVACS6BEkxdj2sOTDVJ3NJoQjf8eEsP0OGjltLlUWMMrn1NuyV9xguQWOYmnfRecgW4I7POah+GquahaRWrGHfu0Z8MIScpVd8IVdvrhc4yD8rAgMBAAECggEBALG+7tSU1kkm0gpHRrfTbF6FVmS6OjbaXmCeu2SYA9E9SpoAEJO6U7TG4QiZCGSnSoEVto0MbdFd37SRV9oXjCQz0AV7fzlLyWaxPLs8EDVOKPZH2Rd9x4IOCyglT3RCrNLIR1BPwjJN3k5gdZZqB4nGrcZFfRrKuf4SyLQoTtgQWYzsIui+dSauuxLw7WWvlj+eXJ3Dgru6/Ym/wfTUxNWvsTgruIPCPLpYMkvg76yPu9y1ID/Amo5hoCPa97tn6szDIA7MLhhicLnRlUBaslV68VfcZuHATe4yip3tZxbr844F8co1WD9T+OyvmMk7xc0OsnSR4yE2M0fFUgtVHYECgYEA+h7HNEB0CPDxmLhfNq8khxwlu/PRZb+JFqwua310GE0hxSg4SelfP6EK5PvY40Bv7MaqEePyS/L3UpkApVJl79ud4RMe1OytqAB+JOYVV8CeFSl2V4JP+mth9+uaNHPqze3bSgt6MrnycJviOu73cQLkYiBVfJQS3LelAnBM3usCgYEA5Gstr3ij2l2t9f/eu3paoKztgqS8fpOAovnu1t5gr+vksPVOBrBn1rDATExkosRHlzfgymxvH4Wcr+AUNW8ffAGEqebpzSbwMC9fntyLjgp9loxR1SMqXkqF0yZDrqsmeO015d/3jyAqZswEP5sk+iF/46wiTbmjh43ZVPhQkMECgYEAxs7IECRbFvBNWNLT+6djJXGeHLNEcde4o6jgjNf++4Hzob7CXx18dBsRickVMCz7yfxvGiFRakUJiUHMXZwNIoYyC8Ei9KPbtHoPykyIEmQsQy3dvtj5sVbBXEqNG7w3ms/BSi2tR7y9k/yT6bwgOlfOKKEC0i7wfzgJlNKmh1kCgYAH+z7DbOG81Z0ohWJRBrt39dLux7bWbW0HRNh1pZuXShTZohix3yQhuldd0yWJEna17/vo1tUjMtYAx0GthE6DVMI/9ZOh2YR3CpC6ylYOBovQ4OJTIkFuvgfjEuk2h0B25UMG30aVN7iDkwlq947ZNqZzXCZutNfj+q7nay3VgQKBgQDg/vL+VG1IS44hEQNwxC3wEQqkcHpOnGubIMt369mG+4Vz7LmjgUlnm8oyquvGq5GqraBDT18S5vD838vMAYgV5EW1nMbylz53TMxAsxgacYyN83pGsqzyEM7Ktr5EfA89hfxFiywEwbo0mYGKCGFLBBPnSWrejOlNc9Q9+eXecQ==", + "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDfLCDqpiso1doI5zjzlmCyYAZTvg8K4EnlX8Aj4N5HJmqIMPqoccgTFNQWZO35dLLH0e9oK+E/cCqLNF4LvQj/n0PKmPSAunZqoHtrR6qrISaa/vFEwCc8M1ObnfeK5B0KsTq28WbcwG+RlXvlkpwg+BY7WcEOnBMhp0+XAm7BVCt1GyYQyFil2+V1gan7ENVWQ49TFSuO9vT99IzqM9RiG55xv9GK0VhJr6vvJ/xVACS6BEkxdj2sOTDVJ3NJoQjf8eEsP0OGjltLlUWMMrn1NuyV9xguQWOYmnfRecgW4I7POah+GquahaRWrGHfu0Z8MIScpVd8IVdvrhc4yD8rAgMBAAE=" +} diff --git a/rt/src/dev/mixins.ts b/rt/src/dev/mixins.ts index 87d398da..da5405c2 100644 --- a/rt/src/dev/mixins.ts +++ b/rt/src/dev/mixins.ts @@ -1,33 +1,34 @@ type Constructor = new (...args: any[]) => T; - class XX { - field = () => { return 10 + this.x } - x : number - constructor (x: number) { - this.x = x - } + field = () => { + return 10 + this.x; + }; + x: number; + constructor(x: number) { + this.x = x; + } } - -function AddFunctionalityOne> (Base:TBase) { - return class extends Base { - timestamp = Date.now () - bar () { return this.x + 1} +function AddFunctionalityOne>(Base: TBase) { + return class extends Base { + timestamp = Date.now(); + bar() { + return this.x + 1; } + }; } -function AddFunctionalityTwo> (Base:TBase) { - return class extends Base { - foo () { return this.x + 3} +function AddFunctionalityTwo>(Base: TBase) { + return class extends Base { + foo() { + return this.x + 3; } + }; } -const AA = AddFunctionalityTwo (AddFunctionalityOne (XX)) - - -const a = new AA (19) - +const AA = AddFunctionalityTwo(AddFunctionalityOne(XX)); -console.log ("Mixins example", a.foo() + a.bar()) +const a = new AA(19); +console.log("Mixins example", a.foo() + a.bar()); diff --git a/rt/src/dev/mod-tests/a.ts b/rt/src/dev/mod-tests/a.ts index 16a1f215..8698b71b 100644 --- a/rt/src/dev/mod-tests/a.ts +++ b/rt/src/dev/mod-tests/a.ts @@ -1,6 +1,5 @@ -import {runId} from "./run_id"; +import { runId } from "./run_id"; -export function foo () { - console.log (runId) +export function foo() { + console.log(runId); } - diff --git a/rt/src/dev/mod-tests/b.ts b/rt/src/dev/mod-tests/b.ts index e64d75d4..d0f9c1e0 100644 --- a/rt/src/dev/mod-tests/b.ts +++ b/rt/src/dev/mod-tests/b.ts @@ -1,5 +1,5 @@ -import {runId} from "./run_id" +import { runId } from "./run_id"; -export function bar () { - console.log (runId) -} \ No newline at end of file +export function bar() { + console.log(runId); +} diff --git a/rt/src/dev/mod-tests/rnd_sum.js b/rt/src/dev/mod-tests/rnd_sum.js index d0bd4d87..77ca6368 100644 --- a/rt/src/dev/mod-tests/rnd_sum.js +++ b/rt/src/dev/mod-tests/rnd_sum.js @@ -1,7 +1,7 @@ -let N = 1000*1000 +let N = 1000 * 1000; let s = 0; -for (let i = 0; i < N ; i ++) { - s += Math.random() +for (let i = 0; i < N; i++) { + s += Math.random(); } -console.log (s) \ No newline at end of file +console.log(s); diff --git a/rt/src/dev/mod-tests/run_id.ts b/rt/src/dev/mod-tests/run_id.ts index 6dc9ec01..fd1b560a 100644 --- a/rt/src/dev/mod-tests/run_id.ts +++ b/rt/src/dev/mod-tests/run_id.ts @@ -1,5 +1,4 @@ -import { v4 as uuidv4} from 'uuid' -export let runId = uuidv4() - +import { v4 as uuidv4 } from "uuid"; +export let runId = uuidv4(); // export default runId diff --git a/rt/src/dev/mod-tests/x.ts b/rt/src/dev/mod-tests/x.ts index 650ad7d1..927bc31a 100644 --- a/rt/src/dev/mod-tests/x.ts +++ b/rt/src/dev/mod-tests/x.ts @@ -1,5 +1,5 @@ -import {foo} from './a' -import {bar} from './b' +import { foo } from "./a"; +import { bar } from "./b"; foo(); -bar() \ No newline at end of file +bar(); diff --git a/rt/src/dev/network.js b/rt/src/dev/network.js index 77bbb963..3f95f2fc 100644 --- a/rt/src/dev/network.js +++ b/rt/src/dev/network.js @@ -1,6 +1,6 @@ -let p2p = require('../p2p/p2p.js'); +let p2p = require("../p2p/p2p.js"); async function main() { - await p2p.startp2p(null, null); - console.log("yay"); + await p2p.startp2p(null, null); + console.log("yay"); } main(); diff --git a/rt/src/dev/network.ts b/rt/src/dev/network.ts index d2f83841..b2b6d523 100644 --- a/rt/src/dev/network.ts +++ b/rt/src/dev/network.ts @@ -1,10 +1,8 @@ -let p2p = require('../p2p/p2p.js') +let p2p = require("../p2p/p2p.js"); -async function foo () { +async function foo() { await p2p.startp2p(null, null); - console.log ("yay") - + console.log("yay"); } - -foo () \ No newline at end of file +foo(); diff --git a/rt/src/dev/relay.ts b/rt/src/dev/relay.ts index 59c035ff..a6aa9419 100644 --- a/rt/src/dev/relay.ts +++ b/rt/src/dev/relay.ts @@ -1,394 +1,384 @@ -'use strict' - - - -const TCP = require ('libp2p-tcp') -const MulticastDNS = require ( 'libp2p-mdns') -const WS = require ( 'libp2p-websockets') -const Bootstrap = require ( 'libp2p-bootstrap') -const KadDHT = require ( 'libp2p-kad-dht') -const Multiplex = require ( 'libp2p-mplex') -const SECIO = require( 'libp2p-secio') -const Libp2p = require('libp2p') -import * as fs from 'node:fs'; -import yargs from 'yargs' -const PeerId = require("peer-id") -const PeerInfo = require ("peer-info") -const AggregateError = require('aggregate-error'); -const pipe = require('it-pipe') - - - -let logLevel = 'debug' - -const logger = require('../logger.js').mkLogger('p2p',logLevel); -const info = (x: any) => logger.info(x) -const debug = (x: string) => logger.debug(x) +"use strict"; + +const TCP = require("libp2p-tcp"); +const MulticastDNS = require("libp2p-mdns"); +const WS = require("libp2p-websockets"); +const Bootstrap = require("libp2p-bootstrap"); +const KadDHT = require("libp2p-kad-dht"); +const Multiplex = require("libp2p-mplex"); +const SECIO = require("libp2p-secio"); +const Libp2p = require("libp2p"); +import * as fs from "node:fs"; +import yargs from "yargs"; +const PeerId = require("peer-id"); +const PeerInfo = require("peer-info"); +const AggregateError = require("aggregate-error"); +const pipe = require("it-pipe"); + +let logLevel = "debug"; + +const logger = require("../logger.js").mkLogger("p2p", logLevel); +const info = (x: any) => logger.info(x); +const debug = (x: string) => logger.debug(x); const error = (x: string) => logger.error(x); -const multiaddr = require('multiaddr') -const _PROTOCOL = "/TroupeRelay/" -const _PORT = 5555 +const multiaddr = require("multiaddr"); +const _PROTOCOL = "/TroupeRelay/"; +const _PORT = 5555; - - - -let _lastTick:any = new Date () +let _lastTick: any = new Date(); let _tickCounter = 0; -function healthMonitor () { - let now:any = new Date () - debug (`>> Tick counter ${_tickCounter ++} ${now - _lastTick}`); +function healthMonitor() { + let now: any = new Date(); + debug(`>> Tick counter ${_tickCounter++} ${now - _lastTick}`); _lastTick = now; - setTimeout (healthMonitor, 1000) + setTimeout(healthMonitor, 1000); } -healthMonitor() - -const bootstrapers = [ - '/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z', - '/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', - '/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', - '/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm', - '/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', - '/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64', - '/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd', - '/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3', -// // '/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx', -// '/ip6/2604:a880:1:20::1f9:9001/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z', -// '/ip6/2604:a880:1:20::203:d001/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', -// '/ip6/2604:a880:0:1010::23:d001/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm', -// '/ip6/2400:6180:0:d0::151:6001/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', -// '/ip6/2604:a880:800:10::4a:5001/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64', -// '/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd', -// '/ip6/2a03:b0c0:1:d0::e7:1/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3', -// // '/ip6/2604:a880:1:20::1d9:6001/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx', -// '/dns4/wss0.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic', -// '/dns4/wss1.bootstrap.libp2p.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6', -// '/dns4/node0.preload.ipfs.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic', -// '/dns4/node1.preload.ipfs.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6' -] - -let node ; - -function nPeers( ) { - return node.metrics.peers.length +healthMonitor(); + +const bootstrapers = [ + "/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", + "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", + "/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", + "/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", + "/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", + "/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", + "/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", + "/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3", + // // '/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx', + // '/ip6/2604:a880:1:20::1f9:9001/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z', + // '/ip6/2604:a880:1:20::203:d001/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', + // '/ip6/2604:a880:0:1010::23:d001/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm', + // '/ip6/2400:6180:0:d0::151:6001/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', + // '/ip6/2604:a880:800:10::4a:5001/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64', + // '/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd', + // '/ip6/2a03:b0c0:1:d0::e7:1/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3', + // // '/ip6/2604:a880:1:20::1d9:6001/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx', + // '/dns4/wss0.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic', + // '/dns4/wss1.bootstrap.libp2p.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6', + // '/dns4/node0.preload.ipfs.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic', + // '/dns4/node1.preload.ipfs.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6' +]; + +let node; + +function nPeers() { + return node.metrics.peers.length; } - -function displayNodePeerInfo () { - let peerInfo = node.peerInfo - debug ("--- node's peer info") - peerInfo.multiaddrs.forEach( m => { - debug (m.toString() ) - }); - debug ("--- ") +function displayNodePeerInfo() { + let peerInfo = node.peerInfo; + debug("--- node's peer info"); + peerInfo.multiaddrs.forEach((m) => { + debug(m.toString()); + }); + debug("--- "); } -async function initNode(id, ishop:boolean = false) { - let pi = new PeerInfo(id); - let port = ishop? _PORT : 0 +async function initNode(id, ishop: boolean = false) { + let pi = new PeerInfo(id); + let port = ishop ? _PORT : 0; - pi.multiaddrs.add(`/ip4/0.0.0.0/tcp/${port}`); - pi.multiaddrs.add( multiaddr(`/p2p/${id.toB58String()}`)) - // pi.multiaddrs.add(`/ip4/0.0.0.0/tcp/${port}/p2p/${id.toB58String()}`); + pi.multiaddrs.add(`/ip4/0.0.0.0/tcp/${port}`); + pi.multiaddrs.add(multiaddr(`/p2p/${id.toB58String()}`)); + // pi.multiaddrs.add(`/ip4/0.0.0.0/tcp/${port}/p2p/${id.toB58String()}`); - if (!ishop) { - bootstrapers.unshift (`/dns4/troupe-lbs-primary.askarov.net/tcp/${_PORT}/p2p/`) - } + if (!ishop) { + bootstrapers.unshift( + `/dns4/troupe-lbs-primary.askarov.net/tcp/${_PORT}/p2p/`, + ); + } - node = await Libp2p.create ({ - peerInfo : pi, - modules: { - transport: [TCP], - streamMuxer: [Multiplex], - connEncryption: [SECIO], - peerDiscovery: [MulticastDNS,Bootstrap], - dht: KadDHT + node = await Libp2p.create({ + peerInfo: pi, + modules: { + transport: [TCP], + streamMuxer: [Multiplex], + connEncryption: [SECIO], + peerDiscovery: [MulticastDNS, Bootstrap], + dht: KadDHT, + }, + metrics: { enabled: true }, + dialer: { + maxParallelDials: 150, // How many multiaddrs we can dial in parallel + maxDialsPerPeer: 8, // How many multiaddrs we can dial per peer, in parallel + dialTimeout: 10e3, // 15 second dial timeout per peer + }, + config: { + peerDiscovery: { + autoDial: true, + mdns: { + interval: 1e3, + enabled: true, + }, + bootstrap: { + interval: 1000, + list: bootstrapers, + enabled: true, + }, }, - metrics: {enabled: true}, - dialer: { - maxParallelDials: 150, // How many multiaddrs we can dial in parallel - maxDialsPerPeer: 8, // How many multiaddrs we can dial per peer, in parallel - dialTimeout: 10e3 // 15 second dial timeout per peer + dht: { + enabled: false, + kBucketSize: 20, }, - config: { - peerDiscovery: { - autoDial:true, - mdns: { - interval: 1e3, - enabled: true - }, - bootstrap: { - interval: 1000, - list : bootstrapers, - enabled: true - } - }, - dht: { - enabled: false, - kBucketSize: 20, - }, - relay:{enabled: true, hop : { enabled: ishop, active:ishop } } - } - }) + relay: { enabled: true, hop: { enabled: ishop, active: ishop } }, + }, + }); - node.on('error', (err) => { - error (`Error in p2p: ${err}`); - }) - + node.on("error", (err) => { + error(`Error in p2p: ${err}`); + }); - node.on('peer:discovery', (peer) => { - // debug (`Discovered: ${peer.id.toB58String()}`) - }) - - node.on ('peer:connect', (peerInfo)=>{ - tryPending (); - let idStr = peerInfo.id.toB58String(); - debug (`++ Connect: ${idStr} ${nPeers()}` ); - }) + node.on("peer:discovery", (peer) => { + // debug (`Discovered: ${peer.id.toB58String()}`) + }); - + node.on("peer:connect", (peerInfo) => { + tryPending(); + let idStr = peerInfo.id.toB58String(); + debug(`++ Connect: ${idStr} ${nPeers()}`); + }); - await node.start(); + await node.start(); - debug ("Node created"); + debug("Node created"); - displayNodePeerInfo() - return node; + displayNodePeerInfo(); + return node; } let __networkPending = []; -function addPending (t) { - __networkPending.push (t); +function addPending(t) { + __networkPending.push(t); } function tryPending() { - if (__networkPending.length > 0 ) { - let n = __networkPending.length; + if (__networkPending.length > 0) { + let n = __networkPending.length; - debug (`# # # # Connect trigger: try Pending ${n}`); + debug(`# # # # Connect trigger: try Pending ${n}`); - for ( let i = 0; i < n; i++) { - // debug (`discovery trigger ${key}`) - let t = __networkPending.shift (); - t () ; - } - } + for (let i = 0; i < n; i++) { + // debug (`discovery trigger ${key}`) + let t = __networkPending.shift(); + t(); + } + } } async function getPeerInfo(id) { - const peerId = id - return new Promise ((resolve, reject) => { - let n_attempts = 0; - async function try_find_peer () { - if (node.peerStore.has(peerId)) { - debug ("peer info is in the store") - resolve (node.peerStore.get(peerId)) - } else { - try { - debug ("calling peerRouting.findPeer") - const peerInfo = await node.peerRouting.findPeer (peerId, {timeout:1000}); - debug ("findPeer returned") - resolve (peerInfo); - } catch (err) { - debug (`try_find_peer exception`) - if (nPeers() > 0 ) { - n_attempts ++ ; - } - - if (err instanceof AggregateError) { - for (let e of err) { - debug (`Find peer error with code: ${e}, ${e.code}`) - } - } else { - debug (`Find peer error: ${err.toString()}`) - throw err; - } - - if (n_attempts > 5) { - resolve (new PeerInfo(id)) - // reject (err);h - } else { - debug (`try_find_peer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`) - addPending (try_find_peer); - } - } - } + const peerId = id; + return new Promise((resolve, reject) => { + let n_attempts = 0; + async function try_find_peer() { + if (node.peerStore.has(peerId)) { + debug("peer info is in the store"); + resolve(node.peerStore.get(peerId)); + } else { + try { + debug("calling peerRouting.findPeer"); + const peerInfo = await node.peerRouting.findPeer(peerId, { + timeout: 1000, + }); + debug("findPeer returned"); + resolve(peerInfo); + } catch (err) { + debug(`try_find_peer exception`); + if (nPeers() > 0) { + n_attempts++; } - try_find_peer (); - }); -} + if (err instanceof AggregateError) { + for (let e of err) { + debug(`Find peer error with code: ${e}, ${e.code}`); + } + } else { + debug(`Find peer error: ${err.toString()}`); + throw err; + } -async function getPeerInfoWithRelay(id) { - let pi:any = await getPeerInfo (id) - console.log ("RELAY ID IS" , _relay_id) - if (_relay_id) { - pi.multiaddrs.add( multiaddr(`/p2p/${_relay_id}/p2p-circuit/p2p/${id.toB58String()}`)) + if (n_attempts > 5) { + resolve(new PeerInfo(id)); + // reject (err);h + } else { + debug( + `try_find_peer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`, + ); + addPending(try_find_peer); + } + } + } } - return pi + try_find_peer(); + }); } -async function dialNode (id) { - function tryDial () { - let i = 0; - let timeout = 2000 - return new Promise((resolve, reject) =>{ - async function iterate() { - try { - let peerInfo : any = await getPeerInfoWithRelay (id); - debug ("PEER INFO OBTAINED") - debug (`>> Dialing to:`) - peerInfo.multiaddrs.forEach( m => { - debug (m.toString() ) - }); - debug (">> << ") - - debug (`trying to dial, attempt number {i}`) - const { stream } = await node.dialProtocol(peerInfo, _PROTOCOL) - resolve ( stream ); - } catch ( err ) { - processExpectedNetworkErrors (err); - // if the error is suppressed we move on to trying 10 times - // with exponential backoff - // 2020-02-10; AA: TODO: this code has a hardcoded constant - if (i <= 10) { - debug (`dial failed, going to retry in ${timeout} seconds`) - setTimeout (iterate, timeout ) - timeout *= 2 - i ++ ; - } else { - reject (err); - } - } - } - iterate () - }) +async function getPeerInfoWithRelay(id) { + let pi: any = await getPeerInfo(id); + console.log("RELAY ID IS", _relay_id); + if (_relay_id) { + pi.multiaddrs.add( + multiaddr(`/p2p/${_relay_id}/p2p-circuit/p2p/${id.toB58String()}`), + ); + } + return pi; +} + +async function dialNode(id) { + function tryDial() { + let i = 0; + let timeout = 2000; + return new Promise((resolve, reject) => { + async function iterate() { + try { + let peerInfo: any = await getPeerInfoWithRelay(id); + debug("PEER INFO OBTAINED"); + debug(`>> Dialing to:`); + peerInfo.multiaddrs.forEach((m) => { + debug(m.toString()); + }); + debug(">> << "); + + debug(`trying to dial, attempt number {i}`); + const { stream } = await node.dialProtocol(peerInfo, _PROTOCOL); + resolve(stream); + } catch (err) { + processExpectedNetworkErrors(err); + // if the error is suppressed we move on to trying 10 times + // with exponential backoff + // 2020-02-10; AA: TODO: this code has a hardcoded constant + if (i <= 10) { + debug(`dial failed, going to retry in ${timeout} seconds`); + setTimeout(iterate, timeout); + timeout *= 2; + i++; + } else { + reject(err); + } + } } - let stream = await tryDial () - debug (">> dial successful << ") + iterate(); + }); + } + let stream = await tryDial(); + debug(">> dial successful << "); - debug ("DIAL OK"); + debug("DIAL OK"); } -function processExpectedNetworkErrors (err) { +function processExpectedNetworkErrors(err) { if (err instanceof AggregateError) { - for (const e of err ) { - processExpectedNetworkErrors (e) + for (const e of err) { + processExpectedNetworkErrors(e); } } else { switch (err.code) { - case 'ENETUNREACH': - error (`${err.toString()}`) + case "ENETUNREACH": + error(`${err.toString()}`); break; - case 'ENOTFOUND': - error (`${err.toString()}`) + case "ENOTFOUND": + error(`${err.toString()}`); break; - case 'ECONNRESET': - error (`${err.toString()}`) + case "ECONNRESET": + error(`${err.toString()}`); break; - case 'ERR_TRANSPORT_DIAL_FAILED': - error (`${err.toString()}`) + case "ERR_TRANSPORT_DIAL_FAILED": + error(`${err.toString()}`); break; - case 'ABORT_ERR': - error (`${err.toString()}`) + case "ABORT_ERR": + error(`${err.toString()}`); break; - case 'ECONNREFUSED': - error ((`${err.toString()}`)) + case "ECONNREFUSED": + error(`${err.toString()}`); break; - case 'ERR_HOP_REQUEST_FAILED': - error ((`${err.toString()}`)) + case "ERR_HOP_REQUEST_FAILED": + error(`${err.toString()}`); break; - case 'ERR_NO_DIAL_MULTIADDRS': + case "ERR_NO_DIAL_MULTIADDRS": break; default: - error (`Unhandled error case ${err.code}`) + error(`Unhandled error case ${err.code}`); throw err; - } - } + } + } } - - - -async function getIdFromFile (fname) { - let s = await fs.promises.readFile(fname, {encoding:'utf8'}); - let json = await JSON.parse (s); +async function getIdFromFile(fname) { + let s = await fs.promises.readFile(fname, { encoding: "utf8" }); + let json = await JSON.parse(s); let id = await PeerId.createFromJSON(json); return id; } let _keepAliveCounter = 0; let _relay_id = null; -async function keepAliveRelay (id) { - async function f () { +async function keepAliveRelay(id) { + async function f() { try { const conn = await node.dial(id); - const {stream} = await node.dialProtocol (id, "/trouperelay/keepalive") - debug (`the stream is ${stream}`) - const peerId = conn.remotePeer - _relay_id = peerId.toB58String() - debug (`dialed to relay ${_keepAliveCounter++}`) - pipe ( stream - , async (source) => { - for await (const msg of source ) { - console.log (`relay says ${msg}`) - } - } - ); - } catch (err ) { + const { stream } = await node.dialProtocol(id, "/trouperelay/keepalive"); + debug(`the stream is ${stream}`); + const peerId = conn.remotePeer; + _relay_id = peerId.toB58String(); + debug(`dialed to relay ${_keepAliveCounter++}`); + pipe(stream, async (source) => { + for await (const msg of source) { + console.log(`relay says ${msg}`); + } + }); + } catch (err) { if (err instanceof AggregateError) { for (let e of err) { - debug (`Error dialing relay server: ${e.code}`) + debug(`Error dialing relay server: ${e.code}`); } - } - else { - error (`error dialing relay ${err}`); + } else { + error(`error dialing relay ${err}`); } } - setTimeout(f, 5000) + setTimeout(f, 5000); } - f () + f(); } - -async function main () { - let serverid = await getIdFromFile (yargs.argv.serverid) - let listenerid ; - switch (yargs.argv.mode) { - case 'relay': - await initNode (serverid, true) - await node.handle("/trouperelay/keepalive", async ({connection, stream}) => { - debug (`relay alive signal on ${connection.toString()}`); - pipe (['hello from Nodejs relay'], stream.sink) - }) - break; - case 'listener': - debug ("listener") - listenerid = await getIdFromFile (yargs.argv.listenerid) - await initNode(listenerid, false) - // keepAliveRelay ("QmWJeEW5cdCtx7BNTMiJR7forsWP3VcDFup5aRpFFPY123"); - keepAliveRelay(`/dns4/troupe-lbs-primary.askarov.net/tcp/${_PORT}/`) - await node.handle(_PROTOCOL, async ({connection, stream, protocol}) => { - debug ("PROTOCOL CONNECTION") - }) - - break; - case 'dialer': - debug ("listener") - let dialerid = await PeerId.create(); - listenerid = await getIdFromFile (yargs.argv.listenerid) - await initNode(dialerid, false) - // keepAliveRelay ("QmWJeEW5cdCtx7BNTMiJR7forsWP3VcDFup5aRpFFPY123"); - keepAliveRelay(`/dns4/troupe-lbs-primary.askarov.net/tcp/${_PORT}/`) - await dialNode(listenerid) - } +async function main() { + let serverid = await getIdFromFile(yargs.argv.serverid); + let listenerid; + switch (yargs.argv.mode) { + case "relay": + await initNode(serverid, true); + await node.handle( + "/trouperelay/keepalive", + async ({ connection, stream }) => { + debug(`relay alive signal on ${connection.toString()}`); + pipe(["hello from Nodejs relay"], stream.sink); + }, + ); + break; + case "listener": + debug("listener"); + listenerid = await getIdFromFile(yargs.argv.listenerid); + await initNode(listenerid, false); + // keepAliveRelay ("QmWJeEW5cdCtx7BNTMiJR7forsWP3VcDFup5aRpFFPY123"); + keepAliveRelay(`/dns4/troupe-lbs-primary.askarov.net/tcp/${_PORT}/`); + await node.handle(_PROTOCOL, async ({ connection, stream, protocol }) => { + debug("PROTOCOL CONNECTION"); + }); + + break; + case "dialer": + debug("listener"); + let dialerid = await PeerId.create(); + listenerid = await getIdFromFile(yargs.argv.listenerid); + await initNode(dialerid, false); + // keepAliveRelay ("QmWJeEW5cdCtx7BNTMiJR7forsWP3VcDFup5aRpFFPY123"); + keepAliveRelay(`/dns4/troupe-lbs-primary.askarov.net/tcp/${_PORT}/`); + await dialNode(listenerid); + } } +process.on("unhandledRejection", processExpectedNetworkErrors); +process.on("uncaughtException", processExpectedNetworkErrors); -process.on('unhandledRejection', processExpectedNetworkErrors) -process.on('uncaughtException', processExpectedNetworkErrors); - - -main () \ No newline at end of file +main(); diff --git a/rt/src/dev/startdustexample.js b/rt/src/dev/startdustexample.js index 6bffb04e..665858d7 100644 --- a/rt/src/dev/startdustexample.js +++ b/rt/src/dev/startdustexample.js @@ -1,57 +1,58 @@ -'use strict' +"use strict"; -const Libp2p = require('libp2p') -const Id = require('peer-id') -const Info = require('peer-info') -const multiaddr = require('multiaddr') -const pull = require('pull-stream') +const Libp2p = require("libp2p"); +const Id = require("peer-id"); +const Info = require("peer-info"); +const multiaddr = require("multiaddr"); +const pull = require("pull-stream"); -const Stardust = require('libp2p-stardust') +const Stardust = require("libp2p-stardust"); -Id.create((err, id) => { // generate a random id for testing - if (err) { throw err } // re-throw any error that might have occured +Id.create((err, id) => { + // generate a random id for testing + if (err) { + throw err; + } // re-throw any error that might have occured - const peerInfo = new Info(id) - peerInfo.multiaddrs.add(multiaddr('/dns4/stardust.mkg20001.io/tcp/443/wss/p2p-stardust/')) + const peerInfo = new Info(id); + peerInfo.multiaddrs.add( + multiaddr("/dns4/stardust.mkg20001.io/tcp/443/wss/p2p-stardust/"), + ); - const stardust = new Stardust({ id }) // the id is required to prove the client's identity to the server + const stardust = new Stardust({ id }); // the id is required to prove the client's identity to the server const modules = { - transport: [ - stardust - ], - discovery: [ - stardust.discovery - ] - } + transport: [stardust], + discovery: [stardust.discovery], + }; - const node = new Libp2p(modules, peerInfo) // create a libp2p node with the stardust transport + const node = new Libp2p(modules, peerInfo); // create a libp2p node with the stardust transport - node.handle('/test/1.0.0', (protocol, conn) => { + node.handle("/test/1.0.0", (protocol, conn) => { pull( - pull.values(['hello']), + pull.values(["hello"]), conn, pull.map((s) => s.toString()), - pull.log() - ) - }) + pull.log(), + ); + }); node.start((err) => { if (err) { - throw err + throw err; } - node.dial(peerInfo, '/test/1.0.0', (err, conn) => { + node.dial(peerInfo, "/test/1.0.0", (err, conn) => { if (err) { - throw err + throw err; } pull( - pull.values(['hello from the other side']), + pull.values(["hello from the other side"]), conn, pull.map((s) => s.toString()), - pull.log() - ) - }) - }) -}) \ No newline at end of file + pull.log(), + ); + }); + }); +}); diff --git a/rt/src/downgrading.mts b/rt/src/downgrading.mts index 666815cc..a531da97 100644 --- a/rt/src/downgrading.mts +++ b/rt/src/downgrading.mts @@ -1,70 +1,105 @@ -import { LCopyVal } from './Lval.mjs'; -import { assertIsNTuple, assertIsAuthority, assertIsLevel } from './Asserts.mjs' -import { __unit } from './UnitVal.mjs'; -import { lub, flowsTo, okToDeclassify, okToEndorse} from './Level.mjs' -import { DowngradeResult, DowngradeDimension, DowngradeErrorReason } from './DowngradeEnums.mjs'; +import { LCopyVal } from "./Lval.mjs"; import { - formatIntegrityMismatchMsg, - formatConfidentialityMismatchMsg, - formatPiniBlockingLevelMismatchMsg, - formatValueInsufficientAuthorityMsg -} from './DowngradeFormatter.mjs'; - + assertIsNTuple, + assertIsAuthority, + assertIsLevel, +} from "./Asserts.mjs"; +import { __unit } from "./UnitVal.mjs"; +import { lub, flowsTo, okToDeclassify, okToEndorse } from "./Level.mjs"; +import { + DowngradeResult, + DowngradeDimension, + DowngradeErrorReason, +} from "./DowngradeEnums.mjs"; +import { + formatIntegrityMismatchMsg, + formatConfidentialityMismatchMsg, + formatPiniBlockingLevelMismatchMsg, + formatValueInsufficientAuthorityMsg, +} from "./DowngradeFormatter.mjs"; -function stringOfDowngrader (d) { - switch (d) { - case DowngradeDimension.CONFIDENTIALITY: { - return "declassification" - } - case DowngradeDimension.INTEGRITY: { - return "endorsement" - } +function stringOfDowngrader(d) { + switch (d) { + case DowngradeDimension.CONFIDENTIALITY: { + return "declassification"; } + case DowngradeDimension.INTEGRITY: { + return "endorsement"; + } + } } -export function downgrader (runtime, dimension:DowngradeDimension, isNMIFC: boolean ) { - return (arg => { - assertIsNTuple(arg, 3); - let argv = arg.val; - let data = argv[0]; - let auth = argv[1]; - assertIsAuthority(auth); - let toLevV = argv[2]; - assertIsLevel(toLevV); - let pc = runtime.$t.pc; - let levFrom = data.lev; - let bl = runtime.$t.bl ; - let lev_to = toLevV.val - const downgradeKindString = stringOfDowngrader (dimension) +export function downgrader( + runtime, + dimension: DowngradeDimension, + isNMIFC: boolean, +) { + return (arg) => { + assertIsNTuple(arg, 3); + const argv = arg.val; + const data = argv[0]; + const auth = argv[1]; + assertIsAuthority(auth); + const toLevV = argv[2]; + assertIsLevel(toLevV); + const pc = runtime.$t.pc; + const levFrom = data.lev; + const bl = runtime.$t.bl; + const lev_to = toLevV.val; + const downgradeKindString = stringOfDowngrader(dimension); - const dg_f = - dimension == DowngradeDimension.CONFIDENTIALITY ? okToDeclassify : okToEndorse; - const ok_to_downgrade_result: DowngradeResult = - dg_f(levFrom, lev_to, auth.val.authorityLevel, bl, isNMIFC) + const dg_f = + dimension == DowngradeDimension.CONFIDENTIALITY + ? okToDeclassify + : okToEndorse; + const ok_to_downgrade_result: DowngradeResult = dg_f( + levFrom, + lev_to, + auth.val.authorityLevel, + bl, + isNMIFC, + ); - if (ok_to_downgrade_result.kind === "SUCCESS") { - let r = new LCopyVal(data, lub(lev_to, pc, arg.lev, auth.lev)); - return runtime.ret(r) - } else { - let errorMessage = ""; - switch (ok_to_downgrade_result.reason) { - case DowngradeErrorReason.INTEGRITY_MISMATCH: - errorMessage = formatIntegrityMismatchMsg(downgradeKindString, levFrom, lev_to); - break; - case DowngradeErrorReason.CONFIDENTIALITY_MISMATCH: - errorMessage = formatConfidentialityMismatchMsg(downgradeKindString, levFrom, lev_to); - break; - case DowngradeErrorReason.BLOCKING_LEVEL_MISMATCH: - errorMessage = formatPiniBlockingLevelMismatchMsg(downgradeKindString, bl, lev_to); - break; - case DowngradeErrorReason.INSUFFICIENT_AUTHORITY: - errorMessage = formatValueInsufficientAuthorityMsg(downgradeKindString, levFrom, auth.val.authorityLevel, lev_to); - break; - default: - const _exhaustiveCheck: never = ok_to_downgrade_result.reason; - errorMessage = `Unhandled downgrade error reason: ${_exhaustiveCheck} for ${downgradeKindString}`; - } - runtime.$t.threadError(errorMessage); - } - }) + if (ok_to_downgrade_result.kind === "SUCCESS") { + const r = new LCopyVal(data, lub(lev_to, pc, arg.lev, auth.lev)); + return runtime.ret(r); + } else { + let errorMessage = ""; + switch (ok_to_downgrade_result.reason) { + case DowngradeErrorReason.INTEGRITY_MISMATCH: + errorMessage = formatIntegrityMismatchMsg( + downgradeKindString, + levFrom, + lev_to, + ); + break; + case DowngradeErrorReason.CONFIDENTIALITY_MISMATCH: + errorMessage = formatConfidentialityMismatchMsg( + downgradeKindString, + levFrom, + lev_to, + ); + break; + case DowngradeErrorReason.BLOCKING_LEVEL_MISMATCH: + errorMessage = formatPiniBlockingLevelMismatchMsg( + downgradeKindString, + bl, + lev_to, + ); + break; + case DowngradeErrorReason.INSUFFICIENT_AUTHORITY: + errorMessage = formatValueInsufficientAuthorityMsg( + downgradeKindString, + levFrom, + auth.val.authorityLevel, + lev_to, + ); + break; + default: + const _exhaustiveCheck: never = ok_to_downgrade_result.reason; + errorMessage = `Unhandled downgrade error reason: ${_exhaustiveCheck} for ${downgradeKindString}`; + } + runtime.$t.threadError(errorMessage); + } + }; } diff --git a/rt/src/levels/DCLabels/cnf.mts b/rt/src/levels/DCLabels/cnf.mts index 43de75d1..f0e569b9 100644 --- a/rt/src/levels/DCLabels/cnf.mts +++ b/rt/src/levels/DCLabels/cnf.mts @@ -1,130 +1,130 @@ -import { CONJ_OPERATOR - , CAT_DELIM_LEFT - , CAT_DELIM_RIGHT - , DISJ_OPERATOR - // , DC_EMPTY_CAT - , Delimiterification - // , DC_DELIM_RIGHT - // , DC_DELIM_LEFT - // , DC_EMPTY_CNF - } from './dcl_pp_config.mjs' +import { + CONJ_OPERATOR, + CAT_DELIM_LEFT, + CAT_DELIM_RIGHT, + DISJ_OPERATOR, + // , DC_EMPTY_CAT + Delimiterification, + // , DC_DELIM_RIGHT + // , DC_DELIM_LEFT + // , DC_EMPTY_CNF +} from "./dcl_pp_config.mjs"; export class Category { - toJSON(): any { - return [...this.labels]; + toJSON(): any { + return [...this.labels]; + } + + static fromJSON(o: [string]): Category { + return new Category(new Set(o)); + } + + labels: Set; + constructor(l: Set) { + this.labels = l; + } + + stringRep(pp_empty_cat): string { + if (this.labels.size == 0) { + return pp_empty_cat; } - - static fromJSON (o:[string]) : Category { - return new Category (new Set(o)); - } - - labels: Set - constructor(l: Set) { - this.labels = l; - } - - stringRep(pp_empty_cat): string { - if (this.labels.size == 0) { - return pp_empty_cat; - } - let r = Array.from(this.labels.values()).join(DISJ_OPERATOR); - return r; - } - + const r = Array.from(this.labels.values()).join(DISJ_OPERATOR); + return r; + } } export class CNF { - toJSON() { - return [...this.categories].map (x => x.toJSON()) + toJSON() { + return [...this.categories].map((x) => x.toJSON()); + } + + static fromJSON(o: [[string]]): CNF { + return new CNF(new Set(o.map((x) => Category.fromJSON(x)))); + } + + categories: Set; + constructor(c: Set) { + this.categories = c; + } + + equals(other: CNF): boolean { + return implies(this, other) && implies(other, this); + } + + stringRep(pp_literals, parenthesize = Delimiterification.AsNeeded): string { + if (this.categories.size == 0) { + return pp_literals.trueLit; } - static fromJSON (o:[[string]]): CNF { - return (new CNF (new Set (o.map (x => Category.fromJSON(x))))) - } - - categories: Set - constructor(c: Set) { - this.categories = c + let p: boolean; + switch (parenthesize) { + case Delimiterification.AsNeeded: + p = this.categories.size > 1; + break; + case Delimiterification.Always: + p = true; + break; + case Delimiterification.None: + p = false; + break; } - - equals(other: CNF): boolean { - return implies(this, other) && implies(other, this); + function g(x: Category): string { + const s: string = x.stringRep(pp_literals.falseLit); + const q = p && x.labels.size > 1; + if (q) { + return CAT_DELIM_LEFT + s + CAT_DELIM_RIGHT; + } else return s; } - stringRep(pp_literals, parenthesize = Delimiterification.AsNeeded): string { - if (this.categories.size == 0) { - return pp_literals.trueLit; - } - - let p: boolean; - switch (parenthesize) { - case Delimiterification.AsNeeded: - p = this.categories.size > 1; - break; - case Delimiterification.Always: - p = true; - break; - case Delimiterification.None: - p = false; - break; - } - function g(x: Category): string { - let s: string = x.stringRep(pp_literals.falseLit); - let q = p && (x.labels.size > 1) - if (q) { - return (CAT_DELIM_LEFT + s + CAT_DELIM_RIGHT) - } else - return s - } - - return Array.from( - this.categories.values().map(g)). - sort((a,b) => a.localeCompare(b)).join(CONJ_OPERATOR) - } + return Array.from(this.categories.values().map(g)) + .sort((a, b) => a.localeCompare(b)) + .join(CONJ_OPERATOR); + } } export function implies(X: CNF, Y: CNF): boolean { - for (let y of Y.categories) y_loop: { - for (let x of X.categories) { - let set_x: any = x.labels; - // console.log (x, " ?? ", y, " -- ", set_x.isSubsetOf (y.labels)) - if (set_x.isSubsetOf(y.labels)) { - break y_loop; - } + for (const y of Y.categories) + y_loop: { + for (const x of X.categories) { + const set_x: any = x.labels; + // console.log (x, " ?? ", y, " -- ", set_x.isSubsetOf (y.labels)) + if (set_x.isSubsetOf(y.labels)) { + break y_loop; } - return false; + } + return false; } - return true; + return true; } export function conjunction(X: CNF, Y: CNF): CNF { - if (implies(X, Y)) { - return X - } - if (implies(Y, X)) { - return Y; - } - return new CNF(X.categories.union(Y.categories)) + if (implies(X, Y)) { + return X; + } + if (implies(Y, X)) { + return Y; + } + return new CNF(X.categories.union(Y.categories)); } export function disjunction(X: CNF, Y: CNF): CNF { - if (implies(X, Y)) { - return Y; - } - if (implies(Y, X)) { - return X; - } - - let newCategories: Set = new Set(); - - for (const xCat of X.categories) { - for (const yCat of Y.categories) { - newCategories.add(new Category(xCat.labels.union(yCat.labels))); - } + if (implies(X, Y)) { + return Y; + } + if (implies(Y, X)) { + return X; + } + + const newCategories = new Set(); + + for (const xCat of X.categories) { + for (const yCat of Y.categories) { + newCategories.add(new Category(xCat.labels.union(yCat.labels))); } + } - return new CNF(newCategories); + return new CNF(newCategories); } export const CNF_TRUE: CNF = new CNF(new Set()); -export const CNF_FALSE: CNF = new CNF(new Set([new Category(new Set())])) \ No newline at end of file +export const CNF_FALSE: CNF = new CNF(new Set([new Category(new Set())])); diff --git a/rt/src/levels/DCLabels/dcl_pp_config.mts b/rt/src/levels/DCLabels/dcl_pp_config.mts index 471c7fd4..f9f5ec01 100644 --- a/rt/src/levels/DCLabels/dcl_pp_config.mts +++ b/rt/src/levels/DCLabels/dcl_pp_config.mts @@ -1,28 +1,30 @@ export enum Delimiterification { - None, - AsNeeded, - Always + None, + AsNeeded, + Always, } -export const DISJ_OPERATOR = "|" -export const CONJ_OPERATOR = "&" -export const CAT_DELIM_LEFT = "(" -export const CAT_DELIM_RIGHT = ")" -export const DC_DELIM_LEFT = "<" -export const DC_DELIM_RIGHT = ">" -export const DC_DELIM_LEFT_V1 = "{" -export const DC_DELIM_RIGHT_V1 = "}" -export const DC_DELIM_SEP = ";" -export const DC_TRUST_ROOT = "#ROOT" -export const DC_IFC_TOP = "#TOP" +export const DISJ_OPERATOR = "|"; +export const CONJ_OPERATOR = "&"; +export const CAT_DELIM_LEFT = "("; +export const CAT_DELIM_RIGHT = ")"; +export const DC_DELIM_LEFT = "<"; +export const DC_DELIM_RIGHT = ">"; +export const DC_DELIM_LEFT_V1 = "{"; +export const DC_DELIM_RIGHT_V1 = "}"; +export const DC_DELIM_SEP = ";"; +export const DC_TRUST_ROOT = "#ROOT"; +export const DC_IFC_TOP = "#TOP"; // export const DC_EMPTY_CAT = "\#FALSE" // export const DC_EMPTY_CNF = "\#TRUE" -export const DC_CONF_LITERALS = { trueLit : "#null-confidentiality" - , falseLit: "#root-confidentiality" - } +export const DC_CONF_LITERALS = { + trueLit: "#null-confidentiality", + falseLit: "#root-confidentiality", +}; -export const DC_INTG_LITERALS = { trueLit : "#null-integrity" - , falseLit: "#root-integrity" - } \ No newline at end of file +export const DC_INTG_LITERALS = { + trueLit: "#null-integrity", + falseLit: "#root-integrity", +}; diff --git a/rt/src/levels/DCLabels/dclabel.mts b/rt/src/levels/DCLabels/dclabel.mts index 028b33d2..7ab254ff 100644 --- a/rt/src/levels/DCLabels/dclabel.mts +++ b/rt/src/levels/DCLabels/dclabel.mts @@ -1,18 +1,36 @@ -import { AbstractLevel, AbstractLevelSystem } from '../../AbstractLevel.mjs'; -import { DowngradeKind, DowngradeDimension, DowngradeResult, DowngradeErrorReason, DowngradeResultSuccess, DowngradeError } from '../../DowngradeEnums.mjs'; -import { tagsetStringRep } from '../tagsets.mjs'; -import { Category - , CNF - , CNF_FALSE - , CNF_TRUE - , implies - , conjunction - , disjunction - } from './cnf.mjs' -import { DC_CONF_LITERALS, DC_DELIM_LEFT, DC_DELIM_LEFT_V1, DC_DELIM_RIGHT, DC_DELIM_RIGHT_V1, DC_DELIM_SEP, DC_IFC_TOP, DC_INTG_LITERALS, DC_TRUST_ROOT } from './dcl_pp_config.mjs'; - -import { getCliArgs, TroupeCliArg } from '../../TroupeCliArgs.mjs'; -import { mkLogger } from '../../logger.mjs'; +import { AbstractLevel, AbstractLevelSystem } from "../../AbstractLevel.mjs"; +import { + DowngradeKind, + DowngradeDimension, + DowngradeResult, + DowngradeErrorReason, + DowngradeResultSuccess, + DowngradeError, +} from "../../DowngradeEnums.mjs"; +import { tagsetStringRep } from "../tagsets.mjs"; +import { + Category, + CNF, + CNF_FALSE, + CNF_TRUE, + implies, + conjunction, + disjunction, +} from "./cnf.mjs"; +import { + DC_CONF_LITERALS, + DC_DELIM_LEFT, + DC_DELIM_LEFT_V1, + DC_DELIM_RIGHT, + DC_DELIM_RIGHT_V1, + DC_DELIM_SEP, + DC_IFC_TOP, + DC_INTG_LITERALS, + DC_TRUST_ROOT, +} from "./dcl_pp_config.mjs"; + +import { getCliArgs, TroupeCliArg } from "../../TroupeCliArgs.mjs"; +import { mkLogger } from "../../logger.mjs"; // const argv = getCliArgs(); // const logLevel = argv[TroupeCliArg.Debug] ? 'debug' : 'info'; @@ -20,39 +38,39 @@ import { mkLogger } from '../../logger.mjs'; // const debug = x => logger.debug(x); export class DCLabel extends AbstractLevel { - integrity: CNF - confidentiality: CNF + integrity: CNF; + confidentiality: CNF; - get dataLevel () { - return IFC_BOT - } + get dataLevel() { + return IFC_BOT; + } - _cachedStringRepresentation: string = null ; + _cachedStringRepresentation: string = null; - constructor(c: CNF, i: CNF) { - super () - this.confidentiality = c; - this.integrity = i; - - } + constructor(c: CNF, i: CNF) { + super(); + this.confidentiality = c; + this.integrity = i; + } - flowsTo(other: DCLabel): boolean { - /* + flowsTo(other: DCLabel): boolean { + /* S_2 ==> S1 I1 ==> I_2 ------------------------------- flowsto assuming this = - - */ - return implies(other.confidentiality, this.confidentiality) - && implies(this.integrity, other.integrity); - } + */ + return ( + implies(other.confidentiality, this.confidentiality) && + implies(this.integrity, other.integrity) + ); + } - actsFor(other:DCLabel) : boolean { - /* - returns true if this label actsfor another label. + actsFor(other: DCLabel): boolean { + /* + returns true if this label actsfor another label. S_1 ==> S2 I_1 ==> I_2 ------------------------------- @@ -61,132 +79,123 @@ export class DCLabel extends AbstractLevel { assuming this = */ - return implies(this.confidentiality, other.confidentiality) - && implies(this.integrity, other.integrity); - - } - - equals(other: DCLabel): boolean { - return this.flowsTo(other) && other.flowsTo(this); - } - - isTagsetCompatible() : boolean | Set { - if (this.confidentiality.categories.size == 0) { - return false; - } + return ( + implies(this.confidentiality, other.confidentiality) && + implies(this.integrity, other.integrity) + ); + } - if (this.integrity.categories.size != 1) { - return false; - } - const _the_integrity: Category = - this.integrity.categories.values().next().value; - - const s :Set = _the_integrity.labels; - - - for (let cat of this.confidentiality.categories) { - if (cat.labels.size == 1) { - // debug (`isTagsetCompatible: cat.labels.size is 1`); - const l:string = cat.labels.values().next().value; - // debug (`checking the label ${l}`) - if (!s.has(l)) { - return false; - } - } else { - // debug (`isTagsetCompatible: cat.labels.size is ${cat.labels.size}`); - return false; - } - } + equals(other: DCLabel): boolean { + return this.flowsTo(other) && other.flowsTo(this); + } - return s; + isTagsetCompatible(): boolean | Set { + if (this.confidentiality.categories.size == 0) { + return false; } - - stringRep(): string { - if (this._cachedStringRepresentation) { - return this._cachedStringRepresentation + if (this.integrity.categories.size != 1) { + return false; + } + const _the_integrity: Category = this.integrity.categories + .values() + .next().value; + + const s: Set = _the_integrity.labels; + + for (const cat of this.confidentiality.categories) { + if (cat.labels.size == 1) { + // debug (`isTagsetCompatible: cat.labels.size is 1`); + const l: string = cat.labels.values().next().value; + // debug (`checking the label ${l}`) + if (!s.has(l)) { + return false; } - - if (this.flowsTo(IFC_BOT)) { - this._cachedStringRepresentation = - DC_DELIM_LEFT_V1 + DC_DELIM_RIGHT_V1 - } else - if (IFC_TOP.flowsTo(this)) { - this._cachedStringRepresentation = - DC_DELIM_LEFT_V1 + DC_IFC_TOP + DC_DELIM_RIGHT_V1 - } else - if (TRUST_ROOT.flowsTo(this) && this.flowsTo(TRUST_ROOT)) { - this._cachedStringRepresentation = - DC_DELIM_LEFT_V1 + DC_TRUST_ROOT + DC_DELIM_RIGHT_V1 - } else { - // debug (`calling isTagsetCompatible`) - let s = this.isTagsetCompatible() - // debug (`returning from isTagsetCompatible: ${s}`) - if (s) { - this._cachedStringRepresentation = - tagsetStringRep (s as Set ); - } else { - this._cachedStringRepresentation = - DC_DELIM_LEFT + - this.confidentiality.stringRep(DC_CONF_LITERALS) + - DC_DELIM_SEP + - this.integrity.stringRep(DC_INTG_LITERALS) + - DC_DELIM_RIGHT - } - } - - return this._cachedStringRepresentation; + } else { + // debug (`isTagsetCompatible: cat.labels.size is ${cat.labels.size}`); + return false; + } } - - /* - - L1 ⊔ L2 = ); + } else { + this._cachedStringRepresentation = + DC_DELIM_LEFT + + this.confidentiality.stringRep(DC_CONF_LITERALS) + + DC_DELIM_SEP + + this.integrity.stringRep(DC_INTG_LITERALS) + + DC_DELIM_RIGHT; + } } + return this._cachedStringRepresentation; + } + /* - toJSON () { - return { confidentiality: this.confidentiality.toJSON() - , integrity: this.integrity.toJSON() - } - } - - static fromJSON (o: { confidentiality: [[string]] - ; integrity: [[string]]; }) { - return new DCLabel(CNF.fromJSON(o.confidentiality) - , CNF.fromJSON(o.integrity)) - } + L1 ⊔ L2 = (most secret, least trusted) (TOP TRUST = most secret, most trusted) @@ -194,133 +203,134 @@ export class DCLabel extends AbstractLevel { ⊥ = (most public, least garbage) */ -/// see fabric paper https://www.cs.cornell.edu/andru/papers/jfabric/jfabric.pdf +/// see fabric paper https://www.cs.cornell.edu/andru/papers/jfabric/jfabric.pdf /// for the intuition about trust - -export const IFC_BOT = new DCLabel(CNF_TRUE, CNF_FALSE) -export const IFC_TOP = new DCLabel(CNF_FALSE, CNF_TRUE) -export const TRUST_NULL = new DCLabel(CNF_TRUE, CNF_TRUE) -export const TRUST_ROOT = new DCLabel(CNF_FALSE, CNF_FALSE) - +export const IFC_BOT = new DCLabel(CNF_TRUE, CNF_FALSE); +export const IFC_TOP = new DCLabel(CNF_FALSE, CNF_TRUE); +export const TRUST_NULL = new DCLabel(CNF_TRUE, CNF_TRUE); +export const TRUST_ROOT = new DCLabel(CNF_FALSE, CNF_FALSE); export class DCLevelSystem extends AbstractLevelSystem { - BOT = IFC_BOT - TOP = IFC_TOP - NULL = TRUST_NULL - ROOT = TRUST_ROOT - flowsTo(a: DCLabel, b: DCLabel): boolean { - return a.flowsTo (b); + BOT = IFC_BOT; + TOP = IFC_TOP; + NULL = TRUST_NULL; + ROOT = TRUST_ROOT; + flowsTo(a: DCLabel, b: DCLabel): boolean { + return a.flowsTo(b); + } + + actsFor(a: DCLabel, b: DCLabel): boolean { + return a.actsFor(b); + } + + glb(a: DCLabel, b: DCLabel): DCLabel { + return a.meet(b); + } + + // 2025-05-24: TODO + // - make a better version of this + lub(...ls: DCLabel[]): DCLabel { + if (ls.length == 0) { + return IFC_BOT; } - - actsFor(a: DCLabel, b: DCLabel): boolean { - return a.actsFor (b); + let r = ls[0]; + for (let i = 1; i < ls.length; i++) { + r = r.join(ls[i]); } - - - - glb(a: DCLabel, b: DCLabel): DCLabel { - return a.meet(b) + return r; + } + + fromV1String(str2: string): DCLabel { + const str1 = str2.trim(); + let str = + str1.startsWith("{") && str1.endsWith("}") + ? str1.substring(1, str1.length - 1) + : str1; + + str = str.trim(); + if (str == "") { + return IFC_BOT; } - // 2025-05-24: TODO - // - make a better version of this - lub(...ls: DCLabel[]): DCLabel { - if (ls.length == 0) { - return IFC_BOT - } - let r = ls[0] - for (let i = 1; i < ls.length; i ++) { - r = r.join (ls[i]) - } - return r; + if (str == "#TOP") { + return IFC_TOP; } - fromV1String (str2:string):DCLabel { - const str1 = str2.trim(); - let str = str1.startsWith ("{") && str1.endsWith ("}") ? - str1.substring(1, str1.length - 1) : - str1; - - str = str.trim(); - if (str == "") { - return IFC_BOT - } - - if (str == "#TOP") { - return IFC_TOP; - } + const s = new Set(); + const tags = str.split(","); + const dcs = tags.map((t) => DCLabel.fromSingleTag(t)); + return this.lub(...dcs); + } + + okToDowngradeGeneric(kind: DowngradeKind, dimension: DowngradeDimension) { + return ( + l_from: DCLabel, + l_to: DCLabel, + l_auth: DCLabel, + bl: DCLabel, + isNMIFC = false, + ): DowngradeResult => { + if (kind === DowngradeKind.VALUE && !this.flowsTo(bl, l_to)) { + return DowngradeError(DowngradeErrorReason.BLOCKING_LEVEL_MISMATCH); + } + + /* - let s = new Set (); - const tags = str.split(','); - const dcs = tags.map (t => DCLabel.fromSingleTag(t)) - return this.lub (...dcs) - } - - - okToDowngradeGeneric (kind: DowngradeKind, dimension: DowngradeDimension) { - return (( l_from : DCLabel - , l_to : DCLabel - , l_auth : DCLabel - , bl : DCLabel - , isNMIFC: boolean = false ) : DowngradeResult => { - - - - if (kind === DowngradeKind.VALUE && !this.flowsTo(bl, l_to)) { - return DowngradeError(DowngradeErrorReason.BLOCKING_LEVEL_MISMATCH); - } - - /* - S_auth /\ S_to ==> S_from I_auth /\ I_from ==> I_to ----------------------------------------------------------- flowsto_{l_auth} - - */ - - switch (dimension) { - case DowngradeDimension.INTEGRITY: - if (!l_from.confidentiality.equals(l_to.confidentiality)) { - return DowngradeError(DowngradeErrorReason.CONFIDENTIALITY_MISMATCH); - } - break; - case DowngradeDimension.CONFIDENTIALITY: - if (!l_from.integrity.equals(l_to.integrity)) { - return DowngradeError(DowngradeErrorReason.INTEGRITY_MISMATCH); - } - break; - default: - const _exhaustiveCheck: never = dimension; - throw new Error (`Unhandled DowngradeDimension: ${_exhaustiveCheck}`) - } - - let enough_confidentiality = - implies( conjunction ( l_auth.confidentiality - , l_to.confidentiality) - , l_from.confidentiality) - let enough_integrity = - implies( conjunction ( l_auth.integrity - , l_from.integrity) - , l_to.integrity) - - if (!(enough_confidentiality && enough_integrity)) { - return DowngradeError(DowngradeErrorReason.INSUFFICIENT_AUTHORITY); - } - - return DowngradeResultSuccess; - } - )} - - okToEndorse = this.okToDowngradeGeneric (DowngradeKind.VALUE, DowngradeDimension.INTEGRITY) - okToDeclassify = this.okToDowngradeGeneric (DowngradeKind.VALUE, DowngradeDimension.CONFIDENTIALITY) - okToDowngrade (kind: DowngradeKind, dimension: DowngradeDimension) { - return this.okToDowngradeGeneric(kind, dimension); - } + */ + switch (dimension) { + case DowngradeDimension.INTEGRITY: + if (!l_from.confidentiality.equals(l_to.confidentiality)) { + return DowngradeError( + DowngradeErrorReason.CONFIDENTIALITY_MISMATCH, + ); + } + break; + case DowngradeDimension.CONFIDENTIALITY: + if (!l_from.integrity.equals(l_to.integrity)) { + return DowngradeError(DowngradeErrorReason.INTEGRITY_MISMATCH); + } + break; + default: + const _exhaustiveCheck: never = dimension; + throw new Error(`Unhandled DowngradeDimension: ${_exhaustiveCheck}`); + } + + const enough_confidentiality = implies( + conjunction(l_auth.confidentiality, l_to.confidentiality), + l_from.confidentiality, + ); + const enough_integrity = implies( + conjunction(l_auth.integrity, l_from.integrity), + l_to.integrity, + ); + + if (!(enough_confidentiality && enough_integrity)) { + return DowngradeError(DowngradeErrorReason.INSUFFICIENT_AUTHORITY); + } + + return DowngradeResultSuccess; + }; + } + + okToEndorse = this.okToDowngradeGeneric( + DowngradeKind.VALUE, + DowngradeDimension.INTEGRITY, + ); + okToDeclassify = this.okToDowngradeGeneric( + DowngradeKind.VALUE, + DowngradeDimension.CONFIDENTIALITY, + ); + okToDowngrade(kind: DowngradeKind, dimension: DowngradeDimension) { + return this.okToDowngradeGeneric(kind, dimension); + } } -export const mkLevel = DCLabel.fromJSON -export type Level = DCLabel -export const levels = new DCLevelSystem () \ No newline at end of file +export const mkLevel = DCLabel.fromJSON; +export type Level = DCLabel; +export const levels = new DCLevelSystem(); diff --git a/rt/src/levels/lohi.js b/rt/src/levels/lohi.js index 0dd33a72..cca235e8 100644 --- a/rt/src/levels/lohi.js +++ b/rt/src/levels/lohi.js @@ -1,5 +1,5 @@ -/* 2020-05-19; this method is commented for convenience to avoid - having the IDE erroneously suggest importing it +/* 2020-05-19; this method is commented for convenience to avoid + having the IDE erroneously suggest importing it */ /* @@ -38,7 +38,7 @@ levels.mkLevel = (x) => { if ( x === "secret" || x === "`{secret}`" ) { return levels.HIGH; } else { - if ( x === "public" || x === "{public}" ) { + if ( x === "public" || x === "{public}" ) { return levels.LOW } else { @@ -48,4 +48,4 @@ levels.mkLevel = (x) => { } module.exports = levels; -*/ \ No newline at end of file +*/ diff --git a/rt/src/levels/singleton.mts b/rt/src/levels/singleton.mts index b1a12254..5992cf0c 100644 --- a/rt/src/levels/singleton.mts +++ b/rt/src/levels/singleton.mts @@ -1,54 +1,42 @@ - -import { AbstractLevel } from '../AbstractLevel.mjs' - +import { AbstractLevel } from "../AbstractLevel.mjs"; export class Singleton extends AbstractLevel { - isTop = true - get dataLevel () { - return __theLevel; // observe delayed - } - constructor () { - super(); - } - - stringRep () { - return "{-}" - - } + isTop = true; + get dataLevel() { + return __theLevel; // observe delayed + } + constructor() { + super(); + } + + stringRep() { + return "{-}"; + } } -let __theLevel = new Singleton() - +const __theLevel = new Singleton(); -export function lub (...ls:Singleton[]):Singleton { - return __theLevel +export function lub(...ls: Singleton[]): Singleton { + return __theLevel; } - -export function glb (l1:Singleton, l2:Singleton):Singleton { - return __theLevel +export function glb(l1: Singleton, l2: Singleton): Singleton { + return __theLevel; } -export function flowsTo (l1:Singleton, l2:Singleton):boolean { - return true; - +export function flowsTo(l1: Singleton, l2: Singleton): boolean { + return true; } - - -function fromString (str2): Singleton { - return __theLevel +function fromString(str2): Singleton { + return __theLevel; } - - -export function lubs (x) { - return __theLevel - +export function lubs(x) { + return __theLevel; } - -export let BOT = __theLevel -export let TOP = __theLevel -export let mkLevel = fromString -// export type Level = Singleton \ No newline at end of file +export const BOT = __theLevel; +export const TOP = __theLevel; +export const mkLevel = fromString; +// export type Level = Singleton diff --git a/rt/src/levels/tagsets.mts b/rt/src/levels/tagsets.mts index 8f9359f1..40d29a42 100644 --- a/rt/src/levels/tagsets.mts +++ b/rt/src/levels/tagsets.mts @@ -1,84 +1,71 @@ -import { mkLogger } from '../logger.mjs' -const logger = mkLogger('TAGSETS'); -const info = x => logger.info(x) -const debug = x => logger.debug(x) - -import { AbstractLevel, AbstractLevelSystem } from '../AbstractLevel.mjs' - - -function stringRep (T:Set ) { - let n = T.size - let s = "{"; - let i = 0; - let R = Array.from (T.values()).sort(); - - R.forEach( t => { - s += t; - if (++ i < n ) { - s += "," - } - }) - s += "}" - return s; +import { mkLogger } from "../logger.mjs"; +const logger = mkLogger("TAGSETS"); +const info = (x) => logger.info(x); +const debug = (x) => logger.debug(x); + +import { AbstractLevel, AbstractLevelSystem } from "../AbstractLevel.mjs"; + +function stringRep(T: Set) { + const n = T.size; + let s = "{"; + let i = 0; + const R = Array.from(T.values()).sort(); + + R.forEach((t) => { + s += t; + if (++i < n) { + s += ","; + } + }); + s += "}"; + return s; } +export const tagsetStringRep = stringRep; -export const tagsetStringRep = stringRep - -let __cache = {} - +const __cache = {}; class TagLevel extends AbstractLevel { - lev: any - isTop: boolean; - __stringRep : string ; - - constructor (lev:any, s = null) { - s = s || stringRep (lev); - super(); - this.lev = lev; - this.__stringRep = s - - } - - stringRep () { - return this.__stringRep; - } - - get dataLevel () { - return botLevel; - } - - + lev: any; + isTop: boolean; + __stringRep: string; + + constructor(lev: any, s = null) { + s = s || stringRep(lev); + super(); + this.lev = lev; + this.__stringRep = s; + } + + stringRep() { + return this.__stringRep; + } + + get dataLevel() { + return botLevel; + } } -// Factory method for creating tag levels -// Observe that it makes use of caching -function createTagLevel0 ( lev ) { - let s = stringRep (lev) - __cache [s] = __cache[s] || (new TagLevel (lev)) - return __cache[s] +// Factory method for creating tag levels +// Observe that it makes use of caching +function createTagLevel0(lev) { + const s = stringRep(lev); + __cache[s] = __cache[s] || new TagLevel(lev); + return __cache[s]; } -let botLevel = createTagLevel0 (new Set ()) +const botLevel = createTagLevel0(new Set()); // botLevel.dataLevel = botLevel ; // 2021-03-19; hacky; AA - -function createTagLevel ( lev ) { - let obj = createTagLevel0 (lev); - // obj.dataLevel = botLevel ; - return obj; +function createTagLevel(lev) { + const obj = createTagLevel0(lev); + // obj.dataLevel = botLevel ; + return obj; } - - -let topLevel = new TagLevel ({}, "{#TOP}"); +const topLevel = new TagLevel({}, "{#TOP}"); topLevel.isTop = true; - - - - /** * TODO Review and document the semantics of this. * Seems to simply strip off "{" and "}" from the beginning and end of the string (if both exist), @@ -87,33 +74,32 @@ topLevel.isTop = true; * for caching, this unchecked input set is rendered into a string, and it seems that the actual tag set * of the resulting Level also just becomes this set.). */ -function fromString (str2): TagLevel { - // debug (str2.toString()) - // the implementation is slightly over-protected - // to deal with {} issues; 2018-09-19; AA - - const str1 = str2.trim(); - const str = str1.startsWith ("{") && str1.endsWith ("}") ? - str1.substring(1, str1.length - 1) : - str1; - - if (str == "#TOP") { - return topLevel; +function fromString(str2): TagLevel { + // debug (str2.toString()) + // the implementation is slightly over-protected + // to deal with {} issues; 2018-09-19; AA + + const str1 = str2.trim(); + const str = + str1.startsWith("{") && str1.endsWith("}") + ? str1.substring(1, str1.length - 1) + : str1; + + if (str == "#TOP") { + return topLevel; + } + + const s = new Set(); + const tags = str.split(","); + + tags.map((t) => { + if (t != "") { + s.add(t.trim().toLowerCase()); } - - let s = new Set (); - const tags = str.split(','); - - tags.map ( t => { - if ( t != '') { - s.add (t.trim().toLowerCase()); - } - }); - return createTagLevel (s); + }); + return createTagLevel(s); } - - // export function lubs (x) { // if (x.length == 0) { // return BOT; @@ -126,82 +112,77 @@ function fromString (str2): TagLevel { // } // } +class TagLevelSystem extends AbstractLevelSystem { + BOT = botLevel; + TOP = topLevel; + NULL = botLevel; + ROOT = topLevel; + lub(...ls: TagLevel[]): TagLevel { + if (ls.length == 0) { + return botLevel; + } + if (ls.length == 2) { + if (ls[0] == ls[1]) { + return ls[0]; + } + } + const s = new Set(); + for (const l of ls) { + if (l == topLevel) { + return topLevel; + } + l.lev.forEach((t) => s.add(t)); + } + return createTagLevel(s); + } + glb(l1: TagLevel, l2: TagLevel): TagLevel { + if (l1 == topLevel) { + return l2; + } -class TagLevelSystem extends AbstractLevelSystem { - BOT = botLevel - TOP = topLevel - NULL = botLevel - ROOT = topLevel + if (l2 == topLevel) { + return l1; + } - lub (...ls:TagLevel[]):TagLevel { - if (ls.length == 0) { - return botLevel; - } - if (ls.length == 2) { - if (ls[0] == ls[1]) { - return ls[0] - } - } + const s = new Set(); + l1.lev.forEach((t) => { + if (l2.lev.has(t)) { + s.add(t); + } + }); + return createTagLevel(s); + } - let s = new Set (); - for (let l of ls) { - if (l == topLevel) { - return topLevel - } - l.lev.forEach(t => s.add(t)); - } - return createTagLevel (s); + flowsTo(l1: TagLevel, l2: TagLevel): boolean { + if (l1 == l2) { + return true; } - - glb (l1:TagLevel, l2:TagLevel):TagLevel { - if (l1 == topLevel) { - return l2; - } - - if (l2 == topLevel ) { - return l1; - } - - let s = new Set(); - l1.lev.forEach ( - t => { - if (l2.lev.has(t)) { - s.add(t); - } - }); - return createTagLevel (s); + if (l2 == topLevel) { + return true; } - flowsTo (l1:TagLevel, l2:TagLevel):boolean { - if (l1 == l2) { - return true; - } - if (l2 == topLevel) { - return true; - } - - if (l1 == topLevel) { - return (l2 == topLevel); - } - - const iter = l1.lev.entries(); - for (let t1 of iter) { - if (!l2.lev.has(t1[0])) { - return false; - } - } - - return true; + if (l1 == topLevel) { + return l2 == topLevel; } - actsFor (l1, l2) : boolean { - return this.flowsTo(l2, l1) + const iter = l1.lev.entries(); + for (const t1 of iter) { + if (!l2.lev.has(t1[0])) { + return false; + } } + + return true; + } + + actsFor(l1, l2): boolean { + return this.flowsTo(l2, l1); + } } -export let mkLevel = fromString -export type Level = TagLevel -export const levels = new TagLevelSystem (); \ No newline at end of file +export const mkLevel = fromString; +export type Level = TagLevel; +export const levels = new TagLevelSystem(); diff --git a/rt/src/loadLibs.mts b/rt/src/loadLibs.mts index 9ba07192..931ba1bd 100644 --- a/rt/src/loadLibs.mts +++ b/rt/src/loadLibs.mts @@ -1,29 +1,29 @@ /* 2020-05-19: AA This code is deprecated */ -'use strict' +"use strict"; -import * as fs from 'node:fs' +import * as fs from "node:fs"; -import { mkLogger } from './logger.mjs' -const logger = mkLogger('lib') +import { mkLogger } from "./logger.mjs"; +const logger = mkLogger("lib"); -const info = x => logger.info(x) -const debug = x => logger.debug(x) +const info = (x) => logger.info(x); +const debug = (x) => logger.debug(x); -const __libcache = {} +const __libcache = {}; export function loadLibsAsync(obj, rtObj, cb) { - let libs = obj.libs - obj.libs = {} + const libs = obj.libs; + obj.libs = {}; function iterateAsync(n) { if (n < libs.length) { - let lib = libs[n].lib; - let decl = libs[n].decl; + const lib = libs[n].lib; + const decl = libs[n].decl; - const key = lib +"." + decl + const key = lib + "." + decl; if (__libcache[key]) { - debug ('lib cache hit on: ' + key) - obj.libs[key]=__libcache[key]; + debug("lib cache hit on: " + key); + obj.libs[key] = __libcache[key]; setImmediate(iterateAsync, n + 1); return; } @@ -31,60 +31,55 @@ export function loadLibsAsync(obj, rtObj, cb) { // 1. Find the file -- note that we load all the libs from a default // location - let filename = process.env.TROUPE + "/lib/out/" + lib + ".js" - - + const filename = process.env.TROUPE + "/lib/out/" + lib + ".js"; // 2. Load the file -- note that this is an asynchronous operation - fs.readFile(filename, 'utf8', (err, input) => { - + fs.readFile(filename, "utf8", (err, input) => { // File read operation finished; we are now in the callbacak that has - // been asynchronously called by the node runtime - + // been asynchronously called by the node runtime + // TODO: check for error! 2018-07-03: aa // 3. Create a JS class (function) from it - let Lib:any = new Function('rt', input); + const Lib: any = new Function("rt", input); // 4. We create a "new" instance of the resulting class - let libinstance = new Lib(rtObj); - + const libinstance = new Lib(rtObj); // load dependent libraries?? - - // libinstance.loadlibs (() => + + // libinstance.loadlibs (() => loadLibsAsync(libinstance, rtObj, () => { // 5. Execute .export() function to obtain the table note - this is a // regular JS function (generated by the compiler) that we just call - // here + // here rtObj.setLibloadMode(); // 2019-01-03: AA; Hack - let table = libinstance.export().val.toArray(); - rtObj.setNormalMode(); // 2019-01-03: AA; EOH + const table = libinstance.export().val.toArray(); + rtObj.setNormalMode(); // 2019-01-03: AA; EOH // 6. Lookup in the resulting table for (let i = 0; i < table.length; i++) { - let name = table[i].val[0].val; - let libf = table[i].val[1].val + const name = table[i].val[0].val; + const libf = table[i].val[1].val; if (name == decl) { // We store the resulting function in the object that was provided - // to us as an argument + // to us as an argument obj.libs[key] = libf; - __libcache [key] = libf; + __libcache[key] = libf; break; } } // Next iteration - iterateAsync (n + 1); - }) - }) - + iterateAsync(n + 1); + }); + }); } else { // We are done processing the lib files. Transferring control back to the - // callback. The callback is either + // callback. The callback is either // // a. The next thing in the initialization, if this is the first time we // are loading libraries -- typically scheduler init, etc (see `start` @@ -97,5 +92,5 @@ export function loadLibsAsync(obj, rtObj, cb) { cb(); } } - iterateAsync (0); + iterateAsync(0); } diff --git a/rt/src/loadLibsAsync.mts b/rt/src/loadLibsAsync.mts index 12adc2ca..0be9a581 100644 --- a/rt/src/loadLibsAsync.mts +++ b/rt/src/loadLibsAsync.mts @@ -1,76 +1,75 @@ -'use strict' -import * as fs from 'node:fs' -import * as levels from './Level.mjs'; -const { readFile } = fs.promises +"use strict"; +import * as fs from "node:fs"; +import * as levels from "./Level.mjs"; +const { readFile } = fs.promises; -import { mkLogger } from './logger.mjs' -const logger = mkLogger('lib') +import { mkLogger } from "./logger.mjs"; +const logger = mkLogger("lib"); -const info = x => logger.info(x) -const debug = x => logger.debug(x) +const info = (x) => logger.info(x); +const debug = (x) => logger.debug(x); -const __libcache = {} +const __libcache = {}; export async function loadLibsAsync(obj, rtObj) { - let libs = obj.libs - obj.libs = {} - for (let n = 0; n < libs.length; n++) { - let lib = libs[n].lib; - let decl = libs[n].decl; - - const key = lib + "." + decl - if (__libcache[key]) { - debug('lib cache hit on: ' + key) - obj.libs[key] = __libcache[key]; - continue - } - - // 1. Find the file -- note that we load all the libs from a default - // location + const libs = obj.libs; + obj.libs = {}; + for (let n = 0; n < libs.length; n++) { + const lib = libs[n].lib; + const decl = libs[n].decl; + + const key = lib + "." + decl; + if (__libcache[key]) { + debug("lib cache hit on: " + key); + obj.libs[key] = __libcache[key]; + continue; + } - let filename = process.env.TROUPE + "/lib/out/" + lib + ".js" + // 1. Find the file -- note that we load all the libs from a default + // location - // 2. Load the file -- note that this is an asynchronous operation - let input = await readFile(filename, 'utf8') + const filename = process.env.TROUPE + "/lib/out/" + lib + ".js"; - // File read operation finished; we are now in the callbacak that has - // been asynchronously called by the node runtime + // 2. Load the file -- note that this is an asynchronous operation + const input = await readFile(filename, "utf8"); - // TODO: check for error! 2018-07-03: aa + // File read operation finished; we are now in the callbacak that has + // been asynchronously called by the node runtime - // 3. Create a JS class (function) from it - let Lib: any = new Function('rt', input); + // TODO: check for error! 2018-07-03: aa - // 4. We create a "new" instance of the resulting class + // 3. Create a JS class (function) from it + const Lib: any = new Function("rt", input); - let libinstance = new Lib(rtObj); + // 4. We create a "new" instance of the resulting class + const libinstance = new Lib(rtObj); - // load dependent libraries?? + // load dependent libraries?? - // libinstance.loadlibs (() => - await loadLibsAsync(libinstance, rtObj) + // libinstance.loadlibs (() => + await loadLibsAsync(libinstance, rtObj); - // 5. Execute .export() function to obtain the table note - this is a - // regular JS function (generated by the compiler) that we just call - // here + // 5. Execute .export() function to obtain the table note - this is a + // regular JS function (generated by the compiler) that we just call + // here - rtObj.setLibloadMode(); // 2019-01-03: AA; Hack - let table = libinstance.export({__dataLevel:levels.BOT}).val.toArray(); - rtObj.setNormalMode(); // 2019-01-03: AA; EOH + rtObj.setLibloadMode(); // 2019-01-03: AA; Hack + const table = libinstance.export({ __dataLevel: levels.BOT }).val.toArray(); + rtObj.setNormalMode(); // 2019-01-03: AA; EOH - // 6. Lookup in the resulting table + // 6. Lookup in the resulting table - for (let i = 0; i < table.length; i++) { - let name = table[i].val[0].val; - let libf = table[i].val[1].val - if (name == decl) { - // We store the resulting function in the object that was provided - // to us as an argument - obj.libs[key] = libf; - __libcache[key] = libf; - break; - } - } + for (let i = 0; i < table.length; i++) { + const name = table[i].val[0].val; + const libf = table[i].val[1].val; + if (name == decl) { + // We store the resulting function in the object that was provided + // to us as an argument + obj.libs[key] = libf; + __libcache[key] = libf; + break; + } } + } } diff --git a/rt/src/logger.mts b/rt/src/logger.mts index 6f8586bb..26ca8cc4 100644 --- a/rt/src/logger.mts +++ b/rt/src/logger.mts @@ -1,39 +1,31 @@ // 2018-07-21: AA; A very basic logging setup ... Not particularly attached to // this library or this way of doing things, but this still beats console -// outputs. +// outputs. -import winston_pkg from 'winston'; -const { createLogger, format, transports } = winston_pkg +import winston_pkg from "winston"; +const { createLogger, format, transports } = winston_pkg; const { combine, timestamp, label, printf } = format; -import { isColorEnabled } from './colorConfig.mjs'; +import { isColorEnabled } from "./colorConfig.mjs"; -const myFormat = printf(info => { +const myFormat = printf((info) => { // return `${info.timestamp} ${info.level}: ${info.message}`; return `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`; }); -export function mkLogger (l, level='info') { - - const consol = new transports.Console(); +export function mkLogger(l, level = "info") { + const consol = new transports.Console(); // Conditionally include colorize based on color configuration - const formatList = [ - label({ label: `${l}` }), - timestamp(), - myFormat - ]; - + const formatList = [label({ label: `${l}` }), timestamp(), myFormat]; + if (isColorEnabled()) { formatList.unshift(format.colorize()); } - let x = createLogger({ - level : level, // comment out this file to remove debug messages - format: combine(...formatList), - transports: [consol] - }); - return x + const x = createLogger({ + level: level, // comment out this file to remove debug messages + format: combine(...formatList), + transports: [consol], + }); + return x; } - - - diff --git a/rt/src/p2p/Pushable.js b/rt/src/p2p/Pushable.js index 4a8466d6..b95a5b9f 100644 --- a/rt/src/p2p/Pushable.js +++ b/rt/src/p2p/Pushable.js @@ -1,34 +1,31 @@ -const FIFO = require('p-fifo') -const defer = require('p-defer') -module.exports = function Pushable () { - const errorPromise = defer() - const returnPromise = defer() - const fifo = new FIFO() +const FIFO = require("p-fifo"); +const defer = require("p-defer"); +module.exports = function Pushable() { + const errorPromise = defer(); + const returnPromise = defer(); + const fifo = new FIFO(); return { - [Symbol.asyncIterator] () { - return this + [Symbol.asyncIterator]() { + return this; }, - next: () => Promise.race([ - errorPromise.promise, - returnPromise.promise, - fifo.shift() - ]), + next: () => + Promise.race([errorPromise.promise, returnPromise.promise, fifo.shift()]), return: async () => { - returnPromise.resolve({ done: true }) - return { done: true } + returnPromise.resolve({ done: true }); + return { done: true }; }, - throw: async err => { - errorPromise.reject(err) - return { done: true } + throw: async (err) => { + errorPromise.reject(err); + return { done: true }; }, - push: value => fifo.push({ value }), - end: async err => { + push: (value) => fifo.push({ value }), + end: async (err) => { if (err) { - errorPromise.reject(err) - return + errorPromise.reject(err); + return; } - return fifo.push({ done: true }) - } - } -} \ No newline at end of file + return fifo.push({ done: true }); + }, + }; +}; diff --git a/rt/src/p2p/id-alice.json b/rt/src/p2p/id-alice.json index 6289e2ec..d300014c 100644 --- a/rt/src/p2p/id-alice.json +++ b/rt/src/p2p/id-alice.json @@ -1 +1,5 @@ -{"id":"QmR6R7asNNn4hRYxbBr8wiYKhSN2rjMeaJZiQR2Kav5GvC","privKey":"CAASpwkwggSjAgEAAoIBAQDgeA9Fxn1zyUowVDcKqq7GR5vDXMW7DTStwrqoTskPA6f2ZZOiSq0UOXX/E6XV+nnqZVEorFE+ARVQ4wYgiAnr0Fk6cbGWzFV+jU1uXtt9ahv2OKwJeIZhpNKobEs72baEc8v81YckVSS0JLtqlqCtDglw7G1Fo33viLxWbHMHHUtUpI46WhN4eTystC409oI1f9dpfnaDuJGT/f0uoqoG7UiAuyaWE3SPsTP/FonyS38HsB8bO4uPzjUAgwHZnPsU70f/xwDxRMfcgwni+LYYD5NDH9oHoQ8TcEdpJ9obieycFKmVl6PPjRjEMTkugVesWTb2Na6wNHbz+Lc09/wPAgMBAAECggEBAJfwjJ31amuan+4wwwUkXaN3SzclL+6aVMMdYY2VrsDL/8BoJ1OeaqOa9YUQfptlrWp85D+8zE1FHHGhCj+w9c46PHu0A7qIW4KLEROZf8bXsU+sMr9CZuvnTnSUwSQlDUeAvl5JBu4P+AU8K+RNSzt4melnD9woe5FNI/b397Ci3YK+vhQ+ZhlNEdy11Yh6cEXjb/B00qFgWTWQAKCkA2lSg9rfkS03qnPxhGnKjQQ75UNSoPsWDOOVV3q0xrELmCnpFxA1xHpB5lX/7PXF57AjKKFOlcJoTwIhcmnaWzQuLwuDorqcSZQc0q7sIhHH3FgOQ44CJ67rBR40H/0kMgECgYEA/pTku1Py1m8hFfE391t4pcOsyWfoocgkKvqzFbj+T1KkcrN/Bmbo1k0GlgUYZYxIDVDafh1XVLOth84j8+5ZnMtrXSubemVNrl2LCIYh4luCyoc4yb0Vzy+jYKXYfo5wwELijETkoa65Ft2JzSnGArBgorUHVI4/TJV0m5SO5wECgYEA4bg3h34arji7xDm5VmiRb+2O/pZOjJQurMXNRCWgLQmlqe34ao3iVDAwPRx9sjBrk3dvzP2BL9m1VThZMdZzrjdRgluOBiPGwnjs2bxvDx5ARRwwDvytfEvha1uQMU+zP1kGRCyzYGX13zJYZuZ20eT7dgUHDfIXHvKK1enTcw8CgYAJR7oyzfObN3/YQevNW4tBV6mzydLkGtyeqHbgwtaaY6PU/pAR1qyEK1ijHVpvUTbLLXhZgo5NayNXQP90g+rGWW/3fIB1bL3xLj3EOMeBbd6NrXI3gGoMHGtzOXhz3JNlnsqNXHGNJ0Zd/ANq9CvgqzdKlxjGT00laIlQppCzAQKBgEKkFdjt9UicvWsIs9x8EPxfwckObXB5y3H9EEZfaXQCliOee6pR65F5jLRuNfom64vlRl/aNIsBFtVrRoI9U3gLIwh+qWbMp0EBXMRIKu3mu4jr8pBqL3o0GQCOTvsQEdbRHNWB8Q+z6qyT+5+dyVTc6xUEFPocEJF1gGH5oBEnAoGAJMG95ltgdDu3f4bszDDBl8pQp41KyF43zqxtN2ipz/uN+X0atQldHubNcrd+VMuK2ieyZmAEAeZI1u04Rij5hrxC9MtLyd2VQOJURtfKEA1Mf558kdTP3jnTPElYUQJMzO9TjE6i3AmAMR+PH4UZy5PsWRAuk3VqZarQ50BCv/k=","pubKey":"CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDgeA9Fxn1zyUowVDcKqq7GR5vDXMW7DTStwrqoTskPA6f2ZZOiSq0UOXX/E6XV+nnqZVEorFE+ARVQ4wYgiAnr0Fk6cbGWzFV+jU1uXtt9ahv2OKwJeIZhpNKobEs72baEc8v81YckVSS0JLtqlqCtDglw7G1Fo33viLxWbHMHHUtUpI46WhN4eTystC409oI1f9dpfnaDuJGT/f0uoqoG7UiAuyaWE3SPsTP/FonyS38HsB8bO4uPzjUAgwHZnPsU70f/xwDxRMfcgwni+LYYD5NDH9oHoQ8TcEdpJ9obieycFKmVl6PPjRjEMTkugVesWTb2Na6wNHbz+Lc09/wPAgMBAAE="} \ No newline at end of file +{ + "id": "QmR6R7asNNn4hRYxbBr8wiYKhSN2rjMeaJZiQR2Kav5GvC", + "privKey": "CAASpwkwggSjAgEAAoIBAQDgeA9Fxn1zyUowVDcKqq7GR5vDXMW7DTStwrqoTskPA6f2ZZOiSq0UOXX/E6XV+nnqZVEorFE+ARVQ4wYgiAnr0Fk6cbGWzFV+jU1uXtt9ahv2OKwJeIZhpNKobEs72baEc8v81YckVSS0JLtqlqCtDglw7G1Fo33viLxWbHMHHUtUpI46WhN4eTystC409oI1f9dpfnaDuJGT/f0uoqoG7UiAuyaWE3SPsTP/FonyS38HsB8bO4uPzjUAgwHZnPsU70f/xwDxRMfcgwni+LYYD5NDH9oHoQ8TcEdpJ9obieycFKmVl6PPjRjEMTkugVesWTb2Na6wNHbz+Lc09/wPAgMBAAECggEBAJfwjJ31amuan+4wwwUkXaN3SzclL+6aVMMdYY2VrsDL/8BoJ1OeaqOa9YUQfptlrWp85D+8zE1FHHGhCj+w9c46PHu0A7qIW4KLEROZf8bXsU+sMr9CZuvnTnSUwSQlDUeAvl5JBu4P+AU8K+RNSzt4melnD9woe5FNI/b397Ci3YK+vhQ+ZhlNEdy11Yh6cEXjb/B00qFgWTWQAKCkA2lSg9rfkS03qnPxhGnKjQQ75UNSoPsWDOOVV3q0xrELmCnpFxA1xHpB5lX/7PXF57AjKKFOlcJoTwIhcmnaWzQuLwuDorqcSZQc0q7sIhHH3FgOQ44CJ67rBR40H/0kMgECgYEA/pTku1Py1m8hFfE391t4pcOsyWfoocgkKvqzFbj+T1KkcrN/Bmbo1k0GlgUYZYxIDVDafh1XVLOth84j8+5ZnMtrXSubemVNrl2LCIYh4luCyoc4yb0Vzy+jYKXYfo5wwELijETkoa65Ft2JzSnGArBgorUHVI4/TJV0m5SO5wECgYEA4bg3h34arji7xDm5VmiRb+2O/pZOjJQurMXNRCWgLQmlqe34ao3iVDAwPRx9sjBrk3dvzP2BL9m1VThZMdZzrjdRgluOBiPGwnjs2bxvDx5ARRwwDvytfEvha1uQMU+zP1kGRCyzYGX13zJYZuZ20eT7dgUHDfIXHvKK1enTcw8CgYAJR7oyzfObN3/YQevNW4tBV6mzydLkGtyeqHbgwtaaY6PU/pAR1qyEK1ijHVpvUTbLLXhZgo5NayNXQP90g+rGWW/3fIB1bL3xLj3EOMeBbd6NrXI3gGoMHGtzOXhz3JNlnsqNXHGNJ0Zd/ANq9CvgqzdKlxjGT00laIlQppCzAQKBgEKkFdjt9UicvWsIs9x8EPxfwckObXB5y3H9EEZfaXQCliOee6pR65F5jLRuNfom64vlRl/aNIsBFtVrRoI9U3gLIwh+qWbMp0EBXMRIKu3mu4jr8pBqL3o0GQCOTvsQEdbRHNWB8Q+z6qyT+5+dyVTc6xUEFPocEJF1gGH5oBEnAoGAJMG95ltgdDu3f4bszDDBl8pQp41KyF43zqxtN2ipz/uN+X0atQldHubNcrd+VMuK2ieyZmAEAeZI1u04Rij5hrxC9MtLyd2VQOJURtfKEA1Mf558kdTP3jnTPElYUQJMzO9TjE6i3AmAMR+PH4UZy5PsWRAuk3VqZarQ50BCv/k=", + "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDgeA9Fxn1zyUowVDcKqq7GR5vDXMW7DTStwrqoTskPA6f2ZZOiSq0UOXX/E6XV+nnqZVEorFE+ARVQ4wYgiAnr0Fk6cbGWzFV+jU1uXtt9ahv2OKwJeIZhpNKobEs72baEc8v81YckVSS0JLtqlqCtDglw7G1Fo33viLxWbHMHHUtUpI46WhN4eTystC409oI1f9dpfnaDuJGT/f0uoqoG7UiAuyaWE3SPsTP/FonyS38HsB8bO4uPzjUAgwHZnPsU70f/xwDxRMfcgwni+LYYD5NDH9oHoQ8TcEdpJ9obieycFKmVl6PPjRjEMTkugVesWTb2Na6wNHbz+Lc09/wPAgMBAAE=" +} diff --git a/rt/src/p2p/id-bob.json b/rt/src/p2p/id-bob.json index 6ff85f88..5c87a01d 100644 --- a/rt/src/p2p/id-bob.json +++ b/rt/src/p2p/id-bob.json @@ -1 +1,5 @@ -{"id":"QmXmHXiVm59DbCLLHKRWFQPtJhWPhNAh57VGNeE5PSYauV","privKey":"CAASqQkwggSlAgEAAoIBAQCRYY0nrVCbTuqQMxsiljXizKtmO1Z/JgHQQE7TGNHhDv2YD1ymeDM/pd+yf08FpB2KtYF7VrOsShJuVjcskE4qVADfoVQB/g1FADZ1wIsSE5Q7WOMd3cBMJ19ZzSMwca0N4DEKJd+w+UcfJhvkGUTSai3gCGf/GfYZNfogGOi6FP+c2OjsyXkpMa6u9odgMqY0AUOJKedDH0q+bcunDhYI7nE3FO+8TyCqCcPuzlJfeTdAGGxXU4XLTq0jw0QyP2ko5rWhfT5XvsjJjSfcrbi/Ya2corFmhECmJp5T0cvMRjMX8/pBHPktgAlqW/m+GI4V6XZap3TeS8OGB/URAkXFAgMBAAECggEAYGfDFfONR2Aelb7+GIJpe1tjsahZpHlMrI9odf24d7jcG7DcLJv6yBMz8wcPHNuGp4vTMDn/bZm0/Sv47HlJDDKmXaV6stOIcyA//PfQgQ0wt+YqvYxmT1mwljk9Q4uuSUxI2MTiwFWdfx9jUXAcPjgg8bZBWF4b3v33Pr+l3Ha+WNepJqjY0gAnFhVHQiGu1+NllSvSAhmFIgdnmuX+u4Vek5szEibUyASpXi76ZbzxdLkr43CKgsm32cvcW/GUWBFGiUD12Jurjj0qmoSiuzvOQfLyw/jUc82yrEFlGCwZ4Q15DIyxXmbPspbxMGxD9W2lsNo9s3vy4gGGYYK8gQKBgQDFZ5ZiiZ86evfbsXrAs48CdxEa6OidBTaLSTgrjvwmzXE+u+JyNFa4k9wgHitozL3a0TMFecfvwFXvUTXI43fRS81pQptxrDc82K8QZcihPHdIod11+Imk7/9V90cenKuclMvk407prciSE/mxoNk15Q3v6mNZR0iKSRhIAle25QKBgQC8iMnlp4CCjxgbFv/ddnUuNgwx+hijSmfrO87ms/YlEElmhmEBJ5zBRvk2EWVMkQiLaarc/Hfq6zDB5tFsTLNc+K/RSIGujEndd6t+BBLfR8hR/VxwnEmTRD1ttU6RERVdmKrBFt8pVaUWPXsEhfNJ4OOQrGjZomUzLsjax62FYQKBgQCqhw+sU8KPXEbdK/YknXh+4qiOHIFFk4lIzZmOV1iPlI2tadT2XyxDCsfvnuBVCflAG9P9ePQ0smwJ7peN0KJi1R6/PWDW07RsBatFeQfV8UwCHIIZNPiC2Sgz9Qck9KZy/z8bnRlAWHWZa1QaFB9PpW1iwZHNP/z0KKynGA752QKBgQCvzrq+rfDXToqDEHJuWL0y53F91SLOel7na7EnTt+UdliMA3lHs2Golf9kXNpiiMg4AMQ1KDTG2qRv3Eajv+5uHvUMqplLZESpAaPocfILRgvV8PYXiJXPfw3tVOm7uvt6eReZ0TMuf0/fqlshv6s71DtAuJVZhObr0I+5/AOiYQKBgQC6rZODggqL7UkcoFr85tOU9+lzXeiWIIhuqTT/8lCMMOPrKhQCqkp4C6gdLKlXu0hAWCFL1CtSp78kK1ngpMAW56IjA04vGmYIbGPjBRtutOUTiP9CEL4jRNat9agiNgu2IrsR1q8Tly17YdMQ04gE8XsNXJP6+S17Wmp4Vqgagg==","pubKey":"CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCRYY0nrVCbTuqQMxsiljXizKtmO1Z/JgHQQE7TGNHhDv2YD1ymeDM/pd+yf08FpB2KtYF7VrOsShJuVjcskE4qVADfoVQB/g1FADZ1wIsSE5Q7WOMd3cBMJ19ZzSMwca0N4DEKJd+w+UcfJhvkGUTSai3gCGf/GfYZNfogGOi6FP+c2OjsyXkpMa6u9odgMqY0AUOJKedDH0q+bcunDhYI7nE3FO+8TyCqCcPuzlJfeTdAGGxXU4XLTq0jw0QyP2ko5rWhfT5XvsjJjSfcrbi/Ya2corFmhECmJp5T0cvMRjMX8/pBHPktgAlqW/m+GI4V6XZap3TeS8OGB/URAkXFAgMBAAE="} \ No newline at end of file +{ + "id": "QmXmHXiVm59DbCLLHKRWFQPtJhWPhNAh57VGNeE5PSYauV", + "privKey": "CAASqQkwggSlAgEAAoIBAQCRYY0nrVCbTuqQMxsiljXizKtmO1Z/JgHQQE7TGNHhDv2YD1ymeDM/pd+yf08FpB2KtYF7VrOsShJuVjcskE4qVADfoVQB/g1FADZ1wIsSE5Q7WOMd3cBMJ19ZzSMwca0N4DEKJd+w+UcfJhvkGUTSai3gCGf/GfYZNfogGOi6FP+c2OjsyXkpMa6u9odgMqY0AUOJKedDH0q+bcunDhYI7nE3FO+8TyCqCcPuzlJfeTdAGGxXU4XLTq0jw0QyP2ko5rWhfT5XvsjJjSfcrbi/Ya2corFmhECmJp5T0cvMRjMX8/pBHPktgAlqW/m+GI4V6XZap3TeS8OGB/URAkXFAgMBAAECggEAYGfDFfONR2Aelb7+GIJpe1tjsahZpHlMrI9odf24d7jcG7DcLJv6yBMz8wcPHNuGp4vTMDn/bZm0/Sv47HlJDDKmXaV6stOIcyA//PfQgQ0wt+YqvYxmT1mwljk9Q4uuSUxI2MTiwFWdfx9jUXAcPjgg8bZBWF4b3v33Pr+l3Ha+WNepJqjY0gAnFhVHQiGu1+NllSvSAhmFIgdnmuX+u4Vek5szEibUyASpXi76ZbzxdLkr43CKgsm32cvcW/GUWBFGiUD12Jurjj0qmoSiuzvOQfLyw/jUc82yrEFlGCwZ4Q15DIyxXmbPspbxMGxD9W2lsNo9s3vy4gGGYYK8gQKBgQDFZ5ZiiZ86evfbsXrAs48CdxEa6OidBTaLSTgrjvwmzXE+u+JyNFa4k9wgHitozL3a0TMFecfvwFXvUTXI43fRS81pQptxrDc82K8QZcihPHdIod11+Imk7/9V90cenKuclMvk407prciSE/mxoNk15Q3v6mNZR0iKSRhIAle25QKBgQC8iMnlp4CCjxgbFv/ddnUuNgwx+hijSmfrO87ms/YlEElmhmEBJ5zBRvk2EWVMkQiLaarc/Hfq6zDB5tFsTLNc+K/RSIGujEndd6t+BBLfR8hR/VxwnEmTRD1ttU6RERVdmKrBFt8pVaUWPXsEhfNJ4OOQrGjZomUzLsjax62FYQKBgQCqhw+sU8KPXEbdK/YknXh+4qiOHIFFk4lIzZmOV1iPlI2tadT2XyxDCsfvnuBVCflAG9P9ePQ0smwJ7peN0KJi1R6/PWDW07RsBatFeQfV8UwCHIIZNPiC2Sgz9Qck9KZy/z8bnRlAWHWZa1QaFB9PpW1iwZHNP/z0KKynGA752QKBgQCvzrq+rfDXToqDEHJuWL0y53F91SLOel7na7EnTt+UdliMA3lHs2Golf9kXNpiiMg4AMQ1KDTG2qRv3Eajv+5uHvUMqplLZESpAaPocfILRgvV8PYXiJXPfw3tVOm7uvt6eReZ0TMuf0/fqlshv6s71DtAuJVZhObr0I+5/AOiYQKBgQC6rZODggqL7UkcoFr85tOU9+lzXeiWIIhuqTT/8lCMMOPrKhQCqkp4C6gdLKlXu0hAWCFL1CtSp78kK1ngpMAW56IjA04vGmYIbGPjBRtutOUTiP9CEL4jRNat9agiNgu2IrsR1q8Tly17YdMQ04gE8XsNXJP6+S17Wmp4Vqgagg==", + "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCRYY0nrVCbTuqQMxsiljXizKtmO1Z/JgHQQE7TGNHhDv2YD1ymeDM/pd+yf08FpB2KtYF7VrOsShJuVjcskE4qVADfoVQB/g1FADZ1wIsSE5Q7WOMd3cBMJ19ZzSMwca0N4DEKJd+w+UcfJhvkGUTSai3gCGf/GfYZNfogGOi6FP+c2OjsyXkpMa6u9odgMqY0AUOJKedDH0q+bcunDhYI7nE3FO+8TyCqCcPuzlJfeTdAGGxXU4XLTq0jw0QyP2ko5rWhfT5XvsjJjSfcrbi/Ya2corFmhECmJp5T0cvMRjMX8/pBHPktgAlqW/m+GI4V6XZap3TeS8OGB/URAkXFAgMBAAE=" +} diff --git a/rt/src/p2p/id-charlie.json b/rt/src/p2p/id-charlie.json index 273a39ef..8c27e41c 100644 --- a/rt/src/p2p/id-charlie.json +++ b/rt/src/p2p/id-charlie.json @@ -1 +1,5 @@ -{"id":"QmagJkXckKk2TQEd5MobpT95kxyuh2rzCTYwtvYZxNbEc6","privKey":"CAASpwkwggSjAgEAAoIBAQCUV9heqxcwWyI4Vka5UScRYzmA613Tc4XBpME+UjNhEf5dzmj2B/DH6sKVRjZXRy1acuoEorInAL0B6EL17aMtA/g58pioyOu9BqQJm9dcpiNmArJj7J2cJnFq2tI6Jks6As+fqWzckBOCRSqNdxYpt6Ts1bJziDSF35bXfOaXaem8MfQfW3NDepxn0/a8eBR+MxzyNGl2wNBGGwYFgYowEAmmNiszIir9uomrJoP2CfVU5MZ1DQQ6UAFVzEt307RvhIDYSNrVPo+uDnw9URMSQpTQAhhSzrxelFiNBYUC2Ptg+XKKgQRECYINIfsBtwU7Pm1h9J67NHtUi2Lyi2IRAgMBAAECggEALJrFaqHTVSzx+zKmDW8Dak0Fq2gaTEx+OZ3KpWyeGmAItjgsg14b3mEOpUf5awDx+DJ5f29UVjn4myw1hjEwUYbSCsqRcJ8Jk0r95A3CEg+6sR+6eCVbtuowTEsDz4xYLldOCtos650+4Hrfsq3OMjkQFE6lW+vmryJt/tmFlJ1BBO1oD1xa5huTwt/GOG16lZYKH0P+vHNXEfsKWByXf2bzlDkrdittR03fs3SC/T4Q4EFNvmdcDdw5sDKaC+zsfw3xt7dVmiiUFnf/9DbEmORJBbGbO3ej0k9yvi5D2KTRF8gOTY1uKgeHwJs7MRz4mFRgPumT2Q9IgPN+hdjAyQKBgQD80zVqBk9mLCoZHWyyKCz6jOV02iMg89KFlc6lV9M709J10EUrx9WfwIiDrRjRCn7P51UNpJZMl5FCmAWbl3VxH8mxx4XliTDgWGxisz+QtfwZyi/6lsMiLvcG/PssVzZgimIg2oSb5mbNkz+Unu00uFNYixOEX/mgPbc8bZhCawKBgQCWNL6IogS4ijNPlKpxZT52AjxHS1q1SsHD00TCvspzGU4kJmx3zVE6UmG2kwf6I8fdTEa2dClc+ApHyl+jtcVuhQn3POrMH09qfqhUdq0us/qWpE1qFN3A3613Nx39BTZXbu8ptNJzVlAIhqD0PibVZ7PcwO1HUqQj6dqgdgukcwKBgQCSM2jt+NwtT1jA0T0sAQORl6yQ2Bv8UELrMOggwRrLvAA2VMvLN3IXQXUwAAcbyx/uBe4vR4AKppM/mT2U7g7h7enqvmB1jdIPydJTeShG/JXeLAd2t3v75oC/L8fnqj8tsJhyOyr4JFJKit33ibfOBtFboIEWyZFG0qmFbjLgJQKBgC/EHCdFJq0svb5772vaH2/VrCeb7f+jA1Vr1Pz9QVIy5OeYFHxQnZknY4102l+Qi1lzjTUuYY0AD/zefWWJQ3yu8AlgpOY+urmKB6u8hbxJXdIT885dTlushfRYYb/5rVtGmuWvbBFjjFX5wiuJrD3HGaqE66/3ttz43B6VC4TDAoGAEPbCPtA8gt8OmqYV+EQi08/HlsdXEyeOTryG+o/kWhY6OyzS25zZ/o65xOy+0GIqjP5NZDVZgBHz8y3Ms7ie39MGaiDOvEFJZrZ/MXoymlxBFAiz8GgodZlGtzugt3vWydrm0eZ9JuFJGHtUwrmZk3YQw0MbjL6nRKMMBUYI+1E=","pubKey":"CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCUV9heqxcwWyI4Vka5UScRYzmA613Tc4XBpME+UjNhEf5dzmj2B/DH6sKVRjZXRy1acuoEorInAL0B6EL17aMtA/g58pioyOu9BqQJm9dcpiNmArJj7J2cJnFq2tI6Jks6As+fqWzckBOCRSqNdxYpt6Ts1bJziDSF35bXfOaXaem8MfQfW3NDepxn0/a8eBR+MxzyNGl2wNBGGwYFgYowEAmmNiszIir9uomrJoP2CfVU5MZ1DQQ6UAFVzEt307RvhIDYSNrVPo+uDnw9URMSQpTQAhhSzrxelFiNBYUC2Ptg+XKKgQRECYINIfsBtwU7Pm1h9J67NHtUi2Lyi2IRAgMBAAE="} \ No newline at end of file +{ + "id": "QmagJkXckKk2TQEd5MobpT95kxyuh2rzCTYwtvYZxNbEc6", + "privKey": "CAASpwkwggSjAgEAAoIBAQCUV9heqxcwWyI4Vka5UScRYzmA613Tc4XBpME+UjNhEf5dzmj2B/DH6sKVRjZXRy1acuoEorInAL0B6EL17aMtA/g58pioyOu9BqQJm9dcpiNmArJj7J2cJnFq2tI6Jks6As+fqWzckBOCRSqNdxYpt6Ts1bJziDSF35bXfOaXaem8MfQfW3NDepxn0/a8eBR+MxzyNGl2wNBGGwYFgYowEAmmNiszIir9uomrJoP2CfVU5MZ1DQQ6UAFVzEt307RvhIDYSNrVPo+uDnw9URMSQpTQAhhSzrxelFiNBYUC2Ptg+XKKgQRECYINIfsBtwU7Pm1h9J67NHtUi2Lyi2IRAgMBAAECggEALJrFaqHTVSzx+zKmDW8Dak0Fq2gaTEx+OZ3KpWyeGmAItjgsg14b3mEOpUf5awDx+DJ5f29UVjn4myw1hjEwUYbSCsqRcJ8Jk0r95A3CEg+6sR+6eCVbtuowTEsDz4xYLldOCtos650+4Hrfsq3OMjkQFE6lW+vmryJt/tmFlJ1BBO1oD1xa5huTwt/GOG16lZYKH0P+vHNXEfsKWByXf2bzlDkrdittR03fs3SC/T4Q4EFNvmdcDdw5sDKaC+zsfw3xt7dVmiiUFnf/9DbEmORJBbGbO3ej0k9yvi5D2KTRF8gOTY1uKgeHwJs7MRz4mFRgPumT2Q9IgPN+hdjAyQKBgQD80zVqBk9mLCoZHWyyKCz6jOV02iMg89KFlc6lV9M709J10EUrx9WfwIiDrRjRCn7P51UNpJZMl5FCmAWbl3VxH8mxx4XliTDgWGxisz+QtfwZyi/6lsMiLvcG/PssVzZgimIg2oSb5mbNkz+Unu00uFNYixOEX/mgPbc8bZhCawKBgQCWNL6IogS4ijNPlKpxZT52AjxHS1q1SsHD00TCvspzGU4kJmx3zVE6UmG2kwf6I8fdTEa2dClc+ApHyl+jtcVuhQn3POrMH09qfqhUdq0us/qWpE1qFN3A3613Nx39BTZXbu8ptNJzVlAIhqD0PibVZ7PcwO1HUqQj6dqgdgukcwKBgQCSM2jt+NwtT1jA0T0sAQORl6yQ2Bv8UELrMOggwRrLvAA2VMvLN3IXQXUwAAcbyx/uBe4vR4AKppM/mT2U7g7h7enqvmB1jdIPydJTeShG/JXeLAd2t3v75oC/L8fnqj8tsJhyOyr4JFJKit33ibfOBtFboIEWyZFG0qmFbjLgJQKBgC/EHCdFJq0svb5772vaH2/VrCeb7f+jA1Vr1Pz9QVIy5OeYFHxQnZknY4102l+Qi1lzjTUuYY0AD/zefWWJQ3yu8AlgpOY+urmKB6u8hbxJXdIT885dTlushfRYYb/5rVtGmuWvbBFjjFX5wiuJrD3HGaqE66/3ttz43B6VC4TDAoGAEPbCPtA8gt8OmqYV+EQi08/HlsdXEyeOTryG+o/kWhY6OyzS25zZ/o65xOy+0GIqjP5NZDVZgBHz8y3Ms7ie39MGaiDOvEFJZrZ/MXoymlxBFAiz8GgodZlGtzugt3vWydrm0eZ9JuFJGHtUwrmZk3YQw0MbjL6nRKMMBUYI+1E=", + "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCUV9heqxcwWyI4Vka5UScRYzmA613Tc4XBpME+UjNhEf5dzmj2B/DH6sKVRjZXRy1acuoEorInAL0B6EL17aMtA/g58pioyOu9BqQJm9dcpiNmArJj7J2cJnFq2tI6Jks6As+fqWzckBOCRSqNdxYpt6Ts1bJziDSF35bXfOaXaem8MfQfW3NDepxn0/a8eBR+MxzyNGl2wNBGGwYFgYowEAmmNiszIir9uomrJoP2CfVU5MZ1DQQ6UAFVzEt307RvhIDYSNrVPo+uDnw9URMSQpTQAhhSzrxelFiNBYUC2Ptg+XKKgQRECYINIfsBtwU7Pm1h9J67NHtUi2Lyi2IRAgMBAAE=" +} diff --git a/rt/src/p2p/id-dialer.json b/rt/src/p2p/id-dialer.json index e27757ae..af39d98a 100644 --- a/rt/src/p2p/id-dialer.json +++ b/rt/src/p2p/id-dialer.json @@ -1,5 +1,5 @@ { - "id": "QmRusd3YsWYpCAgqRvqeMsD3tp1QfqBxhprr1dXr2WAufw", - "privKey": "CAASqAkwggSkAgEAAoIBAQDOLQO1umEIJKHbn90oqZftmKK+k4MKtTJHxiqzPJJUdjWYwpHn51T9M4rqXa6NHBMBzcYBxiNLw00HClGKHmNG83LrsVWvjTfX+pY6I6M0fnUxm1OPD6yu5JvH1giQiVF6GUOPTOoAApFlgISN88sZLonkyfP1ljV2ER0CGYYCefeOcgePHMn+WG5G8k/6lY2wgucftpoX4vNF89Kou7V1ZmcnvyIEL8nGR9KuhG5D4OI1enbQ+L9kaObUys2tWTsUJAWkXGZmHTtxFrC4MXMzp8YSAJL2ECS9sdke3SttlXNwiJ80OkHAid7mpcDLI3QncZeh9gRHA9oeAar5YrEhAgMBAAECggEALYs6D5HNT2wwKQDGbO4RtpWKFckmIF5obfxzgEZ4GJpIOqd4bZ7nYktZe24YWemCtVpMTCYFs/2/bTe1TWprCchLcY8p2265kEc1mkA3FCh/IOcr7SVMQxIS63D3UV5UFkGwb95QrpHipmZeYbEiAz0JjvWho3V798nN+6HBvZfnpgtaBqpDJuiVlSegK1CGMZ875arlckevQcPaqyWVm+9Q/4kSNLtcLUnGLWUH21CHFlIaRF6llpkZW4Xk53WIXuewXQWdVK9L2rjftvN83+/JjblQJAQ2hnYFg63971pKSrYdHi2QsV4MyPFIWS5vcyqwy9hblcjlCA9sXMiBwQKBgQD/1PrLdCzr7ZFeN/J+RVw83M7mUWeKJMGwEsKeo4wVjtNZYvN3GEbSri3iicmY6iE2GC+BmbhNk/uT8FDydfrMmWBjM1mu/xeHdMOndvU0EHwUZmXU6fe/33kcCmfebbD1LvukzvyvbV5/sOazTU4AxaCEYGN8kdtmYSjqSpQdOQKBgQDOT69KEx2rk7DurWJcrnBfTpOHDwPxJHa707NqLxc+Z2XkW3SVFhMSETkxmpEvWiGGL8S20jGS4KFiTR7wdxvyFojeUmtFZLZd2bAPUsF+JyNAHgjyVKk1xAXq3fedgVRqpTTG965N7WgzEqBQahFZrX+Xckl0lu3M05jSAj0bKQKBgQDk3p53QTmm32O7TIXuHRMFh+y4836TgYqdgEsILPv3lUzSnMl+dAN4G0cFcYse9+Y6RKzLXsAY9xiMIuPn5VA3lcc7OAc1nRRppDYdLTj0GQNIJMtZDO8NglkQkuaVgMBcuGl76Yj5T/jId3QMWE4+No8BnlGiccI79xPpdkrHUQKBgGlbkCzH7lL8rVJ2ANFL098YBYbnSCARewEYb3s+aSRZMVOY0MSB7WNAoHCQeqwv3wbjxhWG6gIT7NaCg9ZRPVg34dWHSXi6odbzoFFy9ZUy73GC5Ra73V2zqUHz8Mvii/WaQIWLXtw07Q2H6Y6nXAzr6Uix+IktumrrdBNrSUFhAoGBANLTaixhulcabvZx9oQfj/r3YlDTpsTQXfmDxemwtPqEdPoPPe5OnNcDC9rmK37kdDHJ/Eo4jkvSVOpV4s0AVoAT55NAkkLaR9FF0/tQX6cjJlTrNHZCR3WMytEjMBjhyVoBrWc+qT91KgF8nsxKjHmgmHgZFMQ+PK83rwnWuDQc", - "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDOLQO1umEIJKHbn90oqZftmKK+k4MKtTJHxiqzPJJUdjWYwpHn51T9M4rqXa6NHBMBzcYBxiNLw00HClGKHmNG83LrsVWvjTfX+pY6I6M0fnUxm1OPD6yu5JvH1giQiVF6GUOPTOoAApFlgISN88sZLonkyfP1ljV2ER0CGYYCefeOcgePHMn+WG5G8k/6lY2wgucftpoX4vNF89Kou7V1ZmcnvyIEL8nGR9KuhG5D4OI1enbQ+L9kaObUys2tWTsUJAWkXGZmHTtxFrC4MXMzp8YSAJL2ECS9sdke3SttlXNwiJ80OkHAid7mpcDLI3QncZeh9gRHA9oeAar5YrEhAgMBAAE=" -} \ No newline at end of file + "id": "QmRusd3YsWYpCAgqRvqeMsD3tp1QfqBxhprr1dXr2WAufw", + "privKey": "CAASqAkwggSkAgEAAoIBAQDOLQO1umEIJKHbn90oqZftmKK+k4MKtTJHxiqzPJJUdjWYwpHn51T9M4rqXa6NHBMBzcYBxiNLw00HClGKHmNG83LrsVWvjTfX+pY6I6M0fnUxm1OPD6yu5JvH1giQiVF6GUOPTOoAApFlgISN88sZLonkyfP1ljV2ER0CGYYCefeOcgePHMn+WG5G8k/6lY2wgucftpoX4vNF89Kou7V1ZmcnvyIEL8nGR9KuhG5D4OI1enbQ+L9kaObUys2tWTsUJAWkXGZmHTtxFrC4MXMzp8YSAJL2ECS9sdke3SttlXNwiJ80OkHAid7mpcDLI3QncZeh9gRHA9oeAar5YrEhAgMBAAECggEALYs6D5HNT2wwKQDGbO4RtpWKFckmIF5obfxzgEZ4GJpIOqd4bZ7nYktZe24YWemCtVpMTCYFs/2/bTe1TWprCchLcY8p2265kEc1mkA3FCh/IOcr7SVMQxIS63D3UV5UFkGwb95QrpHipmZeYbEiAz0JjvWho3V798nN+6HBvZfnpgtaBqpDJuiVlSegK1CGMZ875arlckevQcPaqyWVm+9Q/4kSNLtcLUnGLWUH21CHFlIaRF6llpkZW4Xk53WIXuewXQWdVK9L2rjftvN83+/JjblQJAQ2hnYFg63971pKSrYdHi2QsV4MyPFIWS5vcyqwy9hblcjlCA9sXMiBwQKBgQD/1PrLdCzr7ZFeN/J+RVw83M7mUWeKJMGwEsKeo4wVjtNZYvN3GEbSri3iicmY6iE2GC+BmbhNk/uT8FDydfrMmWBjM1mu/xeHdMOndvU0EHwUZmXU6fe/33kcCmfebbD1LvukzvyvbV5/sOazTU4AxaCEYGN8kdtmYSjqSpQdOQKBgQDOT69KEx2rk7DurWJcrnBfTpOHDwPxJHa707NqLxc+Z2XkW3SVFhMSETkxmpEvWiGGL8S20jGS4KFiTR7wdxvyFojeUmtFZLZd2bAPUsF+JyNAHgjyVKk1xAXq3fedgVRqpTTG965N7WgzEqBQahFZrX+Xckl0lu3M05jSAj0bKQKBgQDk3p53QTmm32O7TIXuHRMFh+y4836TgYqdgEsILPv3lUzSnMl+dAN4G0cFcYse9+Y6RKzLXsAY9xiMIuPn5VA3lcc7OAc1nRRppDYdLTj0GQNIJMtZDO8NglkQkuaVgMBcuGl76Yj5T/jId3QMWE4+No8BnlGiccI79xPpdkrHUQKBgGlbkCzH7lL8rVJ2ANFL098YBYbnSCARewEYb3s+aSRZMVOY0MSB7WNAoHCQeqwv3wbjxhWG6gIT7NaCg9ZRPVg34dWHSXi6odbzoFFy9ZUy73GC5Ra73V2zqUHz8Mvii/WaQIWLXtw07Q2H6Y6nXAzr6Uix+IktumrrdBNrSUFhAoGBANLTaixhulcabvZx9oQfj/r3YlDTpsTQXfmDxemwtPqEdPoPPe5OnNcDC9rmK37kdDHJ/Eo4jkvSVOpV4s0AVoAT55NAkkLaR9FF0/tQX6cjJlTrNHZCR3WMytEjMBjhyVoBrWc+qT91KgF8nsxKjHmgmHgZFMQ+PK83rwnWuDQc", + "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDOLQO1umEIJKHbn90oqZftmKK+k4MKtTJHxiqzPJJUdjWYwpHn51T9M4rqXa6NHBMBzcYBxiNLw00HClGKHmNG83LrsVWvjTfX+pY6I6M0fnUxm1OPD6yu5JvH1giQiVF6GUOPTOoAApFlgISN88sZLonkyfP1ljV2ER0CGYYCefeOcgePHMn+WG5G8k/6lY2wgucftpoX4vNF89Kou7V1ZmcnvyIEL8nGR9KuhG5D4OI1enbQ+L9kaObUys2tWTsUJAWkXGZmHTtxFrC4MXMzp8YSAJL2ECS9sdke3SttlXNwiJ80OkHAid7mpcDLI3QncZeh9gRHA9oeAar5YrEhAgMBAAE=" +} diff --git a/rt/src/p2p/id-dorothy.json b/rt/src/p2p/id-dorothy.json index 2d1aca16..bac836be 100644 --- a/rt/src/p2p/id-dorothy.json +++ b/rt/src/p2p/id-dorothy.json @@ -1 +1,5 @@ -{"id":"QmfVDYD9Du7fNR4DKooPXZnRUoArR3FBRR3udbhZAT9m2H","privKey":"CAASpwkwggSjAgEAAoIBAQCOM5J/S7KwIfIZAzLn2upVYtK607klFHtknfN9/2ltrNodKXl/tNDrvK5oRiVsGU7XLqLs51DUhOVv5Fd4bmQFD/OTtC7Q+7ocqixzSotbFVfQyAopVLot3mLGS9xRU6X09bkSREWCWpXKxvoKCxAu568HaxXN7ov/xg8dgwbrEX5TcBthoq9kBkWj0MF8KprkIpbE3m/a3X4bN+PRr9qMQpvSOZgvBJkbYaPOJaQbNUC2HvqWFsjyyLdNNwaSbQrKrd/Qn/SHEUVVliaxMwpuLPg7qUZiYCBku/wlG/eruhUzS20irpVoZvmICfb6S0Y905PVn/zUGbwd+giRjuaDAgMBAAECggEAGWdlOJCRb53g3k8P/RPC4VYyR2YjoVgzYxpEsbG7Z/iFTshmCEaJPFQM5FwDu3gZ+Z8/RAtfCVhklMS6S62M+MqMvUpnQrZ13UEZh889bhw1//p8tj2ItUERbFOJHI5RC54KXhUMRelg8UTyznCDh52kSzL6RjvjjuIXOTJ7PeswpbKcSleFoTC5TanoIi3ws25qnShg0lKjGF7NijU94lNpRT26GItDucxHG1gfIQurzImyvgf6W9NVTEYBA3UxR131qvAeGzx8k3LwjMvJpip1/ynNu77zjwTZV6U39hu0pI2ln9Gsf51ZfNLZnbT5HIMI6+e5k+Sygb4iVKOXAQKBgQDoIOeFOoyT9P0poVqqB6c/yQJRHMs9c1Qr3waeQCG02KfsSA1g2pYzRf8clbANt2eSqHj95sksGsoURZZFyatz1FC/DJqpZOX44rJoTFZalHrhB9Iv069Qju3czRiopTtQs/BTAiFEV7MhwQcyma05boRdAlBgEZFW5ON+QZgpIQKBgQCc0zd3WGs1OCVOEqixTFKqDcOEo1/FGxtZ3bFGEjzkuiKyf8lmKNh7lpZfhXE/bXNQSjn83Zkrwp33nR1x8woUSFT4sE2Dj3B8HeM4Dw4MmriPKgyB7SJaKAKXau+jcMStOh+rBNeQiL8wVBQ0wNsfwamH1ohuEFLnZmEOUZVnIwKBgE1VuQxv5ynb8wQNl7ER/6yGgVkYqLV+WMqM8R2D7Dbd/4P+tUZRTL0kUsvpKtBHDCCWNEkSvG8PNcfvLxNtDsv2LjiYMGbDEMMMc7e/xv1CfnW+L05zzfKey6xGQDLfaZWHfUeKbB7iwPE75/P5svZxVXPPM4vuDmfOteP4YoNBAoGAD9fy6ZbANf83HZ0a99aLH20GjLborQQhDkIsb7TV/BGmAbyRP0XvIQVEqd/UYiEPnlPxac+FcvtVdDemSuXP5d6s3vcIzbrHFXL7iqVSuQlEjgoke1fWuZ8DLAL8tNlmtU2C94cktBBsqFhGNlIpkRrCotuUqvHxPjmEoqqxWlsCgYEAxBR0loibSUpvNN3n8Zk55CN1SPSA+bfKiR+wZHbh0EDVMqVkaiZtsCNGQvZejIifp6y/+aI2Jj+NzvYiwdXBnOtBlQY1jTppXO4hIkTiVT/IFzWBxeBFJyw7Q8gMmp/T1C9TA3mImkyn9aDKdgAj4viWkE3Wan6ctdc8Cg3wWj8=","pubKey":"CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCOM5J/S7KwIfIZAzLn2upVYtK607klFHtknfN9/2ltrNodKXl/tNDrvK5oRiVsGU7XLqLs51DUhOVv5Fd4bmQFD/OTtC7Q+7ocqixzSotbFVfQyAopVLot3mLGS9xRU6X09bkSREWCWpXKxvoKCxAu568HaxXN7ov/xg8dgwbrEX5TcBthoq9kBkWj0MF8KprkIpbE3m/a3X4bN+PRr9qMQpvSOZgvBJkbYaPOJaQbNUC2HvqWFsjyyLdNNwaSbQrKrd/Qn/SHEUVVliaxMwpuLPg7qUZiYCBku/wlG/eruhUzS20irpVoZvmICfb6S0Y905PVn/zUGbwd+giRjuaDAgMBAAE="} \ No newline at end of file +{ + "id": "QmfVDYD9Du7fNR4DKooPXZnRUoArR3FBRR3udbhZAT9m2H", + "privKey": "CAASpwkwggSjAgEAAoIBAQCOM5J/S7KwIfIZAzLn2upVYtK607klFHtknfN9/2ltrNodKXl/tNDrvK5oRiVsGU7XLqLs51DUhOVv5Fd4bmQFD/OTtC7Q+7ocqixzSotbFVfQyAopVLot3mLGS9xRU6X09bkSREWCWpXKxvoKCxAu568HaxXN7ov/xg8dgwbrEX5TcBthoq9kBkWj0MF8KprkIpbE3m/a3X4bN+PRr9qMQpvSOZgvBJkbYaPOJaQbNUC2HvqWFsjyyLdNNwaSbQrKrd/Qn/SHEUVVliaxMwpuLPg7qUZiYCBku/wlG/eruhUzS20irpVoZvmICfb6S0Y905PVn/zUGbwd+giRjuaDAgMBAAECggEAGWdlOJCRb53g3k8P/RPC4VYyR2YjoVgzYxpEsbG7Z/iFTshmCEaJPFQM5FwDu3gZ+Z8/RAtfCVhklMS6S62M+MqMvUpnQrZ13UEZh889bhw1//p8tj2ItUERbFOJHI5RC54KXhUMRelg8UTyznCDh52kSzL6RjvjjuIXOTJ7PeswpbKcSleFoTC5TanoIi3ws25qnShg0lKjGF7NijU94lNpRT26GItDucxHG1gfIQurzImyvgf6W9NVTEYBA3UxR131qvAeGzx8k3LwjMvJpip1/ynNu77zjwTZV6U39hu0pI2ln9Gsf51ZfNLZnbT5HIMI6+e5k+Sygb4iVKOXAQKBgQDoIOeFOoyT9P0poVqqB6c/yQJRHMs9c1Qr3waeQCG02KfsSA1g2pYzRf8clbANt2eSqHj95sksGsoURZZFyatz1FC/DJqpZOX44rJoTFZalHrhB9Iv069Qju3czRiopTtQs/BTAiFEV7MhwQcyma05boRdAlBgEZFW5ON+QZgpIQKBgQCc0zd3WGs1OCVOEqixTFKqDcOEo1/FGxtZ3bFGEjzkuiKyf8lmKNh7lpZfhXE/bXNQSjn83Zkrwp33nR1x8woUSFT4sE2Dj3B8HeM4Dw4MmriPKgyB7SJaKAKXau+jcMStOh+rBNeQiL8wVBQ0wNsfwamH1ohuEFLnZmEOUZVnIwKBgE1VuQxv5ynb8wQNl7ER/6yGgVkYqLV+WMqM8R2D7Dbd/4P+tUZRTL0kUsvpKtBHDCCWNEkSvG8PNcfvLxNtDsv2LjiYMGbDEMMMc7e/xv1CfnW+L05zzfKey6xGQDLfaZWHfUeKbB7iwPE75/P5svZxVXPPM4vuDmfOteP4YoNBAoGAD9fy6ZbANf83HZ0a99aLH20GjLborQQhDkIsb7TV/BGmAbyRP0XvIQVEqd/UYiEPnlPxac+FcvtVdDemSuXP5d6s3vcIzbrHFXL7iqVSuQlEjgoke1fWuZ8DLAL8tNlmtU2C94cktBBsqFhGNlIpkRrCotuUqvHxPjmEoqqxWlsCgYEAxBR0loibSUpvNN3n8Zk55CN1SPSA+bfKiR+wZHbh0EDVMqVkaiZtsCNGQvZejIifp6y/+aI2Jj+NzvYiwdXBnOtBlQY1jTppXO4hIkTiVT/IFzWBxeBFJyw7Q8gMmp/T1C9TA3mImkyn9aDKdgAj4viWkE3Wan6ctdc8Cg3wWj8=", + "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCOM5J/S7KwIfIZAzLn2upVYtK607klFHtknfN9/2ltrNodKXl/tNDrvK5oRiVsGU7XLqLs51DUhOVv5Fd4bmQFD/OTtC7Q+7ocqixzSotbFVfQyAopVLot3mLGS9xRU6X09bkSREWCWpXKxvoKCxAu568HaxXN7ov/xg8dgwbrEX5TcBthoq9kBkWj0MF8KprkIpbE3m/a3X4bN+PRr9qMQpvSOZgvBJkbYaPOJaQbNUC2HvqWFsjyyLdNNwaSbQrKrd/Qn/SHEUVVliaxMwpuLPg7qUZiYCBku/wlG/eruhUzS20irpVoZvmICfb6S0Y905PVn/zUGbwd+giRjuaDAgMBAAE=" +} diff --git a/rt/src/p2p/id-listener.json b/rt/src/p2p/id-listener.json index f90c089b..55b77204 100644 --- a/rt/src/p2p/id-listener.json +++ b/rt/src/p2p/id-listener.json @@ -1,5 +1,5 @@ { - "id": "QmQSEt8DBeumRh8ZupmUaW8rVvwnjFtpBE557vjSLccUBh", - "privKey": "CAASpwkwggSjAgEAAoIBAQCVhRipx878dOFYNlp2GAohUpy++vth4jaN1aqWck5c2cB67f9iD0TmpeCVGXB3rDSu2+Wz2NX6nACUQKyJHZIyE4eGqaY8MYzoDQGQi2uVcjpXMHwbUeS3dAtVunyJB6UhOX+jB54ufpp6F7yTOmeLn3AQJFdoMoAHo94jPra1ltDFFYX5D//Yty8l2D0/sb3b6P94iZkyGLufLYpxOMd6E5XChDO+K4Bl8CEbnjPD65vxRX9ElBiHcfqcswQVAfeAFC+NQ1CmJV3RSVssmw9fQ55gm4nBje2PN1Q4zJx0j134qK3uf5MGpQkCsZd9V8n9rZrgd7VFQbzbyuAenKVhAgMBAAECggEAPWj18T2MiOnkZ9ujGd/TwU3x7QqeVtyXNXftYW8/OimBQbwgaQEGdojojbRuGejTloHgfRZxBEYwgrNxabuIgSK+RhPFn/FmAyTcYKayoCXTSl4yivH+s05pHWPDpHBMZTH9d1M4p7X98mlvXTTetFzepPKYJ8aeCQVHxkgKuNe9IwqBuHS0L6gIdUlFMfp528iSP8vRsDp/rmooLBmsJJjtMDFWTO1XwI5f6/tnHzDz0A2q/rN3A3M51exOVzl4vnAoJpY50HS/qX82ujVMDtoP2MGBrMvq+KlTm+wrhKGrS8NAg1NzMy/bkvfAdZxEVU+2dFWHNZHYosrAB18GlQKBgQDyndDi2Lht1I0pzWgNwSsFunHvQ2cmQCBYDzL/guthAzkCkPd1Fg4HoWjfKuY/JVC/boHN8pPVrvF0mIu0toTydTUDWnWmg4TGaqb3aqmHmwzEsh7WdcLdo9aGffq2WmOx9F/CmfSZfG69s8q38IlT2ewIvtlyB3fZru7rZzilJwKBgQCdxJaaVEuK79ZwiailZXCqW1L/lE7Dq/XIqYQ5SdXAy2TYBYAquXdQI4x5c3Mnbf60cSyuVwce/bmHLNRdU2aQsG9vZOSLJwGjPUrcQ44o6ibAZPJmowUW21SqVogQHOrbaf8rp740OXcttmdlo2DGYEgrMkWKoLzTxXR7I8PGNwKBgBWnIhJs1yDuPF8DtwqrN8S+HBcHg/g09u4FBT8qlwlEeV0SRRONEVl6/VoVgREXqno7SZhw0uLaRzBpwOYy9/CPp1iSRTfEOyBeOmKQgWrZ2qzfXMM1JVwUmDvOmIaX0Jf8QGOky+C660NA/ZGnBQqXw2oQZmW35ullpGsb/kE3AoGBAJgsX4taVUcc0PzZeqaV8pcO4T6N4W8Q9VBoWZYcZqXASXOn0pjjLXdJ4pvexKq6iNuo8gzy+nZlCseccPXXlO1okQOkEGE77XNzkjpkmsFSILCgbcKb6TPDuKVYM4M/MTUTx0FnWanr581ay96YOKb/hXzMz5DIO3oUUabYt2P/AoGAGCK0iKZRscSE5dRmaNBNKQyip6B2FzPma0NVzo/uHhbgcrIpJxbqXFUCBHZ/KL2Z1nMkderNFTvwz1HzAJA6xdbEPNGWs81W/p/UUIShhXpJ4T/uwBrS2r6iB4/Zk098RfBqEQjwggGD6Q4oCT5HtjWFm6kgoP9/49e4O7sSOFQ=", - "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhRipx878dOFYNlp2GAohUpy++vth4jaN1aqWck5c2cB67f9iD0TmpeCVGXB3rDSu2+Wz2NX6nACUQKyJHZIyE4eGqaY8MYzoDQGQi2uVcjpXMHwbUeS3dAtVunyJB6UhOX+jB54ufpp6F7yTOmeLn3AQJFdoMoAHo94jPra1ltDFFYX5D//Yty8l2D0/sb3b6P94iZkyGLufLYpxOMd6E5XChDO+K4Bl8CEbnjPD65vxRX9ElBiHcfqcswQVAfeAFC+NQ1CmJV3RSVssmw9fQ55gm4nBje2PN1Q4zJx0j134qK3uf5MGpQkCsZd9V8n9rZrgd7VFQbzbyuAenKVhAgMBAAE=" -} \ No newline at end of file + "id": "QmQSEt8DBeumRh8ZupmUaW8rVvwnjFtpBE557vjSLccUBh", + "privKey": "CAASpwkwggSjAgEAAoIBAQCVhRipx878dOFYNlp2GAohUpy++vth4jaN1aqWck5c2cB67f9iD0TmpeCVGXB3rDSu2+Wz2NX6nACUQKyJHZIyE4eGqaY8MYzoDQGQi2uVcjpXMHwbUeS3dAtVunyJB6UhOX+jB54ufpp6F7yTOmeLn3AQJFdoMoAHo94jPra1ltDFFYX5D//Yty8l2D0/sb3b6P94iZkyGLufLYpxOMd6E5XChDO+K4Bl8CEbnjPD65vxRX9ElBiHcfqcswQVAfeAFC+NQ1CmJV3RSVssmw9fQ55gm4nBje2PN1Q4zJx0j134qK3uf5MGpQkCsZd9V8n9rZrgd7VFQbzbyuAenKVhAgMBAAECggEAPWj18T2MiOnkZ9ujGd/TwU3x7QqeVtyXNXftYW8/OimBQbwgaQEGdojojbRuGejTloHgfRZxBEYwgrNxabuIgSK+RhPFn/FmAyTcYKayoCXTSl4yivH+s05pHWPDpHBMZTH9d1M4p7X98mlvXTTetFzepPKYJ8aeCQVHxkgKuNe9IwqBuHS0L6gIdUlFMfp528iSP8vRsDp/rmooLBmsJJjtMDFWTO1XwI5f6/tnHzDz0A2q/rN3A3M51exOVzl4vnAoJpY50HS/qX82ujVMDtoP2MGBrMvq+KlTm+wrhKGrS8NAg1NzMy/bkvfAdZxEVU+2dFWHNZHYosrAB18GlQKBgQDyndDi2Lht1I0pzWgNwSsFunHvQ2cmQCBYDzL/guthAzkCkPd1Fg4HoWjfKuY/JVC/boHN8pPVrvF0mIu0toTydTUDWnWmg4TGaqb3aqmHmwzEsh7WdcLdo9aGffq2WmOx9F/CmfSZfG69s8q38IlT2ewIvtlyB3fZru7rZzilJwKBgQCdxJaaVEuK79ZwiailZXCqW1L/lE7Dq/XIqYQ5SdXAy2TYBYAquXdQI4x5c3Mnbf60cSyuVwce/bmHLNRdU2aQsG9vZOSLJwGjPUrcQ44o6ibAZPJmowUW21SqVogQHOrbaf8rp740OXcttmdlo2DGYEgrMkWKoLzTxXR7I8PGNwKBgBWnIhJs1yDuPF8DtwqrN8S+HBcHg/g09u4FBT8qlwlEeV0SRRONEVl6/VoVgREXqno7SZhw0uLaRzBpwOYy9/CPp1iSRTfEOyBeOmKQgWrZ2qzfXMM1JVwUmDvOmIaX0Jf8QGOky+C660NA/ZGnBQqXw2oQZmW35ullpGsb/kE3AoGBAJgsX4taVUcc0PzZeqaV8pcO4T6N4W8Q9VBoWZYcZqXASXOn0pjjLXdJ4pvexKq6iNuo8gzy+nZlCseccPXXlO1okQOkEGE77XNzkjpkmsFSILCgbcKb6TPDuKVYM4M/MTUTx0FnWanr581ay96YOKb/hXzMz5DIO3oUUabYt2P/AoGAGCK0iKZRscSE5dRmaNBNKQyip6B2FzPma0NVzo/uHhbgcrIpJxbqXFUCBHZ/KL2Z1nMkderNFTvwz1HzAJA6xdbEPNGWs81W/p/UUIShhXpJ4T/uwBrS2r6iB4/Zk098RfBqEQjwggGD6Q4oCT5HtjWFm6kgoP9/49e4O7sSOFQ=", + "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhRipx878dOFYNlp2GAohUpy++vth4jaN1aqWck5c2cB67f9iD0TmpeCVGXB3rDSu2+Wz2NX6nACUQKyJHZIyE4eGqaY8MYzoDQGQi2uVcjpXMHwbUeS3dAtVunyJB6UhOX+jB54ufpp6F7yTOmeLn3AQJFdoMoAHo94jPra1ltDFFYX5D//Yty8l2D0/sb3b6P94iZkyGLufLYpxOMd6E5XChDO+K4Bl8CEbnjPD65vxRX9ElBiHcfqcswQVAfeAFC+NQ1CmJV3RSVssmw9fQ55gm4nBje2PN1Q4zJx0j134qK3uf5MGpQkCsZd9V8n9rZrgd7VFQbzbyuAenKVhAgMBAAE=" +} diff --git a/rt/src/p2p/id-listener.keyless.json b/rt/src/p2p/id-listener.keyless.json index caa44081..ad64df70 100644 --- a/rt/src/p2p/id-listener.keyless.json +++ b/rt/src/p2p/id-listener.keyless.json @@ -1,3 +1,3 @@ { - "id": "QmQSEt8DBeumRh8ZupmUaW8rVvwnjFtpBE557vjSLccUBh" -} \ No newline at end of file + "id": "QmQSEt8DBeumRh8ZupmUaW8rVvwnjFtpBE557vjSLccUBh" +} diff --git a/rt/src/p2p/id-server.json b/rt/src/p2p/id-server.json index fde9435a..5bfa8950 100644 --- a/rt/src/p2p/id-server.json +++ b/rt/src/p2p/id-server.json @@ -1 +1,5 @@ -{"id":"QmeuSjy8RbeUHpqtDGj2B66fPHxRowuoecZnaVkvhTS7tb","privKey":"CAASpgkwggSiAgEAAoIBAQCdpvRWMcEKDheG9UFL2frLaja8daG+hOjJo3NlmZMSluGQT7WF+wBNBOZUMOZ0siqOdGf3/VwyeW+Dh3WEOTd+xiOLD3qRTvRmj6C5F0kGPw1d+r3vCGZVvudnmW/3EijQsCv9MM2vsrwPe31nlbrE+muj0sRdakS3LJPBeE/j0WtHjU5YbdZWNkOM+doKKeOmr9NZodvkYWFKEO7au6F8qXxIg+oHYAC7LnPwkhhAxJaWFFjdUKtfji1TYqa0MxdQksbZaM7xW3uTwgJ77sLNkzO77nfe98WR/+iGOnu5ExxMAgJUVOcZgrbNh9OUMlt+mR0kcvobxkoQDKXa5Vq/AgMBAAECggEAZEmCgRphbF4OhWGayf++VIwaicRiwemWlD6P9/+72UV18/Fgzfwf8t69Dq2UzINSIxDV2qGndsxdLdSL4zLqpJCyp5GPLMSHIH8ZhOTVJU4S2Mfa7yXuw3kPh43J9eftYuPO99+F2NDgZRDvc2eCSi/rLWm0VKB3WfbXf2ljmM3tzlSYdIdfFPFdnMJtw2IDzjCrnKBzyxXFK/a70Csd1ovuB0rTiR45oAdTlalOyC9VxfgMQPijt1JJJ3yu8y0iYNy7tCKJUYk96tT61CJjJGgdhcpcHKUlkEPvHygBcEOEZ6ox0UDM/DzrtiOH6gcsHnZiIITk5gH9iD+WJ0OSIQKBgQDLKa5tPG42E8qq0JcphiyBks8i00s0lp2gxV+ZEdDJI8R282LgDeOqaZ1R+OnmMjWsVLCR9tXS1ZPvU0NBnfKkwL16S9dYuw7xis2vNPTKDoyn+yjpI5bXc1opoh0MBvd3mOBm00fgrRG878e3URYiekoq/dY7mqGTjSR4pFlO9wKBgQDGpzuF9tlls31mnahrJAOgfTKbGThnDUEtdBn74ah6VlqVoNMcMziBBL4e7YtOv6nieTVjyQ+jxGk8bg1NVgoU6xZfi+vK849W7spDuPZdjpsMt7ijbocl0XazUMihqnzhlRA7mq2DahvFGZnauHMff7fibOpaJl5AuL2SKJ84eQKBgAMrDTtK2/Uf7eMoCZNuMjd7EJvca6nQR3kAWvNKIdVhJ2krdnlD/i7kIr3qgctDMS8UywQbs03sYrgytjPJwMTs9Id5s0wA7sS5g2eeDcsw2uSruAGaunl1pQxNKOLNIQLOcYFo/g/04vftTVIAg7XZ7lopRzP6v1ZLtyvidDoVAoGAfdUmnigL8yDr+Rk6uos4hOtpJ9ek45oAxDL71pJNLxkODiOuNfm3+/muGFct2/cKPHu8tvWAI6NhabboVCmA/1kede1isc7v6AggNR+vZvnS+w5RNazojKsO/mzYeZdNvXK3spm6+Tg4WPRrgaE+wyAasaF+HRaas3KSGkgC+zkCgYAV6t3M867roSRgSSfjStEhHpFMTsXg2Eu3qiIP2o9OI+cByVd8rsi3nTzCh95D4deBweP8SP2m6043mvlLoOhXLK/MGWI4vE5/RgPIze+W6nTQPLQvISxeOj7RJlM3L0rluAhMIjz+2ih8AQ5UBw53XrtVC+wuiMQ093K9CPne/g==","pubKey":"CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdpvRWMcEKDheG9UFL2frLaja8daG+hOjJo3NlmZMSluGQT7WF+wBNBOZUMOZ0siqOdGf3/VwyeW+Dh3WEOTd+xiOLD3qRTvRmj6C5F0kGPw1d+r3vCGZVvudnmW/3EijQsCv9MM2vsrwPe31nlbrE+muj0sRdakS3LJPBeE/j0WtHjU5YbdZWNkOM+doKKeOmr9NZodvkYWFKEO7au6F8qXxIg+oHYAC7LnPwkhhAxJaWFFjdUKtfji1TYqa0MxdQksbZaM7xW3uTwgJ77sLNkzO77nfe98WR/+iGOnu5ExxMAgJUVOcZgrbNh9OUMlt+mR0kcvobxkoQDKXa5Vq/AgMBAAE="} \ No newline at end of file +{ + "id": "QmeuSjy8RbeUHpqtDGj2B66fPHxRowuoecZnaVkvhTS7tb", + "privKey": "CAASpgkwggSiAgEAAoIBAQCdpvRWMcEKDheG9UFL2frLaja8daG+hOjJo3NlmZMSluGQT7WF+wBNBOZUMOZ0siqOdGf3/VwyeW+Dh3WEOTd+xiOLD3qRTvRmj6C5F0kGPw1d+r3vCGZVvudnmW/3EijQsCv9MM2vsrwPe31nlbrE+muj0sRdakS3LJPBeE/j0WtHjU5YbdZWNkOM+doKKeOmr9NZodvkYWFKEO7au6F8qXxIg+oHYAC7LnPwkhhAxJaWFFjdUKtfji1TYqa0MxdQksbZaM7xW3uTwgJ77sLNkzO77nfe98WR/+iGOnu5ExxMAgJUVOcZgrbNh9OUMlt+mR0kcvobxkoQDKXa5Vq/AgMBAAECggEAZEmCgRphbF4OhWGayf++VIwaicRiwemWlD6P9/+72UV18/Fgzfwf8t69Dq2UzINSIxDV2qGndsxdLdSL4zLqpJCyp5GPLMSHIH8ZhOTVJU4S2Mfa7yXuw3kPh43J9eftYuPO99+F2NDgZRDvc2eCSi/rLWm0VKB3WfbXf2ljmM3tzlSYdIdfFPFdnMJtw2IDzjCrnKBzyxXFK/a70Csd1ovuB0rTiR45oAdTlalOyC9VxfgMQPijt1JJJ3yu8y0iYNy7tCKJUYk96tT61CJjJGgdhcpcHKUlkEPvHygBcEOEZ6ox0UDM/DzrtiOH6gcsHnZiIITk5gH9iD+WJ0OSIQKBgQDLKa5tPG42E8qq0JcphiyBks8i00s0lp2gxV+ZEdDJI8R282LgDeOqaZ1R+OnmMjWsVLCR9tXS1ZPvU0NBnfKkwL16S9dYuw7xis2vNPTKDoyn+yjpI5bXc1opoh0MBvd3mOBm00fgrRG878e3URYiekoq/dY7mqGTjSR4pFlO9wKBgQDGpzuF9tlls31mnahrJAOgfTKbGThnDUEtdBn74ah6VlqVoNMcMziBBL4e7YtOv6nieTVjyQ+jxGk8bg1NVgoU6xZfi+vK849W7spDuPZdjpsMt7ijbocl0XazUMihqnzhlRA7mq2DahvFGZnauHMff7fibOpaJl5AuL2SKJ84eQKBgAMrDTtK2/Uf7eMoCZNuMjd7EJvca6nQR3kAWvNKIdVhJ2krdnlD/i7kIr3qgctDMS8UywQbs03sYrgytjPJwMTs9Id5s0wA7sS5g2eeDcsw2uSruAGaunl1pQxNKOLNIQLOcYFo/g/04vftTVIAg7XZ7lopRzP6v1ZLtyvidDoVAoGAfdUmnigL8yDr+Rk6uos4hOtpJ9ek45oAxDL71pJNLxkODiOuNfm3+/muGFct2/cKPHu8tvWAI6NhabboVCmA/1kede1isc7v6AggNR+vZvnS+w5RNazojKsO/mzYeZdNvXK3spm6+Tg4WPRrgaE+wyAasaF+HRaas3KSGkgC+zkCgYAV6t3M867roSRgSSfjStEhHpFMTsXg2Eu3qiIP2o9OI+cByVd8rsi3nTzCh95D4deBweP8SP2m6043mvlLoOhXLK/MGWI4vE5/RgPIze+W6nTQPLQvISxeOj7RJlM3L0rluAhMIjz+2ih8AQ5UBw53XrtVC+wuiMQ093K9CPne/g==", + "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdpvRWMcEKDheG9UFL2frLaja8daG+hOjJo3NlmZMSluGQT7WF+wBNBOZUMOZ0siqOdGf3/VwyeW+Dh3WEOTd+xiOLD3qRTvRmj6C5F0kGPw1d+r3vCGZVvudnmW/3EijQsCv9MM2vsrwPe31nlbrE+muj0sRdakS3LJPBeE/j0WtHjU5YbdZWNkOM+doKKeOmr9NZodvkYWFKEO7au6F8qXxIg+oHYAC7LnPwkhhAxJaWFFjdUKtfji1TYqa0MxdQksbZaM7xW3uTwgJ77sLNkzO77nfe98WR/+iGOnu5ExxMAgJUVOcZgrbNh9OUMlt+mR0kcvobxkoQDKXa5Vq/AgMBAAE=" +} diff --git a/rt/src/p2p/p2p.mts b/rt/src/p2p/p2p.mts index 13bc31a6..d53a1aae 100644 --- a/rt/src/p2p/p2p.mts +++ b/rt/src/p2p/p2p.mts @@ -29,7 +29,7 @@ Additionally, we pipe the connection to a drain sink that does the following: the publishable object from the lookup table. This should ensure that if we we want to communicate with that node later, we will dialing to that node. -The messages themselves can be one of the six forms: +The messages themselves can be one of the six forms: 1. SPAWN -- spawning on a remote node @@ -55,51 +55,51 @@ the libp2p). // IMPORTS -import type { PeerId } from '@libp2p/interface'; -import { getCliArgs, TroupeCliArg } from '../TroupeCliArgs.mjs'; -import { tcp } from '@libp2p/tcp'; -import { webSockets } from '@libp2p/websockets'; -import { mplex } from '@libp2p/mplex'; -import { yamux } from '@chainsafe/libp2p-yamux'; -import { noise } from '@chainsafe/libp2p-noise'; -import defaultsDeep from '@nodeutils/defaults-deep'; -import { Libp2p, createLibp2p as create } from 'libp2p'; -import { keys } from '@libp2p/crypto'; -import { peerIdFromPrivateKey } from '@libp2p/peer-id'; -import { peerIdFromString } from '@libp2p/peer-id'; -import { bootstrap } from '@libp2p/bootstrap'; -import { mdns } from '@libp2p/mdns'; -import { pipe } from 'it-pipe'; -import * as lp from 'it-length-prefixed'; -import map from 'it-map'; -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'; -import { toString as uint8ArrayToString } from 'uint8arrays/to-string'; -import { pushable } from 'it-pushable'; -import p2pconfig, { setCliRelays, getRelays } from './p2pconfig.mjs'; -import { multiaddr } from '@multiformats/multiaddr'; -import { identify } from '@libp2p/identify'; -import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'; -const KEEP_ALIVE = 'KEEP_ALIVE'; // Tag for keeping connections alive -import { Logger } from 'winston'; -import {v4 as uuidv4} from 'uuid'; -import { kadDHT } from '@libp2p/kad-dht'; - -// LOGGING AND DEBUGGING +import type { PeerId } from "@libp2p/interface"; +import { getCliArgs, TroupeCliArg } from "../TroupeCliArgs.mjs"; +import { tcp } from "@libp2p/tcp"; +import { webSockets } from "@libp2p/websockets"; +import { mplex } from "@libp2p/mplex"; +import { yamux } from "@chainsafe/libp2p-yamux"; +import { noise } from "@chainsafe/libp2p-noise"; +import defaultsDeep from "@nodeutils/defaults-deep"; +import { Libp2p, createLibp2p as create } from "libp2p"; +import { keys } from "@libp2p/crypto"; +import { peerIdFromPrivateKey } from "@libp2p/peer-id"; +import { peerIdFromString } from "@libp2p/peer-id"; +import { bootstrap } from "@libp2p/bootstrap"; +import { mdns } from "@libp2p/mdns"; +import { pipe } from "it-pipe"; +import * as lp from "it-length-prefixed"; +import map from "it-map"; +import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; +import { toString as uint8ArrayToString } from "uint8arrays/to-string"; +import { pushable } from "it-pushable"; +import p2pconfig, { setCliRelays, getRelays } from "./p2pconfig.mjs"; +import { multiaddr } from "@multiformats/multiaddr"; +import { identify } from "@libp2p/identify"; +import { circuitRelayTransport } from "@libp2p/circuit-relay-v2"; +const KEEP_ALIVE = "KEEP_ALIVE"; // Tag for keeping connections alive +import { Logger } from "winston"; +import { v4 as uuidv4 } from "uuid"; +import { kadDHT } from "@libp2p/kad-dht"; + +// LOGGING AND DEBUGGING const argv = getCliArgs(); -let logLevel = argv[TroupeCliArg.DebugP2p]? 'debug':'info'; -let __port = argv[TroupeCliArg.Port] || 0; +const logLevel = argv[TroupeCliArg.DebugP2p] ? "debug" : "info"; +const __port = argv[TroupeCliArg.Port] || 0; let logger: Logger; -(async() => { - let { mkLogger } = await import ('../logger.mjs'); - logger = mkLogger ('p2p', logLevel); -})() +(async () => { + const { mkLogger } = await import("../logger.mjs"); + logger = mkLogger("p2p", logLevel); +})(); -const info = x => logger.info(x); -const debug = x => logger.debug(x); -const error = x => logger.error(x); +const info = (x) => logger.info(x); +const debug = (x) => logger.debug(x); +const error = (x) => logger.error(x); // CONSTANTS @@ -113,7 +113,7 @@ const MessageType = { SEND: 2, TEST: 3, WHEREIS: 4, - WHEREISOK: 5 + WHEREISOK: 5, }; // SET-UP @@ -124,12 +124,12 @@ let _rt = null; // The runtime object const bootstrappers = [ // libp2p bootstrap nodes // (from https://github.com/libp2p/js-libp2p/blob/b36ec7f24e477af21cec31effc086a6c611bf271/examples/discovery-mechanisms/README.md?plain=1#L60) - '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt' + "/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", + "/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN", + "/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb", + "/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp", + "/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa", + "/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt", ]; /** @@ -137,7 +137,7 @@ const bootstrappers = [ * Also sets up the event queue block checker and * the connections to relays. */ -async function startp2p(nodeId, rt: any): Promise { +async function startp2p(nodeId, rt: any): Promise { // Set CLI relays if provided const cliRelays = argv[TroupeCliArg.Relay]; if (cliRelays) { @@ -145,29 +145,28 @@ async function startp2p(nodeId, rt: any): Promise { } // Load or create a private key - let privateKey = await obtainPrivateKey(nodeId); + const privateKey = await obtainPrivateKey(nodeId); let id: PeerId; // Create the libp2p node try { - let nodeListener: Libp2p = await createLibp2p({ + const nodeListener: Libp2p = await createLibp2p({ privateKey: privateKey, }); await nodeListener.start(); - + // Save the libp2p node and runtime objects _node = nodeListener; _rt = rt; - + // Get the peer ID from the node id = nodeListener.peerId; - } catch (err) { error(`Something wrong while creating Libp2p node: ${err}`); throw err; } - + // When a peer dials using the Troupe protocol, handle the connection await _node.handle(_PROTOCOL, async ({ connection, stream }) => { debug(`Handling protocol dial from id: ${connection.remotePeer}`); @@ -175,30 +174,30 @@ async function startp2p(nodeId, rt: any): Promise { }); // When a node is discovered, save the address and report it on the debug logger - _node.addEventListener('peer:discovery', async (evt) => { + _node.addEventListener("peer:discovery", async (evt) => { const peerInfo = evt.detail; await _node.peerStore.patch(peerInfo.id, { - multiaddrs: peerInfo.multiaddrs + multiaddrs: peerInfo.multiaddrs, }); debug(`Discovered: ${peerInfo.id.toString()}`); }); // When a node is connected to, report it on the debug logger - _node.addEventListener('peer:connect', (evt) => { + _node.addEventListener("peer:connect", (evt) => { const peerId = evt.detail; debug(`Connection established to: ${peerId.toString()}`); }); // When a node is disconnected from, report it on the debug logger - _node.addEventListener('peer:disconnect', (evt) => { - let id = evt.detail; + _node.addEventListener("peer:disconnect", (evt) => { + const id = evt.detail; debug(`Disconnect from ${id}`); }); - + // When new addresses are added report it on the debug logger - _node.addEventListener('self:peer:update', (_) => { + _node.addEventListener("self:peer:update", (_) => { debug(`Advertising with following addresses:`); - _node.getMultiaddrs().forEach(m => debug(m.toString())); + _node.getMultiaddrs().forEach((m) => debug(m.toString())); }); debug("Libp2p node started"); @@ -225,38 +224,28 @@ async function startp2p(nodeId, rt: any): Promise { async function createLibp2p(_options) { const defaults = { addresses: { - listen: [`/ip4/0.0.0.0/tcp/${__port}`] + listen: [`/ip4/0.0.0.0/tcp/${__port}`], }, - connectionManager : { + connectionManager: { minConnections: 1, maxConnections: Infinity, }, - transports: [ - tcp(), - webSockets(), - circuitRelayTransport({}) - ], - streamMuxers: [ - yamux(), - mplex() - ], - connectionEncrypters: [ - noise(), - ], + transports: [tcp(), webSockets(), circuitRelayTransport({})], + streamMuxers: [yamux(), mplex()], + connectionEncrypters: [noise()], peerDiscovery: [ bootstrap({ - list: bootstrappers + list: bootstrappers, }), mdns(), ], services: { dht: kadDHT({ - clientMode: false, // Run as both client and server - protocol: '/ipfs/kad/1.0.0' + clientMode: false, // Run as both client and server + protocol: "/ipfs/kad/1.0.0", }), identify: identify(), }, - }; return create(defaultsDeep(_options, defaults)); @@ -267,25 +256,27 @@ async function createLibp2p(_options) { * Create it from a protobuf if possible, * otherwise generate a fresh one. */ -async function obtainPrivateKey(nodeId): Promise { +async function obtainPrivateKey(nodeId): Promise { let privateKey: any = null; - if(nodeId && nodeId.privKey) { + if (nodeId?.privKey) { // Load the private key from the nodeId object try { // Convert base64pad private key string to Uint8Array - const privKeyBytes = Uint8Array.from(Buffer.from(nodeId.privKey.trim(), 'base64')); + const privKeyBytes = Uint8Array.from( + Buffer.from(nodeId.privKey.trim(), "base64"), + ); privateKey = await keys.privateKeyFromProtobuf(privKeyBytes); const id = await peerIdFromPrivateKey(privateKey); debug(`Loaded id from file: ${id.toString()}`); } catch (err) { error(`Error creating private key from protobuf: ${err}`); - throw err; + throw err; } } else { // Otherwise create a fresh key pair try { debug("Creating new key pair..."); - privateKey = await keys.generateKeyPair('Ed25519'); + privateKey = await keys.generateKeyPair("Ed25519"); const id = await peerIdFromPrivateKey(privateKey); debug(`Created new id: ${id.toString()}`); } catch (err) { @@ -305,8 +296,8 @@ async function obtainPrivateKey(nodeId): Promise { * Give up if more than 10 attempts have failed. */ function dial(id: PeerId) { - let i = 0; - let timeout = 2000; + let i = 0; + let timeout = 2000; return new Promise((resolve, reject) => { async function tryDialing() { try { @@ -323,12 +314,12 @@ function dial(id: PeerId) { resolve(stream); } catch (err) { - processExpectedNetworkErrors (err, "dial"); + processExpectedNetworkErrors(err, "dial"); // if the error is suppressed we move on to trying 10 times with exponential backoff - // 2020-02-10; AA: TODO: this code has a hardcoded constant - if(i <= 10) { - debug(`Dial failed, we retry in ${timeout/1000} seconds`); + // 2020-02-10; AA: TODO: this code has a hardcoded constant + if (i <= 10) { + debug(`Dial failed, we retry in ${timeout / 1000} seconds`); debug(err); setTimeout(tryDialing, timeout); i++; @@ -336,10 +327,10 @@ function dial(id: PeerId) { } else { error(`Giving up on dialing ${id}: ${err}`); reject(err); - } + } } } - tryDialing(); + tryDialing(); }); } @@ -349,31 +340,29 @@ function dial(id: PeerId) { * peerRouting and using a relay. */ async function getPeerInfo(id: PeerId): Promise { - let knownNodes = p2pconfig.known_nodes; + const knownNodes = p2pconfig.known_nodes; debug(`Checking whether node is already known`); // Check whether the node is known in p2pconfig - for(let ni of knownNodes) { - if(ni.nodeid == id.toString()) { + for (const ni of knownNodes) { + if (ni.nodeid == id.toString()) { // Found a known node! await _node.peerStore.merge(id, { - multiaddrs: [ - multiaddr(`${ni.ip}`) - ] + multiaddrs: [multiaddr(ni.ip)], }); debug(`Node ${ni.nodeid} will be contacted directly via IP: ${ni.ip}`); return; } } - + let usePeerRouting = true; // Check whether the node is known from previously // and has an address - if(await _node.peerStore.has(id)) { + if (await _node.peerStore.has(id)) { try { - let foundPeer = await _node.peerStore.get(id); - if(foundPeer.addresses.length != 0) { + const foundPeer = await _node.peerStore.get(id); + if (foundPeer.addresses.length != 0) { debug("Peer info is in the store"); usePeerRouting = false; } @@ -383,20 +372,22 @@ async function getPeerInfo(id: PeerId): Promise { } } - if(usePeerRouting) { + if (usePeerRouting) { // The node is not known or has no address debug("The node is not known; using peerRouting"); await getPeerInfoWithPeerRouting(id); } - if(_relayId) { + if (_relayId) { // Try to contact the node through a relay // To use several relays, cycle through them and add them all - debug(`Adding circuit relay address for ${id}: /p2p/${_relayId}/p2p-circuit/p2p/${id.toString()}`); + debug( + `Adding circuit relay address for ${id}: /p2p/${_relayId}/p2p-circuit/p2p/${id.toString()}`, + ); await _node.peerStore.merge(id, { multiaddrs: [ - multiaddr(`/p2p/${_relayId}/p2p-circuit/p2p/${id.toString()}`) - ] + multiaddr(`/p2p/${_relayId}/p2p-circuit/p2p/${id.toString()}`), + ], }); } } @@ -405,20 +396,21 @@ async function getPeerInfo(id: PeerId): Promise { * Tries to find an address to use for a node through * peerRouting. Tries six times, then gives up. */ -async function getPeerInfoWithPeerRouting(id: PeerId) : Promise { - return new Promise ((resolve, _) => { +async function getPeerInfoWithPeerRouting(id: PeerId): Promise { + return new Promise((resolve, _) => { let n_attempts = 0; async function tryFindPeer() { try { // Try to find the node, but only spend 1 second on it debug(`Calling peerRouting.findPeer ${id}`); - const peerInfo = await _node.peerRouting.findPeer(id, {signal : AbortSignal.timeout(2000)}); + const peerInfo = await _node.peerRouting.findPeer(id, { + signal: AbortSignal.timeout(2000), + }); debug("findPeer returned"); // Add the found address await _node.peerStore.merge(id, { - multiaddrs: - peerInfo.multiaddrs + multiaddrs: peerInfo.multiaddrs, }); debug("Added multiaddr to store"); @@ -426,8 +418,8 @@ async function getPeerInfoWithPeerRouting(id: PeerId) : Promise { } catch (err) { debug(`tryFindPeer exception`); - if(err instanceof AggregateError) { - for(let e of err.errors) { + if (err instanceof AggregateError) { + for (const e of err.errors) { debug(`Find peer error with code: ${e}, ${e.code}`); } } else { @@ -436,15 +428,17 @@ async function getPeerInfoWithPeerRouting(id: PeerId) : Promise { // Increase the attempts used // Only if the node is connected to the network - if(nPeers() > 0) { + if (nPeers() > 0) { n_attempts++; } // Try six times and then give up - if(n_attempts > 5) { + if (n_attempts > 5) { debug(`Giving up on peerRouting`); resolve(); } else { - debug(`tryFindPeer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`); + debug( + `tryFindPeer: attempt ${n_attempts} failed with ${nPeers()} nodes connected`, + ); setTimeout(tryFindPeer, 500); } } @@ -469,44 +463,46 @@ function nPeers(): number { * passes any input to the input handler. */ function setupConnection(peerId: PeerId, stream): void { - let id: string = peerId.toString(); + const id: string = peerId.toString(); debug(`setupConnection with ${id}`); - const p = pushable({ objectMode : true }); + const p = pushable({ objectMode: true }); // Setup the pipe to send and receive messages - pipe (p, - (source) => map(source, (json) => JSON.stringify(json)), - (source) => map(source, (string : string) => uint8ArrayFromString(string, 'utf8')), - (source) => lp.encode(source), - stream, - (source) => lp.decode(source), - (source) => map(source, (buf) => uint8ArrayToString(buf.subarray())), - (source) => map(source, (string : string) => JSON.parse(string)), - async (source) => { - try { - for await (const message of source) { - // Send any input to the input handler - inputHandler(id, message); - } - } catch (err) { - processExpectedNetworkErrors(err, "setupConnection/pipe"); - } + pipe( + p, + (source) => map(source, (json) => JSON.stringify(json)), + (source) => + map(source, (string: string) => uint8ArrayFromString(string, "utf8")), + (source) => lp.encode(source), + stream, + (source) => lp.decode(source), + (source) => map(source, (buf) => uint8ArrayToString(buf.subarray())), + (source) => map(source, (string: string) => JSON.parse(string)), + async (source) => { + try { + for await (const message of source) { + // Send any input to the input handler + inputHandler(id, message); + } + } catch (err) { + processExpectedNetworkErrors(err, "setupConnection/pipe"); + } - // Hangs up when the connection closes - debug(`Hanging up connection to ${id}`); - try { - await _node.hangUp(peerId); - } catch (err) { - processExpectedNetworkErrors(err, "setupConnection/hang-up"); - } + // Hangs up when the connection closes + debug(`Hanging up connection to ${id}`); + try { + await _node.hangUp(peerId); + } catch (err) { + processExpectedNetworkErrors(err, "setupConnection/hang-up"); + } - // Resends any unacknowledged WHEREIS and SPAWN requests for this peer - reissueUnacknowledged(id); - } + // Resends any unacknowledged WHEREIS and SPAWN requests for this peer + reissueUnacknowledged(id); + }, ); stream.p = p; // Storing a reference to the pushable on the stream - // We rely on the p2p library to keep track of streams + // We rely on the p2p library to keep track of streams debug(`Connection set up with ${id}`); } @@ -524,35 +520,37 @@ function setupConnection(peerId: PeerId, stream): void { async function inputHandler(id, input) { debug("Input handler"); switch (input.messageType) { - case (MessageType.SPAWN): + case MessageType.SPAWN: // Check if spawning is allowed // Drop the message otherwise - if(_rt.remoteSpawnOK()) { + if (_rt.remoteSpawnOK()) { debug("Received SPAWN"); - if(receivedSpawnNonces[input.spawnNonce]) { + if (receivedSpawnNonces[input.spawnNonce]) { // This is an already seen spawn request. // Look up the reply and resend without spawning again - debug("This spawn was already received; replying again without spawning"); - let cachedAnswer = receivedSpawnNonces[input.spawnNonce]; + debug( + "This spawn was already received; replying again without spawning", + ); + const cachedAnswer = receivedSpawnNonces[input.spawnNonce]; // Reply with SPAWNOK and return pushWrap(id, { messageType: MessageType.SPAWNOK, spawnNonce: input.spawnNonce, - message: cachedAnswer + message: cachedAnswer, }); return; } // Inform the runtime - let runtimeAnswer = await _rt.spawnFromRemote(input.message, id); + const runtimeAnswer = await _rt.spawnFromRemote(input.message, id); // Reply with SPAWNOK pushWrap(id, { messageType: MessageType.SPAWNOK, spawnNonce: input.spawnNonce, - message: runtimeAnswer + message: runtimeAnswer, }); debug("SPAWN replied"); @@ -566,12 +564,12 @@ async function inputHandler(id, input) { } break; - case (MessageType.SPAWNOK): + case MessageType.SPAWNOK: debug("Received SPAWN OK"); // Find the call-back and give the message // Otherwise report an error - let _cb = _spawnNonces[input.spawnNonce]; - if(_cb) { + const _cb = _spawnNonces[input.spawnNonce]; + if (_cb) { delete _spawnNonces[input.spawnNonce]; // Clean-up _cb(null, input.message); // null means no errors } else { @@ -579,51 +577,47 @@ async function inputHandler(id, input) { } break; - case (MessageType.SEND): + case MessageType.SEND: debug(`Received SEND from ${id}`); // Pass the message to the runtime - _rt.receiveFromRemote( - input.pid, - input.message, - id - ); + _rt.receiveFromRemote(input.pid, input.message, id); break; - case (MessageType.WHEREIS): + case MessageType.WHEREIS: debug("Received WHEREIS"); // Get the runtime to find the peer - let runtimeAnswer = await _rt.whereisFromRemote(input.message); + const runtimeAnswer = await _rt.whereisFromRemote(input.message); - // Reply with WHEREISOK + // Reply with WHEREISOK pushWrap(id, { - messageType: MessageType.WHEREISOK, - whereisNonce : input.whereisNonce, - message : runtimeAnswer + messageType: MessageType.WHEREISOK, + whereisNonce: input.whereisNonce, + message: runtimeAnswer, }); debug("WHEREIS replied"); - break; - - case (MessageType.WHEREISOK): + break; + + case MessageType.WHEREISOK: debug("Received WHEREISOK"); // Find the call-back and give the message // Otherwise report an error - let _cbw = _whereisNonces[input.whereisNonce]; - if(_cbw) { - delete _whereisNonces [input.whereisNonce]; // Clean-up + const _cbw = _whereisNonces[input.whereisNonce]; + if (_cbw) { + delete _whereisNonces[input.whereisNonce]; // Clean-up _cbw(null, input.message); // null means no errors } else { error("Cannot find WHEREIS callback"); } break; - case (MessageType.TEST): + case MessageType.TEST: debug("Received TEST"); debug(input); break; - + default: - debug(`received data ${input.toString('utf8').replace('\n', '')}`); + debug(`received data ${input.toString("utf8").replace("\n", "")}`); break; } } @@ -640,7 +634,7 @@ let _keepAliveCounter = 0; // The number of times "keep-alive" has been sent to * on the timeout for new tries. */ async function keepAliveRelay(relayAddr: string) { - let id = relayAddr.split('/').pop(); + const id = relayAddr.split("/").pop(); debug(`Relay id is ${id}`); // In circuit relay v2, we just need to dial the relay once @@ -651,7 +645,7 @@ async function keepAliveRelay(relayAddr: string) { } catch (err) { error(`Failed to connect to relay: ${err}`); processExpectedNetworkErrors(err, "relay"); - + // Retry after a delay if connection fails setTimeout(() => keepAliveRelay(relayAddr), 30000); } @@ -665,18 +659,16 @@ async function keepAliveRelay(relayAddr: string) { async function dialRelay(relayAddr: string) { try { debug(`Dialing relay at ${relayAddr}`); - let id = relayAddr.split('/').pop(); + const id = relayAddr.split("/").pop(); const relayId: PeerId = peerIdFromString(id); // Add the address to the peerStore // Tag the relay with "keep alive" await _node.peerStore.merge(relayId, { - multiaddrs: [ - multiaddr(`${relayAddr}`) - ], + multiaddrs: [multiaddr(relayAddr)], tags: { - [KEEP_ALIVE]: {} - } + [KEEP_ALIVE]: {}, + }, }); // Dial the relay - in circuit relay v2, we just dial without a specific protocol @@ -691,7 +683,7 @@ async function dialRelay(relayAddr: string) { // Just return null since we don't have a stream to return return null; } catch (err) { - processExpectedNetworkErrors (err, "dial relay"); + processExpectedNetworkErrors(err, "dial relay"); } } @@ -704,13 +696,13 @@ async function dialRelay(relayAddr: string) { async function sendp2p(id: string, procId, obj) { debug(`sendp2p`); - let data = { + const data = { messageType: MessageType.SEND, pid: procId, - message: obj + message: obj, }; - - let peerId = peerIdFromString(id); + + const peerId = peerIdFromString(id); debug("Pushing SEND message"); pushWrap(peerId, data); } @@ -722,12 +714,12 @@ async function sendp2p(id: string, procId, obj) { * Continues until the data is successfully pushed. */ async function pushWrap(id: PeerId, data: any) { - while(true) { + while (true) { debug(`pushWrap`); - let p = await getPushable(id); - + const p = await getPushable(id); + try { - if(p) { + if (p) { // A pushable has been found, data can be pushed debug(`Stream obtained; pushing`); await p.push(data); @@ -737,34 +729,34 @@ async function pushWrap(id: PeerId, data: any) { debug("Pushable found was null; re-trying"); } } catch (err) { - // The pushable we have used is no good for whatever reason; + // The pushable we have used is no good for whatever reason; // most likely there are networking issues. // We report the errors and redial - processExpectedNetworkErrors(err, "pushWrap"); + processExpectedNetworkErrors(err, "pushWrap"); } } } /** * Finds a pushable to node `id` by checking all - * existing connections with the node. If no + * existing connections with the node. If no * existing pushable is found, then dials the node. */ -async function getPushable(id: PeerId, relayAddr=null) { +async function getPushable(id: PeerId, relayAddr = null) { debug("getPushable"); - let connections = _node.getConnections(id); + const connections = _node.getConnections(id); let needsToDial = true; let p = null; // Runs through all existing connections with the peer // and checks whether their streams have a pushable - for(const connection of connections) { - let streams = connection.streams; - for(const stream of streams) { + for (const connection of connections) { + const streams = connection.streams; + for (const stream of streams) { p = (stream as any).p; - needsToDial = (p == undefined); + needsToDial = p == undefined; - if(!needsToDial) { + if (!needsToDial) { debug("Found existing pushable"); return p; } @@ -772,18 +764,18 @@ async function getPushable(id: PeerId, relayAddr=null) { } // If no pushable was found, dial the peer - if(needsToDial) { + if (needsToDial) { debug("Needs to dial"); let stream = null; - if(relayAddr) { + if (relayAddr) { stream = await dialRelay(relayAddr); } else { stream = await dial(id); } // If the dial fails, the stream is null - if(stream) { + if (stream) { debug("Dialed to obtain stream"); - p = (stream as any).p; + p = stream.p; } else { debug("Could not obtain stream through dial"); } @@ -794,11 +786,11 @@ async function getPushable(id: PeerId, relayAddr=null) { // WHEREIS / SPAWN -let _whereisNonces = {}; // Stores call-backs for WHEREIS requests -let _spawnNonces = {}; // Stores call-backs for SPAWN requests -let receivedSpawnNonces = {}; // Stores received SPAWN nonces and the runtime answer for their reply - // These are stored for 10 minutes in case the SPAWNOK disappeared -let _unacknowledged: any = {}; // Keeps track of unacknowledged WHEREIS and SPAWN requests +const _whereisNonces = {}; // Stores call-backs for WHEREIS requests +const _spawnNonces = {}; // Stores call-backs for SPAWN requests +const receivedSpawnNonces = {}; // Stores received SPAWN nonces and the runtime answer for their reply +// These are stored for 10 minutes in case the SPAWNOK disappeared +const _unacknowledged: any = {}; // Keeps track of unacknowledged WHEREIS and SPAWN requests /** * Handles a where-is request of peer `id`. @@ -810,31 +802,31 @@ async function whereisp2p(id: string, data: any) { debug("whereisp2p"); // Create a nonce - let whereisNonce = uuidv4(); + const whereisNonce = uuidv4(); function sendMessage() { - let peerId = peerIdFromString(id); + const peerId = peerIdFromString(id); pushWrap(peerId, { - messageType : MessageType.WHEREIS, - whereisNonce : whereisNonce, - message : data + messageType: MessageType.WHEREIS, + whereisNonce: whereisNonce, + message: data, }); } // Set the WHEREIS request as unacknowledged addUnacknowledged(id.toString(), whereisNonce, sendMessage); - + return new Promise((resolve, reject) => { // Return the error or result when an answer comes in _whereisNonces[whereisNonce] = (err, result) => { - if(err) { + if (err) { reject(err); } else { // Only remove the unacknowledged status if the request succeeds removeUnacknowledged(id.toString(), whereisNonce); resolve(result); - } - } + } + }; // Push the WHEREIS message debug("Pushing WHEREIS message"); @@ -849,26 +841,26 @@ async function whereisp2p(id: string, data: any) { */ async function spawnp2p(id: string, data: any) { debug("spawnp2p"); - + // Create a nonce const spawnNonce = uuidv4(); function sendMessage() { - let peerId = peerIdFromString(id); + const peerId = peerIdFromString(id); pushWrap(peerId, { - messageType : MessageType.SPAWN, - spawnNonce : spawnNonce, - message : data + messageType: MessageType.SPAWN, + spawnNonce: spawnNonce, + message: data, }); } // Set the SPAWN request as unacknowledged addUnacknowledged(id.toString(), spawnNonce, sendMessage); - return new Promise ((resolve, reject) => { + return new Promise((resolve, reject) => { // Return the error or result when an answer comes in _spawnNonces[spawnNonce] = (err, result) => { - if(err) { + if (err) { reject(err); } else { // Only remove the unacknowledged status if the request succeeds @@ -888,7 +880,7 @@ async function spawnp2p(id: string, data: any) { * WHEREIS request for `id` with nonce `uuid`. */ function addUnacknowledged(id: string, uuid, f) { - if(!_unacknowledged[id]) { + if (!_unacknowledged[id]) { _unacknowledged[id] = []; } _unacknowledged[id][uuid] = f; @@ -906,7 +898,7 @@ function removeUnacknowledged(id: string, uuid) { * Rerun all unacknowledged WHEREIS requests for `id`. */ function reissueUnacknowledged(id: string) { - for(let uuid in _unacknowledged[id]) { + for (const uuid in _unacknowledged[id]) { setImmediate(_unacknowledged[id][uuid]); } } @@ -919,31 +911,31 @@ function reissueUnacknowledged(id: string) { * If it takes much longer than that before the check runs, * this is reported, since it indicates blocking. */ -function setupBlockingHealthChecker(period: number) { - let lastHealth: number = Date.now(); - let healthCounter = 0; - let healthThreshold = Math.max(period * 1.25 , period + 50); - // AA: 2020-02-10; - // The event queue always has a fair bit of latency, so we adjust for - // the minimal expected latency here; the constant of 50 is an - // empirically derived value, but needs to be critically reevaluated - // as the system evolves - - function checkBlocking() { - let now = Date.now() - // check and report if it has been too long since the last health check - // this could indicate that something is the event queue - if(now - lastHealth > healthThreshold) { - debug(`Potential blocking issue`); - debug(`Health check ${healthCounter} took this long ${now - lastHealth}`); - } - lastHealth = now; - healthCounter++; - - // Run the check periodically - setTimeout(checkBlocking, period); +function setupBlockingHealthChecker(period: number) { + let lastHealth: number = Date.now(); + let healthCounter = 0; + const healthThreshold = Math.max(period * 1.25, period + 50); + // AA: 2020-02-10; + // The event queue always has a fair bit of latency, so we adjust for + // the minimal expected latency here; the constant of 50 is an + // empirically derived value, but needs to be critically reevaluated + // as the system evolves + + function checkBlocking() { + const now = Date.now(); + // check and report if it has been too long since the last health check + // this could indicate that something is the event queue + if (now - lastHealth > healthThreshold) { + debug(`Potential blocking issue`); + debug(`Health check ${healthCounter} took this long ${now - lastHealth}`); } - checkBlocking(); + lastHealth = now; + healthCounter++; + + // Run the check periodically + setTimeout(checkBlocking, period); + } + checkBlocking(); } // ERROR HANDLING @@ -953,95 +945,95 @@ function setupBlockingHealthChecker(period: number) { * Any known errors are reported. * Any unknown errors are reported and thrown. */ -function processExpectedNetworkErrors(err, source="unknown") { - debug(`Error source: ${source}`); - if(err instanceof AggregateError) { - for(const e of err.errors ) { - processExpectedNetworkErrors (e, source) +function processExpectedNetworkErrors(err, source = "unknown") { + debug(`Error source: ${source}`); + if (err instanceof AggregateError) { + for (const e of err.errors) { + processExpectedNetworkErrors(e, source); + } + } else { + if (err.name || err.code) { + const errorId = err.name || err.code; + switch (errorId) { + case "NetworkUnreachableError": + case "ENETUNREACH": + debug(`${err.toString()}`); + break; + case "NotFoundError": + case "ENOTFOUND": + debug(`${err.toString()}`); + break; + case "ConnectionResetError": + case "ECONNRESET": + debug(`${err.toString()}`); + break; + case "TransportDialFailedError": + case "ERR_TRANSPORT_DIAL_FAILED": + debug(`${err.toString()}`); + break; + case "AbortError": + case "ABORT_ERR": + debug(`${err.toString()}`); + break; + case "ConnectionRefusedError": + case "ECONNREFUSED": + debug(`${err.toString()}`); + break; + case "HopRequestFailedError": + case "ERR_HOP_REQUEST_FAILED": + debug(`${err.toString()}`); + break; + case "NoDialMultiaddrsError": + case "ERR_NO_DIAL_MULTIADDRS": + debug(`${err.toString()}`); + break; + case "EncryptionFailedError": + case "ERR_ENCRYPTION_FAILED": + debug(`${err.toString()}`); + break; + case "NoValidAddressesError": + case "ERR_NO_VALID_ADDRESSES": + debug(`${err.toString()}`); + break; + case "StreamResetError": + case "ERR_MPLEX_STREAM_RESET": + debug(`${err.toString()}`); + break; + case "TimeoutError": + case "ERR_TIMEOUT": + debug(`${err.toString()}`); + break; + + default: + error(`Unhandled error case with error identifier ${errorId}`); + throw err; } } else { - if(err.name || err.code) { - const errorId = err.name || err.code; - switch (errorId) { - case 'NetworkUnreachableError': - case 'ENETUNREACH': - debug(`${err.toString()}`) - break; - case 'NotFoundError': - case 'ENOTFOUND': - debug(`${err.toString()}`) - break; - case 'ConnectionResetError': - case 'ECONNRESET': - debug(`${err.toString()}`) - break; - case 'TransportDialFailedError': - case 'ERR_TRANSPORT_DIAL_FAILED': - debug(`${err.toString()}`) - break; - case 'AbortError': - case 'ABORT_ERR': - debug(`${err.toString()}`) - break; - case 'ConnectionRefusedError': - case 'ECONNREFUSED': - debug(`${err.toString()}`) - break; - case 'HopRequestFailedError': - case 'ERR_HOP_REQUEST_FAILED': - debug(`${err.toString()}`) - break; - case 'NoDialMultiaddrsError': - case 'ERR_NO_DIAL_MULTIADDRS': - debug(`${err.toString()}`) - break; - case 'EncryptionFailedError': - case 'ERR_ENCRYPTION_FAILED': - debug(`${err.toString()}`) - break; - case 'NoValidAddressesError': - case 'ERR_NO_VALID_ADDRESSES': - debug(`${err.toString()}`) - break; - case 'StreamResetError': - case 'ERR_MPLEX_STREAM_RESET': - debug(`${err.toString()}`) - break; - case 'TimeoutError': - case 'ERR_TIMEOUT': - debug(`${err.toString()}`); - break; - - default: - error(`Unhandled error case with error identifier ${errorId}`) - throw err; - } - } else { - error(`Unhandled general error case ${err}`) - throw err; - } - } + error(`Unhandled general error case ${err}`); + throw err; + } + } } // INTERFACE -export let p2p = { +export const p2p = { startp2p: (arg1, arg2) => { - return startp2p(arg1, arg2) + return startp2p(arg1, arg2); }, spawnp2p: (arg1, arg2) => { - return spawnp2p(arg1, arg2) + return spawnp2p(arg1, arg2); }, sendp2p: (arg1, arg2, arg3) => { - return sendp2p(arg1, arg2, arg3) + return sendp2p(arg1, arg2, arg3); }, whereisp2p: (arg1, arg2) => { - return whereisp2p(arg1, arg2) + return whereisp2p(arg1, arg2); }, stopp2p: async () => { - return await _node.stop() + await _node.stop(); }, processExpectedNetworkErrors: (arg1, arg2) => { - return processExpectedNetworkErrors(arg1, arg2) - }, -} + processExpectedNetworkErrors(arg1, arg2); + }, +}; diff --git a/rt/src/p2p/p2pconfig.mjs b/rt/src/p2p/p2pconfig.mjs index 49837b28..b815eb7d 100644 --- a/rt/src/p2p/p2pconfig.mjs +++ b/rt/src/p2p/p2pconfig.mjs @@ -1,54 +1,86 @@ -'use strict' -const P2PCONFIG_FILE = 'p2pconfig.json' +"use strict"; +const P2PCONFIG_FILE = "p2pconfig.json"; let logger; -(async() => { - let { mkLogger } = await import ('../logger.mjs'); - logger = mkLogger ('p2p-config','info'); -})() - -import { existsSync, readFileSync } from 'fs'; -let relays +(async () => { + let { mkLogger } = await import("../logger.mjs"); + logger = mkLogger("p2p-config", "info"); +})(); +import { existsSync, readFileSync } from "fs"; +let relays; // TODO: change the relay address to be the actual address let default_relays = // ["/dns4/relay.troupe-lang.net/tcp/5555/p2p/QmcQpBNGULxRC3QmvxVGXSw8BarpMvdADYvFtmvKAL5QMe"] // TODO: dns resolution of the relay has stopped working - ["/ip4/134.209.92.133/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf"] - -let known_nodes = [ - {nodeid:"QmXfj4ysaS4pARJU5uUP59B47aCQP6X6FH6cm5otLhcMPa", ip: "/ip4/134.209.90.7/tcp/6789"}, + [ + "/ip4/134.209.92.133/tcp/5555/ws/p2p/12D3KooWShh9qmeS1UEgwWpjAsrjsigu8UGh8DRKyx1UG6HeHzjf", + ]; +let known_nodes = [ + { + nodeid: "QmXfj4ysaS4pARJU5uUP59B47aCQP6X6FH6cm5otLhcMPa", + ip: "/ip4/134.209.90.7/tcp/6789", + }, - {nodeid:"QmNUiTnU1J5rNFtGXUfZJzSmx2GahSFCPjeSfSTbGoAR4q", ip: "/ip4/142.93.235.197/tcp/6789"}, - {nodeid:"QmW3oruhRQEuZXCtFWUEwE6DT1WyvifcR6YYtBEK6QTsMo", ip: "/ip4/167.71.68.246/tcp/6789"}, - {nodeid:"QmYHExHtTzFEjdwyQcJkD9gaKKgfwvGswoFb4simrJn5Q6", ip: "/ip4/188.166.69.210/tcp/6789"}, - {nodeid:"QmcRfB3SJp92t7GMgS5rygXuSDPm7q31GeAdP8q9HutyYT", ip: "/ip4/128.199.61.30/tcp/6789"}, - {nodeid:"QmSyj7FUykAhog46qDekYKjWDF4Y4PhPbP2hDkEmwz679b", ip: "/ip4/142.93.234.253/tcp/6789"}, - {nodeid:"QmS9tkoqKEPrfgsGMhqQgNT1pcZjCq1XRonUiR9uXEoj9e", ip: "/ip4/188.166.70.113/tcp/6789"}, - {nodeid:"QmYVDakQNvBhVCHeu1JCHJYc2sG1ESBwC3PB1vNzAFJWbH", ip: "/ip4/128.199.41.250/tcp/6789"}, - {nodeid:"QmX2edVZhWVa9Q6gbpwNZJGXqeLgcAvAYTga2m25dwWudH", ip: "/ip4/188.166.70.132/tcp/6789"}, - {nodeid:"QmbkpnNgD8uu9FArPPyzYUYuuVZtCo7n3jQ5Rz2nqiZEWD", ip: "/ip4/167.71.76.8/tcp/6789"}, - {nodeid:"QmYFdcq31Gnch87kkqFjWt5R1GH8jTPNspz5XxBzC6hJ1r", ip: "/ip4/104.248.86.46/tcp/6789"} -] - + { + nodeid: "QmNUiTnU1J5rNFtGXUfZJzSmx2GahSFCPjeSfSTbGoAR4q", + ip: "/ip4/142.93.235.197/tcp/6789", + }, + { + nodeid: "QmW3oruhRQEuZXCtFWUEwE6DT1WyvifcR6YYtBEK6QTsMo", + ip: "/ip4/167.71.68.246/tcp/6789", + }, + { + nodeid: "QmYHExHtTzFEjdwyQcJkD9gaKKgfwvGswoFb4simrJn5Q6", + ip: "/ip4/188.166.69.210/tcp/6789", + }, + { + nodeid: "QmcRfB3SJp92t7GMgS5rygXuSDPm7q31GeAdP8q9HutyYT", + ip: "/ip4/128.199.61.30/tcp/6789", + }, + { + nodeid: "QmSyj7FUykAhog46qDekYKjWDF4Y4PhPbP2hDkEmwz679b", + ip: "/ip4/142.93.234.253/tcp/6789", + }, + { + nodeid: "QmS9tkoqKEPrfgsGMhqQgNT1pcZjCq1XRonUiR9uXEoj9e", + ip: "/ip4/188.166.70.113/tcp/6789", + }, + { + nodeid: "QmYVDakQNvBhVCHeu1JCHJYc2sG1ESBwC3PB1vNzAFJWbH", + ip: "/ip4/128.199.41.250/tcp/6789", + }, + { + nodeid: "QmX2edVZhWVa9Q6gbpwNZJGXqeLgcAvAYTga2m25dwWudH", + ip: "/ip4/188.166.70.132/tcp/6789", + }, + { + nodeid: "QmbkpnNgD8uu9FArPPyzYUYuuVZtCo7n3jQ5Rz2nqiZEWD", + ip: "/ip4/167.71.76.8/tcp/6789", + }, + { + nodeid: "QmYFdcq31Gnch87kkqFjWt5R1GH8jTPNspz5XxBzC6hJ1r", + ip: "/ip4/104.248.86.46/tcp/6789", + }, +]; if (existsSync(P2PCONFIG_FILE)) { try { - let s = readFileSync(P2PCONFIG_FILE) - let o = JSON.parse (s); - console.log (o.relays) - if (o.relays) { - relays = o.relays + let s = readFileSync(P2PCONFIG_FILE); + let o = JSON.parse(s); + console.log(o.relays); + if (o.relays) { + relays = o.relays; } else { - throw new Error ("relays field undefined") + throw new Error("relays field undefined"); } } catch (err) { - logger.error ("error parsing p2p configuration file") - relays = default_relays + logger.error("error parsing p2p configuration file"); + relays = default_relays; } } else { - relays = default_relays + relays = default_relays; } let cliRelays = null; @@ -56,7 +88,9 @@ let cliRelays = null; export function setCliRelays(relayAddresses) { if (relayAddresses && relayAddresses.length > 0) { cliRelays = relayAddresses; - logger?.info(`Using CLI-provided relay addresses: ${relayAddresses.join(', ')}`); + logger?.info( + `Using CLI-provided relay addresses: ${relayAddresses.join(", ")}`, + ); } } @@ -69,4 +103,4 @@ export function getRelays() { return relays; } -export default { relays: getRelays(), known_nodes, setCliRelays, getRelays } +export default { relays: getRelays(), known_nodes, setCliRelays, getRelays }; diff --git a/rt/src/process.mts b/rt/src/process.mts index 29dcb710..f4ce9942 100644 --- a/rt/src/process.mts +++ b/rt/src/process.mts @@ -1,39 +1,38 @@ import { TroupeRawValue } from "./TroupeRawValue.mjs"; import { TroupeType } from "./TroupeTypes.mjs"; -import { BOT } from './Level.mjs' +import { BOT } from "./Level.mjs"; -export function pid_equals (o1, o2) { - let eq = o1.val.pid.toString() == o2.val.pid.toString(); - //console.log("pid eq", o1, o2, eq); - return (eq); - } +export function pid_equals(o1, o2) { + const eq = o1.val.pid.toString() == o2.val.pid.toString(); + //console.log("pid eq", o1, o2, eq); + return eq; +} -export function pid_val_equals (v1, v2) { - let eq = v1.pid.toString() == v2.pid.toString(); +export function pid_val_equals(v1, v2) { + const eq = v1.pid.toString() == v2.pid.toString(); return eq; -} - -export class ProcessID implements TroupeRawValue { - _troupeType = TroupeType.PROCESS_ID - uuid: any; - pid: any; - node: any; - stringRep: () => string; - equals: (o1: any, o2: any) => boolean; - dataLevel = BOT - constructor(rt_uuid, pid, node) { - this.uuid = rt_uuid; - this.pid = pid; - this.node = node ; // getLocalNode(); - this.stringRep = ProcessID.toString; - this.equals = pid_equals; - this.stringRep = this.toString; - } - - toString () { - let x = this.pid.toString(); - // console.log (x); - return x; - } } +export class ProcessID implements TroupeRawValue { + _troupeType = TroupeType.PROCESS_ID; + uuid: any; + pid: any; + node: any; + stringRep: () => string; + equals: (o1: any, o2: any) => boolean; + dataLevel = BOT; + constructor(rt_uuid, pid, node) { + this.uuid = rt_uuid; + this.pid = pid; + this.node = node; // getLocalNode(); + this.stringRep = ProcessID.toString; + this.equals = pid_equals; + this.stringRep = this.toString; + } + + toString() { + const x = this.pid.toString(); + // console.log (x); + return x; + } +} diff --git a/rt/src/runId.mts b/rt/src/runId.mts index 0dbb125f..7c123422 100644 --- a/rt/src/runId.mts +++ b/rt/src/runId.mts @@ -1,3 +1,3 @@ -import { v4 as uuidv4} from 'uuid' -let runId = uuidv4() -export default runId +import { v4 as uuidv4 } from "uuid"; +const runId = uuidv4(); +export default runId; diff --git a/rt/src/runtimeMonitored.mts b/rt/src/runtimeMonitored.mts index 1c54578c..f669917b 100644 --- a/rt/src/runtimeMonitored.mts +++ b/rt/src/runtimeMonitored.mts @@ -1,86 +1,88 @@ -import * as fs from 'node:fs'; -import chalk from 'chalk'; -import { v4 as uuidv4 } from 'uuid' -import AggregateError from 'aggregate-error'; -import { __unit } from './UnitVal.mjs' -import { Authority } from './Authority.mjs' -import { Scheduler } from './Scheduler.mjs' -import { MailboxProcessor } from './MailboxProcessor.mjs' -import { RuntimeInterface } from './RuntimeInterface.mjs' -import { LVal, MbVal } from './Lval.mjs' -import { ProcessID } from './process.mjs'; -import { UserRuntime } from './UserRuntime.mjs' -import * as levels from './Level.mjs' -import * as DS from './deserialize.mjs' -import { p2p } from './p2p/p2p.mjs' -import { closeReadline } from './builtins/stdio.mjs'; -import { __theRegister } from './builtins/whereis.mjs'; -import { assertIsFunction } from './Asserts.mjs' -import runId from './runId.mjs' -import { __nodeManager } from './NodeManager.mjs' -import { setRuntimeObject } from './SysState.mjs'; -import { initTrustMap, nodeTrustLevel, _trustMap } from './TrustManager.mjs'; -import { serialize } from './serialize.mjs'; -import { Thread } from './Thread.mjs'; - -import { Console } from 'node:console' - -const { flowsTo, lub, glb } = levels -import { getCliArgs, TroupeCliArg } from './TroupeCliArgs.mjs'; -import { configureColors, isColorEnabled } from './colorConfig.mjs'; -import { mkLogger } from './logger.mjs' -import { Record } from './Record.mjs'; -import { level } from 'winston'; - -const readFile = fs.promises.readFile -const rt_uuid = runId +import * as fs from "node:fs"; +import chalk from "chalk"; +import { v4 as uuidv4 } from "uuid"; +import AggregateError from "aggregate-error"; +import { __unit } from "./UnitVal.mjs"; +import { Authority } from "./Authority.mjs"; +import { Scheduler } from "./Scheduler.mjs"; +import { MailboxProcessor } from "./MailboxProcessor.mjs"; +import { RuntimeInterface } from "./RuntimeInterface.mjs"; +import { LVal, MbVal } from "./Lval.mjs"; +import { ProcessID } from "./process.mjs"; +import { UserRuntime } from "./UserRuntime.mjs"; +import * as levels from "./Level.mjs"; +import * as DS from "./deserialize.mjs"; +import { p2p } from "./p2p/p2p.mjs"; +import { closeReadline } from "./builtins/stdio.mjs"; +import { __theRegister } from "./builtins/whereis.mjs"; +import { assertIsFunction } from "./Asserts.mjs"; +import runId from "./runId.mjs"; +import { __nodeManager } from "./NodeManager.mjs"; +import { setRuntimeObject } from "./SysState.mjs"; +import { initTrustMap, nodeTrustLevel, _trustMap } from "./TrustManager.mjs"; +import { serialize } from "./serialize.mjs"; +import { Thread } from "./Thread.mjs"; + +import { Console } from "node:console"; + +const { flowsTo, lub, glb } = levels; +import { getCliArgs, TroupeCliArg } from "./TroupeCliArgs.mjs"; +import { configureColors, isColorEnabled } from "./colorConfig.mjs"; +import { mkLogger } from "./logger.mjs"; +import { Record } from "./Record.mjs"; +import { level } from "winston"; + +const readFile = fs.promises.readFile; +const rt_uuid = runId; const argv = getCliArgs(); // Configure colors before any chalk or logger usage configureColors(); -let logLevel = argv[TroupeCliArg.Debug] ? 'debug': 'info' -const logger = mkLogger('RTM', logLevel); +const logLevel = argv[TroupeCliArg.Debug] ? "debug" : "info"; +const logger = mkLogger("RTM", logLevel); -const info = x => logger.info(x) -const debug = x => logger.debug(x) -const error = x => logger.error(x) +const info = (x) => logger.info(x); +const debug = (x) => logger.debug(x); +const error = (x) => logger.error(x); let __p2pRunning = false; +const rt_xconsole = new Console({ + stdout: process.stdout, + stderr: process.stderr, + colorMode: isColorEnabled(), +}); -let rt_xconsole = - new Console({ stdout: process.stdout - , stderr: process.stderr - , colorMode: isColorEnabled() - }); - -function $t():Thread { return __sched.__currentThread }; // returns the current thread +function $t(): Thread { + return __sched.__currentThread; +} // returns the current thread // -------------------------------------------------- async function spawnAtNode(nodeid, f) { - debug (`* rt spawnAtNode ${nodeid}`); - let node = __nodeManager.getNode(nodeid.val); + debug(`* rt spawnAtNode ${nodeid}`); + const node = __nodeManager.getNode(nodeid.val); // debug ("XX", node); // TODO: 2018-09-24: AA: do the information flow check - let { data, level } = serialize(f, lub($t().pc, nodeid.lev)); + const { data, level } = serialize(f, lub($t().pc, nodeid.lev)); - let trustLevel = nodeTrustLevel(node.nodeId); - let theThread = $t(); + const trustLevel = nodeTrustLevel(node.nodeId); + const theThread = $t(); if (!flowsTo(level, trustLevel)) { - theThread.throwInSuspended("Illegal trust flow when spawning on a remote node\n" + - ` | the trust level of the recepient node: ${trustLevel.stringRep()}\n` + - ` | the level of the information in spawn: ${level.stringRep()}`) - __sched.scheduleThread(theThread); - __sched.resumeLoopAsync(); - return; + theThread.throwInSuspended( + "Illegal trust flow when spawning on a remote node\n" + + ` | the trust level of the recepient node: ${trustLevel.stringRep()}\n` + + ` | the level of the information in spawn: ${level.stringRep()}`, + ); + __sched.scheduleThread(theThread); + __sched.resumeLoopAsync(); + return; } - // 0. we assume that the node is different from // the local node @@ -90,35 +92,31 @@ async function spawnAtNode(nodeid, f) { // 4. we return the obtained pid //-------------------------------------------------- - - try { - let body1 = await p2p.spawnp2p(node.nodeId, data); - let body = await DS.deserialize(nodeTrustLevel(node.nodeId), body1) - let pid = new ProcessID(body.val.uuid, body.val.pid, body.val.node); + const body1 = await p2p.spawnp2p(node.nodeId, data); + const body = await DS.deserialize(nodeTrustLevel(node.nodeId), body1); + const pid = new ProcessID(body.val.uuid, body.val.pid, body.val.node); theThread.returnSuspended(new LVal(pid, body.lev)); __sched.scheduleThread(theThread); __sched.resumeLoopAsync(); - } catch (err) { - error("error spawning remotely; this blocks current thread") + error("error spawning remotely; this blocks current thread"); if (err instanceof AggregateError) { - for (let ie in err) { - error(`${ie}`) + for (const ie in err) { + error(ie); } } else { - error(`${err}`) + error(`${err}`); } } } -let _allowRemoteSpawn = argv[TroupeCliArg.RSpawn]; +const _allowRemoteSpawn = argv[TroupeCliArg.RSpawn]; function remoteSpawnOK() { return _allowRemoteSpawn; } - /** * * This function is invoked when someone spawns a thread @@ -136,32 +134,30 @@ function remoteSpawnOK() { * The identity of the node that initiates the spawning. */ async function spawnFromRemote(jsonObj, fromNode) { - debug ("spawn from remote") + debug("spawn from remote"); // 2018-05-17: AA; note that this _only_ uses the lf.lev and // is completely independent of the current thread's pc; - let nodeLev = nodeTrustLevel(fromNode); + const nodeLev = nodeTrustLevel(fromNode); - let lf = await DS.deserialize(nodeLev, jsonObj) - let f = lf.val; - let newPid = - __sched.scheduleNewThreadAtLevel( - f - , __unit //[f.env, __unit] - // , f.namespace - , lf.lev - , lf.lev - ); + const lf = await DS.deserialize(nodeLev, jsonObj); + const f = lf.val; + const newPid = __sched.scheduleNewThreadAtLevel( + f, + __unit, //[f.env, __unit] + // , f.namespace + lf.lev, + lf.lev, + ); // 2018-09-19: AA: because we need to send some info back, we have to invoke // serialization. - let serObj = serialize(newPid, levels.BOT).data + const serObj = serialize(newPid, levels.BOT).data; __sched.resumeLoopAsync(); - return (serObj); + return serObj; } - /** * This function is called when someone sends us a message. * @@ -173,21 +169,22 @@ async function spawnFromRemote(jsonObj, fromNode) { * The node identity of the sender node */ async function receiveFromRemote(pid, jsonObj, fromNode) { - debug(`* rt receiveFromremote * ${JSON.stringify(jsonObj)}`) - let data = await DS.deserialize(nodeTrustLevel(fromNode), jsonObj) + debug(`* rt receiveFromremote * ${JSON.stringify(jsonObj)}`); + const data = await DS.deserialize(nodeTrustLevel(fromNode), jsonObj); debug(`* rt receiveFromremote * ${fromNode} ${data.stringRep()}`); // TODO: 2018-07-23: do we need to do some more raising // about the level of the fromNode?; AA - let fromNodeId = __sched.mkVal(fromNode); - let toPid = new LVal(new ProcessID(rt_uuid, pid, __nodeManager.getLocalNode()), data.lev); + const fromNodeId = __sched.mkVal(fromNode); + const toPid = new LVal( + new ProcessID(rt_uuid, pid, __nodeManager.getLocalNode()), + data.lev, + ); __theMailbox.addMessage(fromNodeId, toPid, data.val, data.lev); __sched.resumeLoopAsync(); - } - /** * Sends the provided mesasge to a remote process, first doing the information * flow check that the remote process is not going to violate our trust @@ -198,62 +195,61 @@ async function receiveFromRemote(pid, jsonObj, fromNode) { * */ function sendMessageToRemote(toPid, message) { - let node = toPid.node.nodeId; - let pid = toPid.pid; - // debug (`* rt * ${toPid} ${message.stringRep()}`); + const node = toPid.node.nodeId; + const pid = toPid.pid; + // debug (`* rt * ${toPid} ${message.stringRep()}`); - let { data, level } = serialize(new MbVal(message, $t().pc), $t().pc); + const { data, level } = serialize(new MbVal(message, $t().pc), $t().pc); // debug (`* rt * ${JSON.stringify(data)}`); - let trustLevel = nodeTrustLevel(node); + const trustLevel = nodeTrustLevel(node); // debug ("data level: " + level.stringRep()); // debug ("remote trust level: " + trustLevel.stringRep()); if (!flowsTo(level, trustLevel)) { - threadError("Illegal trust flow when sending information to a remote node\n" + - ` | the trust level of the recepient node: ${trustLevel.stringRep()}\n` + - ` | the level of the information to send: ${level.stringRep()}`); + threadError( + "Illegal trust flow when sending information to a remote node\n" + + ` | the trust level of the recepient node: ${trustLevel.stringRep()}\n` + + ` | the level of the information to send: ${level.stringRep()}`, + ); } else { - p2p.sendp2p(node, pid, data) - return $t().returnImmediateLValue(__unit); // we return unit to the call site at the thread level + p2p.sendp2p(node, pid, data); + return $t().returnImmediateLValue(__unit); // we return unit to the call site at the thread level } } // TODO: AA; 2020-05-19; consider moving these two functions somewhere else function isLocalPid(pid) { - let x = pid.uuid.toString() == rt_uuid.toString(); - return (x); + const x = pid.uuid.toString() == rt_uuid.toString(); + return x; } function rt_mkuuid() { - let pid = uuidv4(); - let uuidval = $t().mkVal(pid); + const pid = uuidv4(); + const uuidval = $t().mkVal(pid); return uuidval; } function rt_sendMessageNochecks(lRecipientPid, message, ret = true) { - let recipientPid = lRecipientPid.val; + const recipientPid = lRecipientPid.val; // debug (`rt_sendMessageNoChecks ${message.stringRep()}`) if (isLocalPid(recipientPid)) { - let nodeId = __sched.mkVal(__nodeManager.getNodeId()); + const nodeId = __sched.mkVal(__nodeManager.getNodeId()); __theMailbox.addMessage(nodeId, lRecipientPid, message, $t().pc); if (ret) { - return $t().returnImmediateLValue(__unit); + return $t().returnImmediateLValue(__unit); } } else { - debug ("* rt rt_send remote *"/*, recipientPid, message*/); - return sendMessageToRemote(recipientPid, message) + debug("* rt rt_send remote *" /*, recipientPid, message*/); + return sendMessageToRemote(recipientPid, message); } } - - - -let rt_debug = function (s) { +const rt_debug = function (s) { function formatToN(s, n) { if (s.length < n) { let j = s.length; @@ -264,65 +260,57 @@ let rt_debug = function (s) { return s; } - let tid = $t().tidErrorStringRep() - let pc = $t().pc.stringRep() - let bl = $t().bl.stringRep() - let handler_state = __sched.handlerState.toString() + const tid = $t().tidErrorStringRep(); + const pc = $t().pc.stringRep(); + const bl = $t().bl.stringRep(); + const handler_state = __sched.handlerState.toString(); rt_xconsole.log( chalk.red(formatToN("PID:" + tid, 50)), chalk.red(formatToN("PC:" + pc, 20)), chalk.red(formatToN("BL:" + bl, 20)), chalk.red(formatToN("HN" + handler_state, 20)), chalk.red(formatToN("_sp:" + $t()._sp, 20)), - s + s, ); -} - - +}; async function whereisFromRemote(k) { - __sched.resumeLoopAsync() + __sched.resumeLoopAsync(); // TODO: 2018-10-20: make use of the levels as they were // recorded during the registration (instead of the bottom here ) if (__theRegister[k]) { - let serObj = serialize(__theRegister[k], levels.BOT).data - return serObj + const serObj = serialize(__theRegister[k], levels.BOT).data; + return serObj; } } - - function rt_mkLabel(x) { // debug ("mkLabel", x, x === "secret"); - return new LVal(levels.fromSingleTag(x), $t().pc); - } - - - function threadError(s, internal = false) { - return $t().threadError(s, internal); + $t().threadError(s, internal); } -let rt_threadError = threadError; +const rt_threadError = threadError; function rt_error(x) { threadError(x.val); } function rt_errorPos(x, pos) { - if (pos != '') { + if (pos != "") { threadError(x.val + " at " + pos); } else { threadError(x.val); } } - -let rt_ret = (arg) => { return $t().returnImmediateLValue(arg); } +const rt_ret = (arg) => { + return $t().returnImmediateLValue(arg); +}; // let rt_ret_raw = () => __sched.returnInThread_raw(); // function tailcall(lff, arg) { @@ -331,80 +319,75 @@ let rt_ret = (arg) => { return $t().returnImmediateLValue(arg); } // __sched.tailToTroupeFun(lff.val, arg); // } -let __sched: Scheduler -let __theMailbox: MailboxProcessor -let __userRuntime: any -let __service:any = {} +let __sched: Scheduler; +let __theMailbox: MailboxProcessor; +let __userRuntime: any; +const __service: any = {}; class RuntimeObject implements RuntimeInterface { // tailcall = tailcall - xconsole = rt_xconsole - ret = rt_ret - // ret_raw = rt_ret_raw - debug = rt_debug - spawnAtNode = spawnAtNode - rt_mkuuid = rt_mkuuid - mkLabel = rt_mkLabel + xconsole = rt_xconsole; + ret = rt_ret; + // ret_raw = rt_ret_raw + debug = rt_debug; + spawnAtNode = spawnAtNode; + rt_mkuuid = rt_mkuuid; + mkLabel = rt_mkLabel; sendMessageNoChecks = rt_sendMessageNochecks; - cleanup = cleanupAsync + cleanup = cleanupAsync; persist(obj, path) { - let jsonObj = serialize(obj, $t().pc).data; + const jsonObj = serialize(obj, $t().pc).data; fs.writeFileSync(path, JSON.stringify(jsonObj)); } - get $service () { - return __service + get $service() { + return __service; } - + get $t() { - return $t() + return $t(); } get __sched() { - return __sched + return __sched; } get __mbox() { - return __theMailbox + return __theMailbox; } get __userRuntime() { - return __userRuntime + return __userRuntime; } constructor() { - __sched = new Scheduler(this) - __theMailbox = new MailboxProcessor(this) - __userRuntime = new UserRuntime(this) + __sched = new Scheduler(this); + __theMailbox = new MailboxProcessor(this); + __userRuntime = new UserRuntime(this); } - } - -let __rtObj = new RuntimeObject(); +const __rtObj = new RuntimeObject(); DS.setRuntimeObj(__rtObj.__userRuntime); -setRuntimeObject(__rtObj) - - +setRuntimeObject(__rtObj); async function cleanupAsync() { - closeReadline() + closeReadline(); DS.stopCompiler(); if (__p2pRunning) { try { - debug("stopping p2p") - await p2p.stopp2p() - debug("p2p stop OK") + debug("stopping p2p"); + await p2p.stopp2p(); + debug("p2p stop OK"); } catch (err) { - debug(`p2p stop failed ${err}`) + debug(`p2p stop failed ${err}`); } } } - // 2020-02-09; AA; ugly ugly hack function bulletProofSigint() { - let listeners = process.listeners("SIGINT"); + const listeners = process.listeners("SIGINT"); // console.log (util.inspect(listeners)) // for (let i = 0; i < listeners.length; i ++ ) { // console.log (listeners[i].toString()); @@ -413,123 +396,134 @@ function bulletProofSigint() { // process.stdin.removeAllListeners("on"); process.removeAllListeners("SIGINT"); // console.log ("sigint bulletproofing") - process.on('SIGINT', () => { + process.on("SIGINT", () => { debug("SIGINT"); (async () => { - await cleanupAsync() + await cleanupAsync(); process.exit(0); - })() - }) + })(); + }); // setTimeout (bulletProofSigint, 1000) } bulletProofSigint(); - - async function loadServiceCode() { - let input = await fs.promises.readFile(process.env.TROUPE + '/trp-rt/out/service.js', 'utf8') - let S: any = new Function('rt', input) - let service = new S(__userRuntime); + const input = await fs.promises.readFile( + process.env.TROUPE + "/trp-rt/out/service.js", + "utf8", + ); + const S: any = new Function("rt", input); + const service = new S(__userRuntime); - await __userRuntime.linkLibs(service) + await __userRuntime.linkLibs(service); - __userRuntime.setLibloadMode() - let table = service.export({__dataLevel:levels.BOT}).val.toArray() - __userRuntime.setNormalMode() + __userRuntime.setLibloadMode(); + const table = service.export({ __dataLevel: levels.BOT }).val.toArray(); + __userRuntime.setNormalMode(); for (let i = 0; i < table.length; i++) { - let name = table[i].val[0].val - let ff = table[i].val[1].val - __service[name] = ff + const name = table[i].val[0].val; + const ff = table[i].val[1].val; + __service[name] = ff; } } - - async function getNetworkPeerId(rtHandlers) { - const nodeIdFile = argv[TroupeCliArg.Id] as string; + const nodeIdFile = argv[TroupeCliArg.Id]; if (nodeIdFile) { try { - let nodeIdObj = await readFile(nodeIdFile, 'utf-8') - process.on('unhandledRejection', (e) => p2p.processExpectedNetworkErrors(e, "unhandledRejection")) + const nodeIdObj = await readFile(nodeIdFile, "utf-8"); + process.on("unhandledRejection", (e) => { + p2p.processExpectedNetworkErrors(e, "unhandledRejection"); + }); // process.on ('unhandledRejection', up => {console.log ("Unhandled rejection"); console.error (up)}) // process.on ('uncaughtException', up => {console.log ("Uncaught exception"); console.error (up)}) - process.on('uncaughtException', (e) => p2p.processExpectedNetworkErrors(e, "uncaughtException")) + process.on("uncaughtException", (e) => { + p2p.processExpectedNetworkErrors(e, "uncaughtException"); + }); return await p2p.startp2p(JSON.parse(nodeIdObj), rtHandlers); } catch (err) { - logger.error("cannot load id file") + logger.error("cannot load id file"); process.exit(1); } } else { try { if (argv[TroupeCliArg.LocalOnly] || argv[TroupeCliArg.Persist]) { - info("Skipping network creation. Observe that all external IO operations will yield a runtime error.") + info( + "Skipping network creation. Observe that all external IO operations will yield a runtime error.", + ); if (argv[TroupeCliArg.Persist]) { - info("Running with persist flag.") + info("Running with persist flag."); } - return null// OBS: 2018-07-22: we are jumping over the network creation + return null; // OBS: 2018-07-22: we are jumping over the network creation } else { return await p2p.startp2p(null, rtHandlers); } } catch (err) { - logger.error("uncaught exception in the runtime") - console.error(err.stack);; + logger.error("uncaught exception in the runtime"); + console.error(err.stack); process.exit(1); } } } export async function start(f) { - await initTrustMap() + await initTrustMap(); - let peerid = await getNetworkPeerId({ + const peerid = await getNetworkPeerId({ remoteSpawnOK, spawnFromRemote, receiveFromRemote, - whereisFromRemote - }) + whereisFromRemote, + }); if (peerid) { - __p2pRunning = true - debug("network ready") + __p2pRunning = true; + debug("network ready"); } else { - debug("network not initialized") + debug("network not initialized"); } __nodeManager.setLocalPeerId(peerid); - let stopWhenAllThreadsAreDone = !__p2pRunning - __sched.initScheduler(__nodeManager.getLocalNode() - , stopWhenAllThreadsAreDone - , cleanupAsync); + const stopWhenAllThreadsAreDone = !__p2pRunning; + __sched.initScheduler( + __nodeManager.getLocalNode(), + stopWhenAllThreadsAreDone, + cleanupAsync, + ); - await loadServiceCode() - await __userRuntime.linkLibs(f) - let mainAuthority = new LVal(new Authority(levels.ROOT), levels.BOT); + await loadServiceCode(); + await __userRuntime.linkLibs(f); + const mainAuthority = new LVal(new Authority(levels.ROOT), levels.BOT); if (__p2pRunning) { - let service_arg = - new LVal ( new Record([ ["authority", mainAuthority], - ["options", __unit]]), - levels.BOT); - __sched.scheduleNewThreadAtLevel(__service['service'] - , service_arg - , levels.TOP - , levels.BOT - , false - , null - , true); + const service_arg = new LVal( + new Record([ + ["authority", mainAuthority], + ["options", __unit], + ]), + levels.BOT, + ); + __sched.scheduleNewThreadAtLevel( + __service.service, + service_arg, + levels.TOP, + levels.BOT, + false, + null, + true, + ); } __sched.scheduleNewThreadAtLevel( - () => f.main ({__dataLevel:levels.BOT}) - , mainAuthority + () => f.main({ __dataLevel: levels.BOT }), + mainAuthority, // , f - , levels.BOT - , levels.BOT - , true - , argv[TroupeCliArg.Persist] - ) - __sched.loop() + levels.BOT, + levels.BOT, + true, + argv[TroupeCliArg.Persist], + ); + __sched.loop(); } - diff --git a/rt/src/serialize.mts b/rt/src/serialize.mts index 75c9ee77..258e552c 100644 --- a/rt/src/serialize.mts +++ b/rt/src/serialize.mts @@ -1,4 +1,4 @@ -'use strict' +"use strict"; /* ..######..########.########..####....###....##.......####.########....###....########.####..#######..##....## .##....##.##.......##.....##..##....##.##...##........##.......##....##.##......##.....##..##.....##.###...## @@ -9,204 +9,200 @@ ..######..########.##.....##.####.##.....##.########.####.########.##.....##....##....####..#######..##....## */ -import assert from 'assert' -import { lub } from './Level.mjs'; -import * as Ty from './TroupeTypes.mjs' -import { LVal } from './Lval.mjs'; -import { Level } from './Level.mjs'; -import { StopThreadError, ThreadError } from './TroupeError.mjs'; -import { getRuntimeObject } from './SysState.mjs'; +import assert from "assert"; +import { lub } from "./Level.mjs"; +import * as Ty from "./TroupeTypes.mjs"; +import { LVal } from "./Lval.mjs"; +import { Level } from "./Level.mjs"; +import { StopThreadError, ThreadError } from "./TroupeError.mjs"; +import { getRuntimeObject } from "./SysState.mjs"; -import { getCliArgs, TroupeCliArg } from './TroupeCliArgs.mjs'; +import { getCliArgs, TroupeCliArg } from "./TroupeCliArgs.mjs"; const argv = getCliArgs(); -let logLevel = argv[TroupeCliArg.Debug] ? 'debug': 'info' -import { mkLogger } from './logger.mjs' -const logger = mkLogger('SRL', logLevel); -const debug = x => logger.debug(x) - +const logLevel = argv[TroupeCliArg.Debug] ? "debug" : "info"; +import { mkLogger } from "./logger.mjs"; +const logger = mkLogger("SRL", logLevel); +const debug = (x) => logger.debug(x); export class UnserializableObjectError extends StopThreadError { - obj: LVal - get errorMessage () { - return (`Unserializable object: ${this.obj.stringRep()}`); - // TODO: 2021-06-12: improve error reporting - // - indicate what the current type of this object is - // - and explain why it is the case that it isn't serializable - } - - constructor (obj:LVal) { - super (getRuntimeObject().$t) ; - this.obj = obj - } + obj: LVal; + get errorMessage() { + return `Unserializable object: ${this.obj.stringRep()}`; + // TODO: 2021-06-12: improve error reporting + // - indicate what the current type of this object is + // - and explain why it is the case that it isn't serializable + } + + constructor(obj: LVal) { + super(getRuntimeObject().$t); + this.obj = obj; + } } +export function serialize(w: LVal, pclev: Level) { + const seenNamespaces = new Map(); + const seenClosures = new Map(); + const seenEnvs = new Map(); -export function serialize(w:LVal, pclev:Level) { - let seenNamespaces = new Map(); - let seenClosures = new Map(); - let seenEnvs = new Map(); - - let namespaces = []; - let closures = []; - let envs = []; - + const namespaces = []; + const closures = []; + const envs = []; - let level = pclev; + let level = pclev; - function walk(lval:LVal) { - assert(Ty.isLVal(lval)); + function walk(lval: LVal) { + assert(Ty.isLVal(lval)); - level = lub(level, lval.lev); // 2018-09-24: AA: is this the only place - // where we need to check the level of the message? + level = lub(level, lval.lev); // 2018-09-24: AA: is this the only place + // where we need to check the level of the message? - let jsonObj; - let x = lval.val; - + let jsonObj; + const x = lval.val; + const _tt = lval.troupeType; - let _tt = lval.troupeType - - - - - switch (_tt) { - case Ty.TroupeType.RECORD: - jsonObj = []; - for (let [k,v] of x.__obj.entries()) { - jsonObj.push ([k, walk(v)]) - } - break; - case Ty.TroupeType.LIST: - jsonObj = []; - let y = x.toArray() - - for (let i = 0; i < y.length; i++) { - jsonObj.push(walk(y[i])); - } - break; - case Ty.TroupeType.TUPLE: - jsonObj = []; - for (let i = 0; i < x.length; i++) { - jsonObj.push(walk(x[i])); - } - break; - case Ty.TroupeType.CLOSURE: - if (!Ty.isSerializableClosure (lval.closureType)) { - throw new UnserializableObjectError (lval) - } - - if (seenClosures.has(x)) { // debuglog ("pointer to [existing] heap object", seen.get(x)) - jsonObj = { ClosureID: seenClosures.get(x) }; - } else { - jsonObj = { ClosureID: closures.length } - seenClosures.set(x, closures.length); - let jsonClosure: any = {}; - closures.push(jsonClosure); - - let jsonEnvPtr; - if (seenEnvs.has(x.env)) { - jsonEnvPtr = { EnvID: seenEnvs.get(x.env) } - } else { - jsonEnvPtr = { EnvID: envs.length }; - seenEnvs.set(x.eqnv, envs.length) - let jsonEnv = {}; - envs.push(jsonEnv); - - for (let field in x.env) { - if (field != "ret" && field != "_is_rt_env" && field != "__dataLevel") { - let y = x.env[field]; - jsonEnv[field] = walk(y); - } - } - } - - jsonClosure.envptr = jsonEnvPtr; - // debug (`the namespace is ${x.namespace}`); - for (let ff in x.namespace) { - // debug (`the function in the namespace is ${ff.toString()}`) - if (x.namespace[ff] == x.fun) { - let jsonNamespacePtr; - let namespace; - if (seenNamespaces.has(x.namespace)) { - let n_id = seenNamespaces.get(x.namespace); - jsonNamespacePtr = { NamespaceID: n_id }; - namespace = namespaces[n_id]; - } else { - jsonNamespacePtr = { NamespaceID: namespaces.length }; - seenNamespaces.set(x.namespace, namespaces.length); - namespace = new Map(); - namespaces.push(namespace); - } - - namespace.set(ff, x.fun.serialized) - - function dfs(deps) { - for (let depName of deps) { - if (!namespace.has(depName)) { - namespace.set(depName, x.namespace[depName].serialized); - dfs(x.namespace[depName].deps); - } - } - } - - dfs(x.fun.deps); - - jsonClosure.namespacePtr = jsonNamespacePtr; - jsonClosure.fun = ff; - } - } - } - break; - case Ty.TroupeType.LEVEL: - jsonObj = { lev: x.toJSON(), isLevel: true }; - break; - case Ty.TroupeType.LVAL: - jsonObj = walk(x); - break; - case Ty.TroupeType.AUTHORITY: - jsonObj = { authorityLevel: x.authorityLevel.toJSON() } - break; - case Ty.TroupeType.ATOM: - jsonObj = { atom: x.atom, creation_uuid: x.creation_uuid }; - break; - case Ty.TroupeType.LOCALOBJECT: - throw new UnserializableObjectError (lval) - default: - jsonObj = x; + switch (_tt) { + case Ty.TroupeType.RECORD: + jsonObj = []; + for (const [k, v] of x.__obj.entries()) { + jsonObj.push([k, walk(v)]); } + break; + case Ty.TroupeType.LIST: + jsonObj = []; + const y = x.toArray(); - // OBS: we are moving away from LVal representation - // to a more explicit tuple that is different on purpose - // from LVal. 2018-09-20: AA; We should ideally encapsulate - // that in a different class with a name that reflects that - // this is a transport-level representation. - - return { - val: jsonObj - , lev: lval.lev.toJSON() - , tlev: lval.tlev.toJSON() - , troupeType: _tt - }; - } + for (let i = 0; i < y.length; i++) { + jsonObj.push(walk(y[i])); + } + break; + case Ty.TroupeType.TUPLE: + jsonObj = []; + for (let i = 0; i < x.length; i++) { + jsonObj.push(walk(x[i])); + } + break; + case Ty.TroupeType.CLOSURE: + if (!Ty.isSerializableClosure(lval.closureType)) { + throw new UnserializableObjectError(lval); + } - let value = walk(w); - value.lev = lub(w.lev, pclev).toJSON(); + if (seenClosures.has(x)) { + // debuglog ("pointer to [existing] heap object", seen.get(x)) + jsonObj = { ClosureID: seenClosures.get(x) }; + } else { + jsonObj = { ClosureID: closures.length }; + seenClosures.set(x, closures.length); + const jsonClosure: any = {}; + closures.push(jsonClosure); + + let jsonEnvPtr; + if (seenEnvs.has(x.env)) { + jsonEnvPtr = { EnvID: seenEnvs.get(x.env) }; + } else { + jsonEnvPtr = { EnvID: envs.length }; + seenEnvs.set(x.eqnv, envs.length); + const jsonEnv = {}; + envs.push(jsonEnv); + + for (const field in x.env) { + if ( + field != "ret" && + field != "_is_rt_env" && + field != "__dataLevel" + ) { + const y = x.env[field]; + jsonEnv[field] = walk(y); + } + } + } + + jsonClosure.envptr = jsonEnvPtr; + // debug (`the namespace is ${x.namespace}`); + for (const ff in x.namespace) { + // debug (`the function in the namespace is ${ff.toString()}`) + if (x.namespace[ff] == x.fun) { + let jsonNamespacePtr; + let namespace; + if (seenNamespaces.has(x.namespace)) { + const n_id = seenNamespaces.get(x.namespace); + jsonNamespacePtr = { NamespaceID: n_id }; + namespace = namespaces[n_id]; + } else { + jsonNamespacePtr = { NamespaceID: namespaces.length }; + seenNamespaces.set(x.namespace, namespaces.length); + namespace = new Map(); + namespaces.push(namespace); + } + + namespace.set(ff, x.fun.serialized); + + function dfs(deps) { + for (const depName of deps) { + if (!namespace.has(depName)) { + namespace.set(depName, x.namespace[depName].serialized); + dfs(x.namespace[depName].deps); + } + } + } + dfs(x.fun.deps); - let nsp = []; - for (let j = 0; j < namespaces.length; j++) { - nsp.push(Array.from(namespaces[j])); + jsonClosure.namespacePtr = jsonNamespacePtr; + jsonClosure.fun = ff; + } + } + } + break; + case Ty.TroupeType.LEVEL: + jsonObj = { lev: x.toJSON(), isLevel: true }; + break; + case Ty.TroupeType.LVAL: + jsonObj = walk(x); + break; + case Ty.TroupeType.AUTHORITY: + jsonObj = { authorityLevel: x.authorityLevel.toJSON() }; + break; + case Ty.TroupeType.ATOM: + jsonObj = { atom: x.atom, creation_uuid: x.creation_uuid }; + break; + case Ty.TroupeType.LOCALOBJECT: + throw new UnserializableObjectError(lval); + default: + jsonObj = x; } - let serializeObj = { - libdeps: [] - , namespaces: nsp - , closures: closures - , envs: envs - , value: value + // OBS: we are moving away from LVal representation + // to a more explicit tuple that is different on purpose + // from LVal. 2018-09-20: AA; We should ideally encapsulate + // that in a different class with a name that reflects that + // this is a transport-level representation. + + return { + val: jsonObj, + lev: lval.lev.toJSON(), + tlev: lval.tlev.toJSON(), + troupeType: _tt, }; - - // TODO: propagate the level; - return { data: serializeObj, level: level } + } + + const value = walk(w); + value.lev = lub(w.lev, pclev).toJSON(); + + const nsp = []; + for (let j = 0; j < namespaces.length; j++) { + nsp.push(Array.from(namespaces[j])); + } + + const serializeObj = { + libdeps: [], + namespaces: nsp, + closures: closures, + envs: envs, + value: value, + }; + + // TODO: propagate the level; + return { data: serializeObj, level: level }; } diff --git a/rt/src/troupe.mts b/rt/src/troupe.mts index 981ac8c6..8322c899 100644 --- a/rt/src/troupe.mts +++ b/rt/src/troupe.mts @@ -1,28 +1,26 @@ -import { start } from './runtimeMonitored.mjs'; -import { getRuntimeObject } from './SysState.mjs'; -import path from 'path'; -import fs from 'node:fs' -import { getCliArgs, TroupeCliArg } from './TroupeCliArgs.mjs'; +import { start } from "./runtimeMonitored.mjs"; +import { getRuntimeObject } from "./SysState.mjs"; +import path from "path"; +import fs from "node:fs"; +import { getCliArgs, TroupeCliArg } from "./TroupeCliArgs.mjs"; const argv = getCliArgs(); -let p:any = argv[TroupeCliArg.File]; +let p: any = argv[TroupeCliArg.File]; if (!p) { - console.error("Error: -f/--file argument is required."); - process.exit(1); + console.error("Error: -f/--file argument is required."); + process.exit(1); } if (!path.isAbsolute(p)) { - p = path.normalize(process.cwd() + "/" + p); + p = path.normalize(process.cwd() + "/" + p); } if (!fs.existsSync(p)) { - console.error(`Cannot find file ${p}`); - process.exit(1); + console.error(`Cannot find file ${p}`); + process.exit(1); } (async () => { - let d = await import (p); - let Top = d.default - let __userRuntime = (getRuntimeObject() as any).__userRuntime; - let top = new Top(__userRuntime); - start(top); - -}) () - + const d = await import(p); + const Top = d.default; + const __userRuntime = (getRuntimeObject() as any).__userRuntime; + const top = new Top(__userRuntime); + start(top); +})();